build 3.2.0
diff --git a/bin/add-license.js b/bin/add-license.js deleted file mode 100755 index cda0eaa..0000000 --- a/bin/add-license.js +++ /dev/null
@@ -1,61 +0,0 @@ -#!/usr/bin/env node - -// prepend a license to the beginning of all the output files - -'use strict'; - -var version = require('../package.json').version; -var fs = require('fs'); - -/* jshint maxlen:100 */ -var comments = { - - 'pouchdb': 'PouchDB ' + version + - '\n' + - '\n(c) 2012-2014 Dale Harvey and the PouchDB team' + - '\nPouchDB may be freely distributed under the Apache license, version 2.0.' + - '\nFor all details and documentation:' + - '\nhttp://pouchdb.com', - - 'pouchdb.idb-alt': 'PouchDB alternative IndexedDB plugin ' + version + - '\nBased on level.js: https://github.com/maxogden/level.js' + - '\n' + - '\n(c) 2012-2014 Dale Harvey and the PouchDB team' + - '\nPouchDB may be freely distributed under the Apache license, version 2.0.' + - '\nFor all details and documentation:' + - '\nhttp://pouchdb.com', - - 'pouchdb.memory': 'PouchDB in-memory plugin ' + version + - '\nBased on MemDOWN: https://github.com/rvagg/memdown' + - '\n' + - '\n(c) 2012-2014 Dale Harvey and the PouchDB team' + - '\nPouchDB may be freely distributed under the Apache license, version 2.0.' + - '\nFor all details and documentation:' + - '\nhttp://pouchdb.com', - - 'pouchdb.localstorage': 'PouchDB localStorage plugin ' + version + - '\nBased on localstorage-down: https://github.com/No9/localstorage-down' + - '\n' + - '\n(c) 2012-2014 Dale Harvey and the PouchDB team' + - '\nPouchDB may be freely distributed under the Apache license, version 2.0.' + - '\nFor all details and documentation:' + - '\nhttp://pouchdb.com' -}; - -Object.keys(comments).forEach(function (name) { - var comment = comments[name]; - comment = comment.replace(/(^|\n)/g, '$1// '); - - var filenames = [name + '.js', name + '.min.js']; - - filenames.forEach(function (filename) { - filename = './dist/' + filename; - var contents = fs.readFileSync(filename); - contents = comment + '\n' + contents; - - fs.writeFileSync(filename, contents); - }); -}); - - -
diff --git a/bin/build-all-plugins.sh b/bin/build-all-plugins.sh deleted file mode 100755 index b5c28a6..0000000 --- a/bin/build-all-plugins.sh +++ /dev/null
@@ -1,19 +0,0 @@ -#!/bin/sh - -LEVEL_BACKEND=memdown \ - OUTPUT_FILENAME=pouchdb.memory.js \ - ./bin/build-plugin.sh - -LEVEL_BACKEND=localstorage-down \ - OUTPUT_FILENAME=pouchdb.localstorage.js \ - ./bin/build-plugin.sh - -LEVEL_BACKEND=level-js \ - OUTPUT_FILENAME=pouchdb.idb-alt.js \ - ./bin/build-plugin.sh - -UGLIFY=./node_modules/uglify-js/bin/uglifyjs - -$UGLIFY dist/pouchdb.memory.js -mc > dist/pouchdb.memory.min.js -$UGLIFY dist/pouchdb.localstorage.js -mc > dist/pouchdb.localstorage.min.js -$UGLIFY dist/pouchdb.idb-alt.js -mc > dist/pouchdb.idb-alt.min.js \ No newline at end of file
diff --git a/bin/build-plugin.sh b/bin/build-plugin.sh deleted file mode 100755 index fda2de0..0000000 --- a/bin/build-plugin.sh +++ /dev/null
@@ -1,20 +0,0 @@ -#!/bin/bash - -if [ -z "$LEVEL_BACKEND" ]; then - echo "Error: must specify LEVEL_BACKEND parameter." - exit 1 -fi - -if [ -z "$OUTPUT_FILENAME" ]; then - echo "Error: must specify OUTPUT_FILENAME parameter." - exit 1 -fi -DEREQUIRE=./node_modules/.bin/derequire - -./node_modules/.bin/browserify lib/plugins/index.js \ - -r $LEVEL_BACKEND:leveldown \ - -x pouchdb \ - -r ./lib/plugins/config-$LEVEL_BACKEND.js:adapter-config \ - -r ./lib/plugins/migrate-browser.js:./lib/deps/migrate \ - -r ./lib/plugins/migrate-browser.js:./lib/deps/migrate \ - | $DEREQUIRE > ./dist/$OUTPUT_FILENAME
diff --git a/bin/build-site.js b/bin/build-site.js deleted file mode 100755 index 69a62a2..0000000 --- a/bin/build-site.js +++ /dev/null
@@ -1,52 +0,0 @@ -#!/usr/bin/env node - -'use strict'; - -var fs = require('fs'); - -var http_server = require('http-server'); -var execSync = require('exec-sync'); -var mkdirp = require('mkdirp'); -var watchGlob = require('watch-glob'); - -var POUCHDB_CSS = __dirname + '/../docs/static/css/pouchdb.css'; -var POUCHDB_LESS = __dirname + '/../docs/static/less/pouchdb/pouchdb.less'; - -if (!execSync('gem list jekyll -i')) { - console.log('Install Jekyll'); - process.exit(1); -} - -mkdirp.sync(__dirname + '/../docs/static/css'); - -function buildCSS() { - var css = - execSync(__dirname + '/../node_modules/less/bin/lessc ' + POUCHDB_LESS); - fs.writeFileSync(POUCHDB_CSS, css); - console.log('Updated: ', POUCHDB_CSS); -} - -if (!process.env.BUILD) { - watchGlob('docs/static/less/*/*.less', buildCSS); -} -buildCSS(); - -process.chdir('docs'); - -function buildJekyll(path) { - // Dont rebuild on website artifacts being written - if (path && /^_site/.test(path.relative)) { - return; - } - execSync('jekyll build'); - console.log('=> Rebuilt jekyll'); -} - -if (!process.env.BUILD) { - watchGlob('**', buildJekyll); - buildJekyll(); - http_server.createServer({root: '_site', cache: '-1'}).listen(4000); - console.log('Server address: http://0.0.0.0:4000'); -} else { - execSync('jekyll build'); -}
diff --git a/bin/dev-server.js b/bin/dev-server.js deleted file mode 100755 index 883441b..0000000 --- a/bin/dev-server.js +++ /dev/null
@@ -1,130 +0,0 @@ -#!/usr/bin/env node - -'use strict'; - -var fs = require('fs'); -var Promise = require('bluebird'); -var through = require('through2'); -var _derequire = require('derequire'); -var watchify = require('watchify'); -var browserify = require('browserify'); -var cors_proxy = require('corsproxy'); -var http_proxy = require('pouchdb-http-proxy'); -var http_server = require('http-server'); - -function derequire() { - var out = new Buffer(''); - return through(function (data, _, next) { - out = Buffer.concat([out, data]); - next(); - }, function (next) { - this.push(_derequire(out.toString())); - next(); - }); -} -var queryParams = {}; - -if (process.env.ES5_SHIM || process.env.ES5_SHIMS) { - queryParams.es5shim = true; -} -if (process.env.ADAPTERS) { - queryParams.adapters = process.env.ADAPTERS; -} -if (process.env.AUTO_COMPACTION) { - queryParams.autoCompaction = true; -} - -var indexfile = "./lib/index.js"; -var outfile = "./dist/pouchdb.js"; -var perfRoot = './tests/performance/'; -var performanceBundle = './tests/performance-bundle.js'; - -var w = watchify(browserify(indexfile, { - standalone: "PouchDB", - cache: {}, - packageCache: {}, - fullPaths: true -})).on('update', bundle); -var b = watchify(browserify({ - entries: perfRoot, - cache: {}, - packageCache: {}, - fullPaths: true - })).on('update', bundlePerfTests); - -function bundle(callback) { - w.bundle().pipe(derequire()).pipe(fs.createWriteStream(outfile)) - .on('finish', function () { - console.log('Updated: ', outfile); - if (typeof callback === 'function') { - callback(); - } - }); -} - -function bundlePerfTests(callback) { - - b.bundle().pipe(fs.createWriteStream(performanceBundle)) - .on('finish', function () { - console.log('Updated: ', performanceBundle); - if (typeof callback === 'function') { - callback(); - } - }); - -} - -var filesWritten = false; -Promise.all([ - new Promise(function (resolve) { - bundle(resolve); - }), - new Promise(function (resolve) { - bundlePerfTests(resolve); - }) -]).then(function () { - filesWritten = true; - checkReady(); -}); - -var COUCH_HOST = process.env.COUCH_HOST || 'http://127.0.0.1:5984'; - -var HTTP_PORT = 8000; -var CORS_PORT = 2020; - -var serversStarted; -var readyCallback; - -function startServers(callback) { - readyCallback = callback; - http_server.createServer().listen(HTTP_PORT, function () { - cors_proxy.options = {target: COUCH_HOST}; - http_proxy.createServer(cors_proxy).listen(CORS_PORT, function () { - var testRoot = 'http://127.0.0.1:' + HTTP_PORT; - var query = ''; - Object.keys(queryParams).forEach(function (key) { - query += (query ? '&' : '?'); - query += key + '=' + encodeURIComponent(queryParams[key]); - }); - console.log('Integration tests: ' + testRoot + - '/tests/integration/' + query); - console.log('Performance tests: ' + testRoot + - '/tests/performance/'); - serversStarted = true; - checkReady(); - }); - }); -} - -function checkReady() { - if (filesWritten && serversStarted && readyCallback) { - readyCallback(); - } -} - - -if (require.main === module) { - startServers(); -} else { - module.exports.start = startServers; -}
diff --git a/bin/get-version.js b/bin/get-version.js deleted file mode 100755 index 500cf45..0000000 --- a/bin/get-version.js +++ /dev/null
@@ -1,8 +0,0 @@ -#!/usr/bin/env node -'use strict'; -var version = require('../package.json').version; -var fs = require('fs'); -var file = 'module.exports = "' + version + '";\n'; -fs.writeFileSync('./lib/version-browser.js', file, { - encoding: 'utf8' -});
diff --git a/bin/publish-site.sh b/bin/publish-site.sh deleted file mode 100755 index 12e84a0..0000000 --- a/bin/publish-site.sh +++ /dev/null
@@ -1,8 +0,0 @@ -#!/bin/bash - -# Build the website -BUILD=1 npm run build-site - -# Push the site live, requires credentials, open a bug -# if you need to be able to push the site -scp -r docs/_site/* pouchdb@pouchdb.com:/home/pouchdb/www/pouchdb.com/
diff --git a/bin/release.sh b/bin/release.sh deleted file mode 100755 index 21ddc59..0000000 --- a/bin/release.sh +++ /dev/null
@@ -1,31 +0,0 @@ -#!/bin/bash - -#make sure deps are up to date -rm -r node_modules -npm install - -# get current version -VERSION=$(node --eval "console.log(require('./package.json').version);") - -# Build -git checkout -b build - -npm run build - -# Publish npm release with tests/scripts/goodies -npm publish - -# Create git tag, which is also the Bower/Github release -git add dist -f -git add bower.json component.json package.json lib/version-browser.js -git rm -r bin docs scripts tests vendor - -git commit -m "build $VERSION" - -# Tag and push -git tag $VERSION -git push --tags git@github.com:pouchdb/pouchdb.git $VERSION - -# Cleanup -git checkout master -git branch -D build
diff --git a/bin/repl.js b/bin/repl.js deleted file mode 100755 index c7cbe28..0000000 --- a/bin/repl.js +++ /dev/null
@@ -1,101 +0,0 @@ -#!/usr/bin/env node -'use strict'; - -var repl = require("repl"); -var utils = require('../lib/utils'); -var prompt = '> '; -var _toPromise = utils.toPromise; // Backup old toPromise method - -function truncate(string, length) { - if (!string) { - return string; - } - if (!length) { - length = 400; - } - - if (string.length > length) { - return string.substring(0, length) + '...'; - } else { - return string; - } -} - - -// A patched toPromise function, to log the results of promise if required. -utils.toPromise = function (func, passPromise) { - var fn = _toPromise(func, passPromise); - - var patchedFn = function () { - var args = Array.prototype.slice.call(arguments); - var promise = fn.apply(this, args); - - function logResult(result, method) { - method = method || 'log'; - - patchedFn._dbInfo.then(function (info) { - console[method]( - "\n==>", patchedFn._dbType, info.db_name, patchedFn._methodName, - "\nargs: " + truncate(JSON.stringify(args)), - "\nresult:", truncate(JSON.stringify(result, null, 2)), - "\n===" - ); - // Might not be the best of ideas. - process.stdout.write(prompt); - }); - } - - if (patchedFn._doPromiseLog && PatchedPouch.doPromiseLog) { - return promise.then(function (result) { - logResult(result); - }, function (err) { - logResult(err, 'error'); - }); - } else { - return promise; - } - }; - - // Few attributres for communcation with PatchedPouch constructor. - patchedFn._isPromisingFunction = true; - patchedFn._doPromiseLog = false; - return patchedFn; -}; - -// Load pouchdb with the patched toPromise -var PouchDB = require('../'); - -// A Patched version of PouchDB - to complement what toPromise logging needs. -function PatchedPouch(name, opts, callback) { - var db = new PouchDB(name, opts, callback); - var excluded = ['info']; - var dbInfo = db.info(); - var dbType = db.type(); - var doPromiseLog = false; - - for (var key in db) { - if (key !== 'info' && typeof db[key] === 'function' && - db[key]._isPromisingFunction) { - - doPromiseLog = excluded.indexOf(key) < 0; - // Update attributes to communicate back to toPromise's logging. - utils.extend(db[key], { - _doPromiseLog: doPromiseLog, - _methodName: key, - _dbInfo: dbInfo, - _dbType: dbType - }); - - } - } - - return db; -} -PatchedPouch.doPromiseLog = true; - -utils.extend(repl.start({ - prompt: prompt -}).context, { - PouchDB: PatchedPouch, - P: PatchedPouch -});
diff --git a/bin/run-cordova.sh b/bin/run-cordova.sh deleted file mode 100755 index 3234d22..0000000 --- a/bin/run-cordova.sh +++ /dev/null
@@ -1,89 +0,0 @@ -#!/bin/bash - -if [[ -z $CLIENT ]]; then - echo -e "\nUsing default client (android), you can specify with e.g." - echo -e '$CLIENT'"=android" or '$CLIENT'"=ios\n" - CLIENT=android -fi; - -if [[ -z $DEVICE ]]; then - ACTION=emulate - echo -e "\nUsing default "'$DEVICE'"=false, you can also do:" - echo -e '$DEVICE'"=true to run on a real device\n" -else - if [[ $DEVICE -ne 'true' ]]; then - ACTION=emulate - else - ACTION=run - fi; -fi; - -TESTS_DIR=./tests/integration/cordova - -rm -fr $TESTS_DIR/www -mkdir -p $TESTS_DIR/www - -mkdir -p $TESTS_DIR/www/node_modules -cp -r node_modules/mocha node_modules/chai node_modules/es5-shim \ - $TESTS_DIR/www/node_modules -mkdir -p $TESTS_DIR/www/tests/integration -cp -r tests/integration/*{js,html} tests/integration/deps $TESTS_DIR/www/tests/integration - -mkdir -p $TESTS_DIR/www/dist -cp dist/pouchdb*js $TESTS_DIR/www/dist - -./node_modules/replace/bin/replace.js '<body>' \ - '<body><script src="../cordova.js"></script>' \ - $TESTS_DIR/www/tests/integration/index.html - -if [[ ! -z $GREP ]]; then - ./node_modules/replace/bin/replace.js '<body>' \ - "<body><script>window.GREP = ""'"$GREP"'"";</script>" \ - $TESTS_DIR/www/tests/integration/index.html -fi - -if [[ ! -z $ES5_SHIMS ]]; then - ES5_SHIM=$ES5_SHIMS # synonym -fi - -if [[ ! -z $ES5_SHIM ]]; then - ./node_modules/replace/bin/replace.js '<body>' \ - "<body><script>window.ES5_SHIM = ""'"$ES5_SHIM"'"";</script>" \ - $TESTS_DIR/www/tests/integration/index.html -fi - -if [[ ! -z $COUCH_HOST ]]; then - ./node_modules/replace/bin/replace.js '<body>' \ - "<body><script>window.COUCH_HOST = ""'"$COUCH_HOST"'"";</script>" \ - $TESTS_DIR/www/tests/integration/index.html -fi - -if [[ ! -z $ADAPTER ]]; then - ADAPTERS=$ADAPTER # I know I'm gonna mistype this -fi - -if [[ ! -z $ADAPTERS ]]; then - ./node_modules/replace/bin/replace.js '<body>' \ - "<body><script>window.ADAPTERS = ""'"$ADAPTERS"'"";</script>" \ - $TESTS_DIR/www/tests/integration/index.html -fi - -if [[ ! -z $WEINRE_HOST ]]; then - ./node_modules/replace/bin/replace.js '<body>' \ - "<body><script src=""'"$WEINRE_HOST"/target/target-script-min.js#anonymous""'""></script>" \ - $TESTS_DIR/www/tests/integration/index.html - -fi - -cd $TESTS_DIR - -CORDOVA=../../../node_modules/cordova/bin/cordova - -$CORDOVA platform add $CLIENT -if [[ $($CORDOVA plugin list | grep sqlite) ]]; then - $CORDOVA plugin rm com.phonegap.plugins.sqlite -fi -if [[ $SQLITE_PLUGIN == 'true' ]]; then - $CORDOVA plugin add https://github.com/brodysoft/Cordova-SQLitePlugin -fi -$CORDOVA $ACTION $CLIENT
diff --git a/bin/run-couch-master-on-travis.sh b/bin/run-couch-master-on-travis.sh deleted file mode 100755 index 8705bf6..0000000 --- a/bin/run-couch-master-on-travis.sh +++ /dev/null
@@ -1,39 +0,0 @@ -#!/bin/bash -set -e -set -x - -CWD=$(pwd) - -# Install deps -sudo apt-get update -sudo apt-get --no-install-recommends -y install \ - build-essential \ - ca-certificates \ - curl \ - erlang-dev \ - erlang-nox \ - git \ - libicu-dev \ - libmozjs185-dev \ - python - -# Rebar isnt in apt -git clone git://github.com/rebar/rebar.git ~/rebar -cd ~/rebar -./bootstrap -sudo cp ./rebar /usr/local/bin - -# Sweet, build CouchDB -cd .. -git clone https://github.com/apache/couchdb.git ~/couchdb -cd ~/couchdb -./configure -make - -# All done, run a cluster -python dev/run & - -# Lets get rid of this at some point :) -sleep 10 - -cd $CWD
diff --git a/bin/run-coverage.js b/bin/run-coverage.js deleted file mode 100755 index 57a6193..0000000 --- a/bin/run-coverage.js +++ /dev/null
@@ -1,43 +0,0 @@ -#!/usr/bin/env node -'use strict'; - -if (!process.env.DASHBOARD_HOST) { - console.log('DASHBOARD_HOST is required'); - process.exit(0); -} - -var spawn = require('child_process').spawn; -var fs = require('fs'); -var request = require('request'); - -var DASHBOARD_HOST = process.env.DASHBOARD_HOST; - -var env = process.env; -env.COVERAGE = 1; -env.stdio = 'inherit'; - -var sp = spawn('npm', ['test'], env); - -sp.on('close', function (code) { - console.log('child process exited with code ' + code); - - var coverage_file = fs.readFileSync('coverage/coverage.json', 'utf-8'); - var coverage_json = JSON.parse(coverage_file); - coverage_json.date = Date.now(); - - var options = { - method: 'POST', - uri: DASHBOARD_HOST + '/coverage_results', - json: coverage_json - }; - - request(options, function (error, response, body) { - if (!error) { - return process.exit(0); - } else { - return process.exit(1); - } - }); - -}); -
diff --git a/bin/run-test.sh b/bin/run-test.sh deleted file mode 100755 index 73808a0..0000000 --- a/bin/run-test.sh +++ /dev/null
@@ -1,52 +0,0 @@ -#!/bin/bash - -: ${CLIENT:="node"} - -if [[ ! -z $SERVER ]]; then - if [ "$SERVER" == "pouchdb-server" ]; then - if [[ "$TRAVIS_REPO_SLUG" == "pouchdb/pouchdb" ]]; then - # for pouchdb-server to link to pouchdb, only in travis - rm -fr ./node_modules/pouchdb-server/node_modules/pouchdb - ln -s ../../.. ./node_modules/pouchdb-server/node_modules/pouchdb - fi - export COUCH_HOST='http://127.0.0.1:6984' - echo -e "Starting up pouchdb-server\n" - TESTDIR=./tests/pouchdb_server - rm -rf $TESTDIR && mkdir -p $TESTDIR - if [[ "$SERVER_ADAPTER" == "memory" ]]; then - FLAGS='--in-memory' - else - FLAGS="-d $TESTDIR" - fi - ./node_modules/.bin/pouchdb-server -p 6984 $FLAGS & - export POUCHDB_SERVER_PID=$! - sleep 15 # give it a chance to start up - elif [ "$SERVER" == "couchdb-master" ]; then - if [[ "$TRAVIS_REPO_SLUG" == "pouchdb/pouchdb" ]]; then - ./bin/run-couch-master-on-travis.sh - fi - export COUCH_HOST='http://127.0.0.1:15986' - elif [ "$SERVER" == "pouchdb-express-router" ]; then - node ./tests/misc/pouchdb-express-router.js & - sleep 5 - export COUCH_HOST='http://127.0.0.1:3000' - else - # I mistype pouchdb-server a lot - echo -e "Unknown SERVER $SERVER. Did you mean pouchdb-server?\n" - exit 1 - fi -fi - -if [ "$CLIENT" == "unit" ]; then - npm run test-unit -elif [ "$CLIENT" == "node" ]; then - npm run test-node -else - npm run test-browser -fi - -EXIT_STATUS=$? -if [[ ! -z $POUCHDB_SERVER_PID ]]; then - kill $POUCHDB_SERVER_PID -fi -exit $EXIT_STATUS
diff --git a/bin/test-browser.js b/bin/test-browser.js deleted file mode 100755 index 7d4c8e0..0000000 --- a/bin/test-browser.js +++ /dev/null
@@ -1,211 +0,0 @@ -#!/usr/bin/env node -'use strict'; - -var path = require('path'); -var spawn = require('child_process').spawn; - -var wd = require('wd'); -wd.configureHttp({timeout: 180000}); // 3 minutes -var sauceConnectLauncher = require('sauce-connect-launcher'); -var querystring = require("querystring"); -var request = require('request').defaults({json: true}); - -var devserver = require('./dev-server.js'); - -var SELENIUM_PATH = '../vendor/selenium-server-standalone-2.38.0.jar'; -var SELENIUM_HUB = 'http://localhost:4444/wd/hub/status'; - -var testTimeout = 30 * 60 * 1000; - -var username = process.env.SAUCE_USERNAME; -var accessKey = process.env.SAUCE_ACCESS_KEY; - -// BAIL=0 to disable bailing -var bail = process.env.BAIL !== '0'; - -// process.env.CLIENT is a colon seperated list of -// (saucelabs|selenium):browserName:browserVerion:platform -var tmp = (process.env.CLIENT || 'selenium:firefox').split(':'); -var client = { - runner: tmp[0] || 'selenium', - browser: tmp[1] || 'firefox', - version: tmp[2] || null, // Latest - platform: tmp[3] || null -}; - -var testRoot = 'http://127.0.0.1:8000/tests/'; -var testUrl = testRoot + - (process.env.PERF ? 'performance/index.html' : 'integration/index.html'); -var qs = {}; - -var sauceClient; -var sauceConnectProcess; -var tunnelId = process.env.TRAVIS_JOB_NUMBER || 'tunnel-' + Date.now(); - -if (client.runner === 'saucelabs') { - qs.saucelabs = true; -} -if (process.env.GREP) { - qs.grep = process.env.GREP; -} -if (process.env.ADAPTERS) { - qs.adapters = process.env.ADAPTERS; -} -if (process.env.ES5_SHIM || process.env.ES5_SHIMS) { - qs.es5shim = true; -} -if (process.env.AUTO_COMPACTION) { - qs.autoCompaction = true; -} -if (process.env.SERVER) { - qs.SERVER = process.env.SERVER; -} - -testUrl += '?'; -testUrl += querystring.stringify(qs); - -if (process.env.TRAVIS && - client.browser !== 'firefox' && - process.env.TRAVIS_SECURE_ENV_VARS === 'false') { - console.error('Not running test, cannot connect to saucelabs'); - process.exit(0); - return; -} - -function testError(e) { - console.error(e); - console.error('Doh, tests failed'); - sauceClient.quit(); - process.exit(3); -} - -function postResult(result) { - if (process.env.PERF && process.env.DASHBOARD_HOST) { - result.branch = process.env.TRAVIS_BRANCH || process.env.BRANCH || false; - result.commit = process.env.TRAVIS_COMMIT || process.env.COMMIT || false; - result.pull_request = process.env.TRAVIS_PULL_REQUEST; - var commits = 'https://api.github.com/repos/pouchdb/pouchdb/git/commits/'; - request({ - method: 'GET', - uri: commits + result.commit, - headers: {'User-Agent': 'request'} - }, function (error, response, body) { - result._id = result.date = body.committer.date; - request({ - method: 'POST', - uri: process.env.DASHBOARD_HOST + '/performance_results', - json: result - }, function (error, response, body) { - console.log(result); - process.exit(!!error); - }); - }); - return; - } - process.exit(!process.env.PERF && result.failed ? 1 : 0); -} - -function testComplete(result) { - console.log(result); - - sauceClient.quit().then(function () { - if (sauceConnectProcess) { - sauceConnectProcess.close(function () { - postResult(result); - }); - } else { - postResult(result); - } - }); -} - -function startSelenium(callback) { - - // Start selenium - spawn('java', ['-jar', path.resolve(__dirname, SELENIUM_PATH)], {}); - - var retries = 0; - var started = function () { - - if (++retries > 60) { - console.error('Unable to connect to selenium'); - process.exit(1); - return; - } - - request(SELENIUM_HUB, function (err, resp) { - if (resp && resp.statusCode === 200) { - sauceClient = wd.promiseChainRemote(); - callback(); - } else { - setTimeout(started, 1000); - } - }); - }; - - started(); - -} - -function startSauceConnect(callback) { - - var options = { - username: username, - accessKey: accessKey, - tunnelIdentifier: tunnelId - }; - - sauceConnectLauncher(options, function (err, process) { - if (err) { - console.error('Failed to connect to saucelabs'); - console.error(err); - return process.exit(1); - } - sauceConnectProcess = process; - sauceClient = wd.promiseChainRemote("localhost", 4445, username, accessKey); - callback(); - }); -} - -function startTest() { - - console.log('Starting', client); - - var opts = { - browserName: client.browser, - version: client.version, - platform: client.platform, - tunnelTimeout: testTimeout, - name: client.browser + ' - ' + tunnelId, - 'max-duration': 60 * 45, - 'command-timeout': 599, - 'idle-timeout': 599, - 'tunnel-identifier': tunnelId - }; - - sauceClient.init(opts).get(testUrl, function () { - - /* jshint evil: true */ - var interval = setInterval(function () { - sauceClient.eval('window.results', function (err, results) { - if (err) { - clearInterval(interval); - testError(err); - } else if (results.completed || (results.failures.length && bail)) { - clearInterval(interval); - testComplete(results); - } else { - console.log('=> ', results); - } - }); - }, 10 * 1000); - }); -} - -devserver.start(function () { - if (client.runner === 'saucelabs') { - startSauceConnect(startTest); - } else { - startSelenium(startTest); - } -});
diff --git a/bin/test-node.sh b/bin/test-node.sh deleted file mode 100755 index 58231eb..0000000 --- a/bin/test-node.sh +++ /dev/null
@@ -1,32 +0,0 @@ -#!/bin/bash - -: ${TIMEOUT:=50000} -: ${REPORTER:="spec"} -: ${BAIL:=1} - -if [ $BAIL -eq 1 ]; then - BAIL_OPT="--bail" -else - BAIL_OPT="" -fi - -if [ $PERF ]; then - node tests/performance/index.js -elif [ ! $COVERAGE ]; then - ./node_modules/.bin/mocha \ - $BAIL_OPT \ - --timeout $TIMEOUT \ - --require=./tests/integration/node.setup.js \ - --reporter=$REPORTER \ - --grep=$GREP \ - tests/integration/test.*.js -else - ./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha -- \ - $BAIL_OPT \ - --timeout $TIMEOUT \ - --require=./tests/integration/node.setup.js \ - --reporter=$REPORTER \ - --grep=$GREP \ - tests/integration/test.*.js -fi -
diff --git a/bower.json b/bower.json index fc250db..cd0d64b 100644 --- a/bower.json +++ b/bower.json
@@ -1,6 +1,6 @@ { "name": "pouchdb", - "version": "3.1.1-prerelease", + "version": "3.2.0", "description": "PouchDB is a pocket-sized database.", "repo": "daleharvey/pouchdb", "keywords": [
diff --git a/component.json b/component.json index b295430..ed6d9e9 100644 --- a/component.json +++ b/component.json
@@ -1,6 +1,6 @@ { "name": "pouchdb", - "version": "3.1.1-prerelease", + "version": "3.2.0", "description": "PouchDB is a pocket-sized database.", "repo": "daleharvey/pouchdb", "keywords": [
diff --git a/dist/pouchdb.idb-alt.js b/dist/pouchdb.idb-alt.js new file mode 100644 index 0000000..bf82aa5 --- /dev/null +++ b/dist/pouchdb.idb-alt.js
@@ -0,0 +1,16416 @@ +// PouchDB alternative IndexedDB plugin 3.2.0 +// Based on level.js: https://github.com/maxogden/level.js +// +// (c) 2012-2014 Dale Harvey and the PouchDB team +// PouchDB may be freely distributed under the Apache license, version 2.0. +// For all details and documentation: +// http://pouchdb.com +require=(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<r.length;o++)s(r[o]);return s})({"./lib/deps/migrate":[function(_dereq_,module,exports){ +(function (process){ +'use strict'; +// LevelAlt doesn't need the pre-2.2.0 LevelDB-specific migrations +exports.toSublevel = function (name, db, callback) { + process.nextTick(function () { + callback(); + }); +}; + +exports.localAndMetaStores = function (db, stores, callback) { + process.nextTick(function () { + callback(); + }); +}; + +}).call(this,_dereq_('_process')) +},{"_process":24}],1:[function(_dereq_,module,exports){ +(function (process,Buffer){ +'use strict'; + +var levelup = _dereq_('levelup'); +var originalLeveldown = _dereq_('leveldown'); +var sublevel = _dereq_('level-sublevel'); +var through = _dereq_('through2').obj; + +var errors = _dereq_('../deps/errors'); +var merge = _dereq_('../merge'); +var utils = _dereq_('../utils'); +var migrate = _dereq_('../deps/migrate'); +var vuvuzela = _dereq_('vuvuzela'); +var Deque = _dereq_("double-ended-queue"); + +var DOC_STORE = 'document-store'; +var BY_SEQ_STORE = 'by-sequence'; +var ATTACHMENT_STORE = 'attach-store'; +var BINARY_STORE = 'attach-binary-store'; +var LOCAL_STORE = 'local-store'; +var META_STORE = 'meta-store'; +var BATCH_SIZE = 50; + +// leveldb barks if we try to open a db multiple times +// so we cache opened connections here for initstore() +var dbStores = new utils.Map(); + +// store the value of update_seq in the by-sequence store the key name will +// never conflict, since the keys in the by-sequence store are integers +var UPDATE_SEQ_KEY = '_local_last_update_seq'; +var DOC_COUNT_KEY = '_local_doc_count'; +var UUID_KEY = '_local_uuid'; + +var MD5_PREFIX = 'md5-'; + +var vuvuEncoding = { + encode: vuvuzela.stringify, + decode: vuvuzela.parse, + buffer: false, + type: 'cheap-json' +}; + +function fetchAttachments(results, stores) { + return utils.Promise.all(results.map(function (row) { + if (row.doc && row.doc._attachments) { + var attNames = Object.keys(row.doc._attachments); + return utils.Promise.all(attNames.map(function (att) { + var attObj = row.doc._attachments[att]; + if ('data' in attObj) { // already fetched + return; + } + return new utils.Promise(function (resolve, reject) { + stores.binaryStore.get(attObj.digest, function (err, buffer) { + var base64 = ''; + if (err && err.name !== 'NotFoundError') { + return reject(err); + } else if (!err) { + base64 = utils.btoa(buffer); + } + row.doc._attachments[att] = utils.extend( + utils.pick(attObj, ['digest', 'content_type']), + {data: base64} + ); + resolve(); + }); + }); + })); + } + })); +} + +function createChangesFilter(opts) { + var baseFilter = utils.filterChange(opts); + var docIds = opts.doc_ids && new utils.Set(opts.doc_ids); + return function filter(change) { + // It's the responsibility of each adapter to actually do + // the doc_ids filtering, since websql/idb can do it + // more efficiently. + if (docIds && !docIds.has(change.id)) { + return false; + } + return baseFilter(change); + }; +} + +function LevelPouch(opts, callback) { + opts = utils.clone(opts); + var api = this; + var instanceId; + var stores = {}; + var db; + var name = opts.name; + if (typeof opts.createIfMissing === 'undefined') { + opts.createIfMissing = true; + } + + var leveldown = opts.db || originalLeveldown; + if (typeof leveldown.destroy !== 'function') { + leveldown.destroy = function (name, cb) { cb(); }; + } + var dbStore; + if (dbStores.has(leveldown.name)) { + dbStore = dbStores.get(leveldown.name); + } else { + dbStore = new utils.Map(); + dbStores.set(leveldown.name, dbStore); + } + if (dbStore.has(name)) { + db = dbStore.get(name); + afterDBCreated(); + } else { + dbStore.set(name, sublevel(levelup(name, opts, function (err) { + if (err) { + dbStore["delete"](name); + return callback(err); + } + db = dbStore.get(name); + db._docCountQueue = { + queue : [], + running : false, + docCount : -1 + }; + db._writeQueue = new Deque(); + if (opts.db || opts.noMigrate) { + afterDBCreated(); + } else { + migrate.toSublevel(name, db, afterDBCreated); + } + }))); + } + + function afterDBCreated() { + stores.docStore = db.sublevel(DOC_STORE, {valueEncoding: vuvuEncoding}); + stores.bySeqStore = db.sublevel(BY_SEQ_STORE, {valueEncoding: 'json'}); + stores.attachmentStore = + db.sublevel(ATTACHMENT_STORE, {valueEncoding: 'json'}); + stores.binaryStore = db.sublevel(BINARY_STORE, {valueEncoding: 'binary'}); + stores.localStore = db.sublevel(LOCAL_STORE, {valueEncoding: 'json'}); + stores.metaStore = db.sublevel(META_STORE, {valueEncoding: 'json'}); + migrate.localAndMetaStores(db, stores, function () { + stores.metaStore.get(UPDATE_SEQ_KEY, function (err, value) { + if (typeof db._updateSeq === 'undefined') { + db._updateSeq = value || 0; + } + stores.metaStore.get(DOC_COUNT_KEY, function (err, value) { + db._docCountQueue.docCount = !err ? value : 0; + countDocs(function (err) { // notify queue that the docCount is ready + if (err) { + api.emit('error', err); + } + stores.metaStore.get(UUID_KEY, function (err, value) { + instanceId = !err ? value : utils.uuid(); + stores.metaStore.put(UUID_KEY, instanceId, function (err, value) { + process.nextTick(function () { + callback(null, api); + }); + }); + }); + }); + }); + }); + }); + } + + function countDocs(callback) { + if (db._docCountQueue.running || !db._docCountQueue.queue.length || + db._docCountQueue.docCount === -1) { + return incrementDocCount(0, callback); // wait for fresh data + } + return db._docCountQueue.docCount; // use cached value + } + + function applyNextDocCountDelta() { + if (db._docCountQueue.running || !db._docCountQueue.queue.length || + db._docCountQueue.docCount === -1) { + return; + } + db._docCountQueue.running = true; + var item = db._docCountQueue.queue.shift(); + if (db.isClosed()) { + return item.callback(new Error('database is closed')); + } + stores.metaStore.get(DOC_COUNT_KEY, function (err, docCount) { + docCount = !err ? docCount : 0; + + function complete(err) { + db._docCountQueue.docCount = docCount; + item.callback(err, docCount); + db._docCountQueue.running = false; + applyNextDocCountDelta(); + } + + if (item.delta === 0) { + complete(); + } else { + stores.metaStore.put(DOC_COUNT_KEY, docCount + item.delta, complete); + } + }); + } + + function incrementDocCount(delta, callback) { + db._docCountQueue.queue.push({delta : delta, callback : callback}); + applyNextDocCountDelta(); + } + + api.type = function () { + return 'leveldb'; + }; + + api._id = function (callback) { + callback(null, instanceId); + }; + + api._info = function (callback) { + countDocs(function (err, docCount) { + if (err) { + return callback(err); + } + stores.metaStore.get(UPDATE_SEQ_KEY, function (err, otherUpdateSeq) { + if (err) { + otherUpdateSeq = db._updateSeq; + } + + return callback(null, { + doc_count: docCount, + update_seq: otherUpdateSeq + }); + }); + }); + }; + + // all read/write operations to the database are done in a queue, + // similar to how websql/idb works. this avoids problems such + // as e.g. compaction needing to have a lock on the database while + // it updates stuff. in the future we can revisit this. + function writeLock(fun) { + return utils.getArguments(function (args) { + + var callback = args[args.length - 1]; + args[args.length - 1] = utils.getArguments(function (cbArgs) { + callback.apply(null, cbArgs); + process.nextTick(function () { + db._writeQueue.shift(); + if (db._writeQueue.length) { + db._writeQueue.peekFront()(); + } + }); + }); + + db._writeQueue.push(function () { + fun.apply(null, args); + }); + + if (db._writeQueue.length === 1) { + db._writeQueue.peekFront()(); + } + }); + } + + function formatSeq(n) { + return ('0000000000000000' + n).slice(-16); + } + + function parseSeq(s) { + return parseInt(s, 10); + } + + function makeDoc(rawDoc, callback) { + var doc = rawDoc.data; + doc._id = rawDoc.metadata.id; + if ('_rev' in doc) { + if (doc._rev !== rawDoc.metadata.rev) { + return callback(new Error('wrong doc returned')); + } + } else { + // we didn't always store rev + doc._rev = rawDoc.metadata.rev; + } + callback(null, {doc: doc, metadata: rawDoc.metadata}); + } + + api._get = function (id, opts, callback) { + opts = utils.clone(opts); + var docChanged = []; + + function didDocChange(doc) { + docChanged.push(doc); + } + + db.on('pouchdb-id-' + id, didDocChange); + + stores.docStore.get(id, function (err, metadata) { + db.removeListener('pouchdb-id-' + id, didDocChange); + + if (err || !metadata) { + return callback(errors.MISSING_DOC); + } + + if (utils.isDeleted(metadata) && !opts.rev) { + return callback(errors.error(errors.MISSING_DOC, "deleted")); + } + + var updated; + + function ifUpdate(doc) { + updated = doc; + } + + var rev = merge.winningRev(metadata); + rev = opts.rev ? opts.rev : rev; + + var seq = metadata.rev_map[rev]; + + var anyChanged = docChanged.filter(function (doc) { + return doc.metadata.seq === seq; + }); + + if (anyChanged.length) { + return makeDoc(anyChanged.pop(), callback); + } + + db.on('pouchdb-' + seq, ifUpdate); + + stores.bySeqStore.get(formatSeq(seq), function (err, doc) { + db.removeListener('pouchdb-' + seq, ifUpdate); + if (updated) { + return makeDoc(updated, callback); + + } + + if (!doc) { + return callback(errors.MISSING_DOC); + } + if ('_id' in doc && doc._id !== metadata.id) { + // this failing implies something very wrong + return callback(new Error('wrong doc returned')); + } + doc._id = metadata.id; + if ('_rev' in doc) { + if (doc._rev !== rev) { + // this failing implies something very wrong + return callback(new Error('wrong doc returned')); + } + } else { + // we didn't always store this + doc._rev = rev; + } + return callback(null, {doc: doc, metadata: metadata}); + }); + }); + }; + + // not technically part of the spec, but if putAttachment has its own + // method... + api._getAttachment = function (attachment, opts, callback) { + var digest = attachment.digest; + + stores.binaryStore.get(digest, function (err, attach) { + var data; + + if (err && err.name === 'NotFoundError') { + // Empty attachment + data = opts.encode ? '' : process.browser ? + utils.createBlob([''], {type: attachment.content_type}) : + new Buffer(''); + return callback(null, data); + } + + if (err) { + return callback(err); + } + + if (process.browser) { + if (opts.encode) { + data = utils.btoa(attach); + } else { + data = utils.createBlob([utils.fixBinary(attach)], + {type: attachment.content_type}); + } + } else { + data = opts.encode ? utils.btoa(attach) : attach; + } + callback(null, data); + }); + }; + + api._bulkDocs = writeLock(function (req, opts, callback) { + var newEdits = opts.new_edits; + var results = new Array(req.docs.length); + var lock = new utils.Set(); + + // parse the docs and give each a sequence number + var userDocs = req.docs; + var info = userDocs.map(function (doc, i) { + if (doc._id && utils.isLocalId(doc._id)) { + return doc; + } + var newDoc = utils.parseDoc(doc, newEdits); + + if (newDoc.metadata && !newDoc.metadata.rev_map) { + newDoc.metadata.rev_map = {}; + } + + return newDoc; + }); + var current = 0; + var infoErrors = info.filter(function (doc) { + return doc.error; + }); + + if (infoErrors.length) { + return callback(infoErrors[0]); + } + + // verify any stub attachments as a precondition test + + function verifyAttachment(digest, callback) { + stores.attachmentStore.get(digest, function (levelErr) { + if (levelErr) { + var err = new Error('unknown stub attachment with digest ' + digest); + err.status = 412; + callback(err); + } else { + callback(); + } + }); + } + + function verifyAttachments(finish) { + var digests = []; + userDocs.forEach(function (doc) { + if (doc && doc._attachments) { + Object.keys(doc._attachments).forEach(function (filename) { + var att = doc._attachments[filename]; + if (att.stub) { + digests.push(att.digest); + } + }); + } + }); + if (!digests.length) { + return finish(); + } + var numDone = 0; + var err; + + function checkDone() { + if (++numDone === digests.length) { + finish(err); + } + } + digests.forEach(function (digest) { + verifyAttachment(digest, function (attErr) { + if (attErr && !err) { + err = attErr; + } + checkDone(); + }); + }); + } + + var inProgress = 0; + function processDocs() { + var index = current; + if (inProgress > BATCH_SIZE) { + return; + } + if (index >= info.length) { + if (inProgress === 0) { + return complete(); + } else { + return; + } + } + var currentDoc = info[index]; + current++; + inProgress++; + if (currentDoc._id && utils.isLocalId(currentDoc._id)) { + api[currentDoc._deleted ? '_removeLocalNoLock' : '_putLocalNoLock']( + currentDoc, function (err, resp) { + if (err) { + results[index] = err; + } else { + results[index] = {}; + } + inProgress--; + processDocs(); + }); + return; + } + + if (lock.has(currentDoc.metadata.id)) { + results[index] = errors.REV_CONFLICT; + inProgress--; + return processDocs(); + } + lock.add(currentDoc.metadata.id); + + stores.docStore.get(currentDoc.metadata.id, function (err, oldDoc) { + if (err) { + if (err.name === 'NotFoundError') { + insertDoc(currentDoc, index, function () { + lock["delete"](currentDoc.metadata.id); + inProgress--; + processDocs(); + }); + } else { + err.error = true; + results[index] = err; + lock["delete"](currentDoc.metadata.id); + inProgress--; + processDocs(); + } + } else { + updateDoc(oldDoc, currentDoc, index, function () { + lock["delete"](currentDoc.metadata.id); + inProgress--; + processDocs(); + }); + } + }); + + if (newEdits) { + processDocs(); + } + } + + function insertDoc(doc, index, callback) { + // Can't insert new deleted documents + if ('was_delete' in opts && utils.isDeleted(doc.metadata)) { + results[index] = errors.MISSING_DOC; + return callback(); + } + writeDoc(doc, index, function (err) { + if (err) { + return callback(err); + } + if (utils.isDeleted(doc.metadata)) { + return callback(); + } + incrementDocCount(1, callback); + }); + } + + function updateDoc(oldDoc, docInfo, index, callback) { + + if (utils.revExists(oldDoc, docInfo.metadata.rev)) { + results[index] = docInfo; + callback(); + return; + } + + var previouslyDeleted = utils.isDeleted(oldDoc); + var deleted = utils.isDeleted(docInfo.metadata); + var isRoot = /^1-/.test(docInfo.metadata.rev); + + if (previouslyDeleted && !deleted && newEdits && isRoot) { + var newDoc = docInfo.data; + newDoc._rev = oldDoc.rev; + newDoc._id = docInfo.metadata.id; + docInfo = utils.parseDoc(newDoc, newEdits); + } + + var merged = + merge.merge(oldDoc.rev_tree, docInfo.metadata.rev_tree[0], 1000); + + var inConflict = newEdits && ((previouslyDeleted && deleted) || + (!previouslyDeleted && newEdits && merged.conflicts !== 'new_leaf') || + (previouslyDeleted && !deleted && merged.conflicts === 'new_branch')); + + if (inConflict) { + results[index] = errors.REV_CONFLICT; + return callback(); + } + var newRev = docInfo.metadata.rev; + docInfo.metadata.rev_tree = merged.tree; + docInfo.metadata.rev_map = oldDoc.rev_map; + + var delta = 0; + if (newEdits || merge.winningRev(docInfo.metadata) === newRev) { + // if newEdits==false and we're pushing existing revisions, + // then the only thing that matters is whether this revision + // is the winning one, and thus replaces an old one + delta = (previouslyDeleted === deleted) ? 0 : + previouslyDeleted < deleted ? -1 : 1; + } + + incrementDocCount(delta, function (err) { + if (err) { + return callback(err); + } + writeDoc(docInfo, index, callback); + }); + + } + + function writeDoc(doc, index, callback2) { + var err = null; + var recv = 0; + + doc.data._id = doc.metadata.id; + doc.data._rev = doc.metadata.rev; + + if (utils.isDeleted(doc.metadata)) { + doc.data._deleted = true; + } + + var attachments = doc.data._attachments ? + Object.keys(doc.data._attachments) : + []; + + function collectResults(attachmentErr) { + if (!err) { + if (attachmentErr) { + err = attachmentErr; + callback2(err); + } else if (recv === attachments.length) { + finish(); + } + } + } + + function attachmentSaved(err) { + recv++; + collectResults(err); + } + + function onMD5Load(doc, key, data, attachmentSaved) { + return function (result) { + saveAttachment(doc, MD5_PREFIX + result, key, data, attachmentSaved); + }; + } + + function onLoadEnd(doc, key, attachmentSaved) { + return function (data) { + utils.MD5(data).then( + onMD5Load(doc, key, data, attachmentSaved) + ); + }; + } + + for (var i = 0; i < attachments.length; i++) { + var key = attachments[i]; + var att = doc.data._attachments[key]; + + if (att.stub) { + // still need to update the refs mapping + var id = doc.data._id; + var rev = doc.data._rev; + saveAttachmentRefs(id, rev, att.digest, attachmentSaved); + continue; + } + var data; + if (typeof att.data === 'string') { + try { + data = utils.atob(att.data); + } catch (e) { + callback(utils.extend({}, errors.BAD_ARG, + {reason: "Attachments need to be base64 encoded"})); + return; + } + } else if (!process.browser) { + data = att.data; + } else { // browser + utils.readAsBinaryString(att.data, + onLoadEnd(doc, key, attachmentSaved)); + continue; + } + utils.MD5(data).then( + onMD5Load(doc, key, data, attachmentSaved) + ); + } + + function finish() { + var seq = doc.metadata.rev_map[doc.metadata.rev]; + if (!seq) { + // check that there aren't any existing revisions with the same + // reivision id, else we shouldn't increment updateSeq + seq = ++db._updateSeq; + } + doc.metadata.rev_map[doc.metadata.rev] = doc.metadata.seq = seq; + var seqKey = formatSeq(seq); + db.emit('pouchdb-id-' + doc.metadata.id, doc); + db.emit('pouchdb-' + seqKey, doc); + db.batch([{ + key: seqKey, + value: doc.data, + prefix: stores.bySeqStore, + type: 'put', + valueEncoding: 'json' + }, { + key: doc.metadata.id, + value: doc.metadata, + prefix: stores.docStore, + type: 'put', + valueEncoding: vuvuEncoding + }], function (err) { + if (!err) { + db.emit('pouchdb-id-' + doc.metadata.id, doc); + db.emit('pouchdb-' + seqKey, doc); + } + return stores.metaStore.put(UPDATE_SEQ_KEY, db._updateSeq, + function (err) { + if (err) { + results[index] = err; + } else { + results[index] = doc; + } + return callback2(); + }); + }); + } + + if (!attachments.length) { + finish(); + } + } + + // attachments are queued per-digest, otherwise the refs could be + // overwritten by concurrent writes in the same bulkDocs session + var attachmentQueues = {}; + + function saveAttachmentRefs(id, rev, digest, callback) { + + function fetchAtt() { + return new utils.Promise(function (resolve, reject) { + stores.attachmentStore.get(digest, function (err, oldAtt) { + if (err && err.name !== 'NotFoundError') { + return reject(err); + } + resolve(oldAtt); + }); + }); + } + + function saveAtt(oldAtt) { + var ref = [id, rev].join('@'); + var newAtt = {}; + + if (oldAtt) { + if (oldAtt.refs) { + // only update references if this attachment already has them + // since we cannot migrate old style attachments here without + // doing a full db scan for references + newAtt.refs = oldAtt.refs; + newAtt.refs[ref] = true; + } + } else { + newAtt.refs = {}; + newAtt.refs[ref] = true; + } + + return new utils.Promise(function (resolve, reject) { + stores.attachmentStore.put(digest, newAtt, function (err) { + if (err) { + return reject(err); + } + resolve(!oldAtt); + }); + }); + } + + // put attachments in a per-digest queue, to avoid two docs with the same + // attachment overwriting each other + var queue = attachmentQueues[digest] || utils.Promise.resolve(); + attachmentQueues[digest] = queue.then(function () { + return fetchAtt().then(saveAtt).then(function (isNewAttachment) { + callback(null, isNewAttachment); + }, callback); + }); + } + + function saveAttachment(docInfo, digest, key, data, callback) { + var att = docInfo.data._attachments[key]; + delete att.data; + att.digest = digest; + att.length = data.length; + var id = docInfo.metadata.id; + var rev = docInfo.metadata.rev; + + saveAttachmentRefs(id, rev, digest, function (err, isNewAttachment) { + if (err) { + return callback(err); + } + // do not try to store empty attachments + if (data.length === 0) { + return callback(err); + } + if (!isNewAttachment) { + // small optimization - don't bother writing it again + return callback(err); + } + // doing this in batch causes a test to fail, wtf? + stores.binaryStore.put(digest, data, function (err) { + callback(err); + }); + }); + } + + function complete() { + var aresults = results.map(function (result) { + if (!Object.keys(result).length) { + return { + ok: true + }; + } + if (result.error) { + return result; + } + + var metadata = result.metadata; + var rev = merge.winningRev(metadata); + + return { + ok: true, + id: metadata.id, + rev: rev + }; + }); + LevelPouch.Changes.notify(name); + process.nextTick(function () { + callback(null, aresults); + }); + } + + verifyAttachments(function (err) { + if (err) { + return callback(err); + } + processDocs(); + }); + }); + api._allDocs = function (opts, callback) { + opts = utils.clone(opts); + countDocs(function (err, docCount) { + if (err) { + return callback(err); + } + var readstreamOpts = {}; + var skip = opts.skip || 0; + if (opts.startkey) { + readstreamOpts.start = opts.startkey; + } + if (opts.endkey) { + readstreamOpts.end = opts.endkey; + } + if (opts.key) { + readstreamOpts.start = readstreamOpts.end = opts.key; + } + if (opts.descending) { + readstreamOpts.reverse = true; + // switch start and ends + var tmp = readstreamOpts.start; + readstreamOpts.start = readstreamOpts.end; + readstreamOpts.end = tmp; + } + var limit; + if (typeof opts.limit === 'number') { + limit = opts.limit; + } else { + limit = -1; + } + if (limit === 0 || + ('start' in readstreamOpts && 'end' in readstreamOpts && + readstreamOpts.start > readstreamOpts.end)) { + // should return 0 results when start is greater than end. + // normally level would "fix" this for us by reversing the order, + // so short-circuit instead + return callback(null, { + total_rows: docCount, + offset: opts.skip, + rows: [] + }); + } + var results = []; + var docstream = stores.docStore.readStream(readstreamOpts); + + var throughStream = through(function (entry, _, next) { + if (!utils.isDeleted(entry.value)) { + if (skip-- > 0) { + next(); + return; + } else if (limit-- === 0) { + docstream.unpipe(); + docstream.destroy(); + next(); + return; + } + } else if (opts.deleted !== 'ok') { + next(); + return; + } + function allDocsInner(metadata, data) { + var doc = { + id: metadata.id, + key: metadata.id, + value: { + rev: merge.winningRev(metadata) + } + }; + if (opts.include_docs) { + doc.doc = data; + doc.doc._rev = doc.value.rev; + if (opts.conflicts) { + doc.doc._conflicts = merge.collectConflicts(metadata); + } + for (var att in doc.doc._attachments) { + if (doc.doc._attachments.hasOwnProperty(att)) { + doc.doc._attachments[att].stub = true; + } + } + } + if (opts.inclusive_end === false && metadata.id === opts.endkey) { + return next(); + } else if (utils.isDeleted(metadata)) { + if (opts.deleted === 'ok') { + doc.value.deleted = true; + doc.doc = null; + } else { + return next(); + } + } + results.push(doc); + next(); + } + var metadata = entry.value; + if (opts.include_docs) { + var seq = metadata.rev_map[merge.winningRev(metadata)]; + stores.bySeqStore.get(formatSeq(seq), function (err, data) { + allDocsInner(metadata, data); + }); + } + else { + allDocsInner(metadata); + } + }, function (next) { + utils.Promise.resolve().then(function () { + return opts.attachments && fetchAttachments(results, stores); + }).then(function () { + callback(null, { + total_rows: docCount, + offset: opts.skip, + rows: results + }); + }, callback); + next(); + }).on('unpipe', function () { + throughStream.end(); + }); + + docstream.on('error', callback); + + docstream.pipe(throughStream); + }); + }; + + api._changes = function (opts) { + opts = utils.clone(opts); + + if (opts.continuous) { + var id = name + ':' + utils.uuid(); + LevelPouch.Changes.addListener(name, id, api, opts); + LevelPouch.Changes.notify(name); + return { + cancel: function () { + LevelPouch.Changes.removeListener(name, id); + } + }; + } + + var descending = opts.descending; + var results = []; + var last_seq = 0; + var called = 0; + var streamOpts = { + reverse: descending + }; + var limit; + if ('limit' in opts && opts.limit > 0) { + limit = opts.limit; + } + if (!streamOpts.reverse) { + streamOpts.start = formatSeq(opts.since ? opts.since + 1 : 0); + } + + var filter = createChangesFilter(opts); + + var returnDocs; + if ('returnDocs' in opts) { + returnDocs = opts.returnDocs; + } else { + returnDocs = true; + } + + function complete() { + opts.done = true; + if (returnDocs && opts.limit) { + if (opts.limit < results.length) { + results.length = opts.limit; + } + } + changeStream.unpipe(throughStream); + changeStream.destroy(); + if (!opts.continuous && !opts.cancelled) { + utils.Promise.resolve().then(function () { + if (opts.include_docs && opts.attachments) { + return fetchAttachments(results, stores); + } + }).then(function () { + opts.complete(null, {results: results, last_seq: last_seq}); + }); + } + } + var changeStream = stores.bySeqStore.readStream(streamOpts); + var throughStream = through(function (data, _, next) { + if (limit && called >= limit) { + complete(); + return next(); + } + if (opts.cancelled || opts.done) { + return next(); + } + + stores.docStore.get(data.value._id, function (err, metadata) { + if (opts.cancelled || opts.done || db.isClosed() || + utils.isLocalId(metadata.id)) { + return next(); + } + var doc = data.value; + doc._rev = merge.winningRev(metadata); + var change = opts.processChange(doc, metadata, opts); + change.seq = metadata.seq; + + if (last_seq < metadata.seq) { + last_seq = metadata.seq; + } + + // Ensure duplicated dont overwrite winning rev + if (parseSeq(data.key) === metadata.rev_map[change.doc._rev] && + filter(change)) { + called++; + + if (opts.attachments && opts.include_docs) { + // fetch attachment immediately for the benefit + // of live listeners + fetchAttachments([change], stores).then(function () { + opts.onChange(change); + }); + } else { + opts.onChange(change); + } + + if (returnDocs) { + results.push(change); + } + } + next(); + }); + }, function (next) { + if (opts.cancelled) { + return next(); + } + if (returnDocs && opts.limit) { + if (opts.limit < results.length) { + results.length = opts.limit; + } + } + + next(); + }).on('unpipe', function () { + throughStream.end(); + complete(); + }); + changeStream.pipe(throughStream); + return { + cancel: function () { + opts.cancelled = true; + complete(); + } + }; + }; + + api._close = function (callback) { + if (db.isClosed()) { + return callback(errors.NOT_OPEN); + } + db.close(function (err) { + if (err) { + callback(err); + } else { + dbStore["delete"](name); + callback(); + } + }); + }; + + api._getRevisionTree = function (docId, callback) { + stores.docStore.get(docId, function (err, metadata) { + if (err) { + callback(errors.MISSING_DOC); + } else { + callback(null, metadata.rev_tree); + } + }); + }; + + api._doCompaction = writeLock(function (docId, revs, callback) { + if (!revs.length) { + return callback(); + } + stores.docStore.get(docId, function (err, metadata) { + if (err) { + return callback(err); + } + var seqs = metadata.rev_map; // map from rev to seq + merge.traverseRevTree(metadata.rev_tree, function (isLeaf, pos, + revHash, ctx, opts) { + var rev = pos + '-' + revHash; + if (revs.indexOf(rev) !== -1) { + opts.status = 'missing'; + } + }); + var batch = []; + batch.push({ + key: metadata.id, + value: metadata, + type: 'put', + valueEncoding: vuvuEncoding, + prefix: stores.docStore + }); + + var digestMap = {}; + var numDone = 0; + var overallErr; + function checkDone(err) { + if (err) { + overallErr = err; + } + if (++numDone === revs.length) { // done + if (overallErr) { + return callback(err); + } + deleteOrphanedAttachments(); + } + } + + function finish(err) { + if (err) { + return callback(err); + } + db.batch(batch, callback); + } + + function deleteOrphanedAttachments() { + var possiblyOrphanedAttachments = Object.keys(digestMap); + if (!possiblyOrphanedAttachments.length) { + return finish(); + } + var numDone = 0; + var overallErr; + function checkDone(err) { + if (err) { + overallErr = err; + } + if (++numDone === possiblyOrphanedAttachments.length) { + finish(overallErr); + } + } + var refsToDelete = new utils.Map(); + revs.forEach(function (rev) { + refsToDelete.set(docId + '@' + rev, true); + }); + possiblyOrphanedAttachments.forEach(function (digest) { + stores.attachmentStore.get(digest, function (err, attData) { + if (err) { + if (err.name === 'NotFoundError') { + return checkDone(); + } else { + return checkDone(err); + } + } + var refs = Object.keys(attData.refs || {}).filter(function (ref) { + return !refsToDelete.has(ref); + }); + var newRefs = {}; + refs.forEach(function (ref) { + newRefs[ref] = true; + }); + if (refs.length) { // not orphaned + batch.push({ + key: digest, + type: 'put', + valueEncoding: 'json', + value: {refs: newRefs}, + prefix: stores.attachmentStore + }); + } else { // orphaned, can safely delete + batch = batch.concat([{ + key: digest, + type: 'del', + prefix: stores.attachmentStore + }, { + key: digest, + type: 'del', + prefix: stores.binaryStore + }]); + } + checkDone(); + }); + }); + } + + revs.forEach(function (rev) { + var seq = seqs[rev]; + if (!seq) { + return; + } + batch.push({ + key: formatSeq(seq), + type: 'del', + prefix: stores.bySeqStore + }); + stores.bySeqStore.get(formatSeq(seq), function (err, doc) { + if (err) { + if (err.name === 'NotFoundError') { + return checkDone(); + } else { + return checkDone(err); + } + } + var atts = Object.keys(doc._attachments || {}); + atts.forEach(function (attName) { + var digest = doc._attachments[attName].digest; + digestMap[digest] = true; + }); + checkDone(); + }); + }); + }); + }); + + api._getLocal = function (id, callback) { + stores.localStore.get(id, function (err, doc) { + if (err) { + callback(errors.MISSING_DOC); + } else { + callback(null, doc); + } + }); + }; + + api._putLocal = writeLock(function (doc, callback) { + api._putLocalNoLock(doc, callback); + }); + + // the NoLock version is for use by bulkDocs + api._putLocalNoLock = function (doc, callback) { + delete doc._revisions; // ignore this, trust the rev + var oldRev = doc._rev; + var id = doc._id; + stores.localStore.get(id, function (err, resp) { + if (err) { + if (oldRev) { + return callback(errors.REV_CONFLICT); + } + } + if (resp && resp._rev !== oldRev) { + return callback(errors.REV_CONFLICT); + } + if (!oldRev) { + doc._rev = '0-1'; + } else { + doc._rev = '0-' + (parseInt(oldRev.split('-')[1], 10) + 1); + } + stores.localStore.put(id, doc, function (err) { + if (err) { + return callback(err); + } + var ret = {ok: true, id: doc._id, rev: doc._rev}; + callback(null, ret); + }); + }); + }; + + api._removeLocal = writeLock(function (doc, callback) { + api._removeLocalNoLock(doc, callback); + }); + + // the NoLock version is for use by bulkDocs + api._removeLocalNoLock = function (doc, callback) { + stores.localStore.get(doc._id, function (err, resp) { + if (err) { + return callback(err); + } + if (resp._rev !== doc._rev) { + return callback(errors.REV_CONFLICT); + } + stores.localStore.del(doc._id, function (err) { + if (err) { + return callback(err); + } + var ret = {ok: true, id: doc._id, rev: '0-0'}; + callback(null, ret); + }); + }); + }; +} + +LevelPouch.valid = function () { + return process && !process.browser; +}; + +// close and delete open leveldb stores +LevelPouch.destroy = utils.toPromise(function (name, opts, callback) { + opts = utils.clone(opts); + + var leveldown = opts.db || originalLeveldown; + function callDestroy(name, cb) { + if (typeof leveldown.destroy === 'function') { + leveldown.destroy(name, cb); + } else { + process.nextTick(callback); + } + } + + var dbStore; + if (dbStores.has(leveldown.name)) { + dbStore = dbStores.get(leveldown.name); + } else { + return callDestroy(name, callback); + } + + if (dbStore.has(name)) { + + LevelPouch.Changes.removeAllListeners(name); + + dbStore.get(name).close(function () { + dbStore["delete"](name); + callDestroy(name, callback); + }); + } else { + callDestroy(name, callback); + } +}); + +LevelPouch.use_prefix = false; + +LevelPouch.Changes = new utils.Changes(); + +module.exports = LevelPouch; + +}).call(this,_dereq_('_process'),_dereq_("buffer").Buffer) +},{"../deps/errors":5,"../deps/migrate":7,"../merge":10,"../utils":13,"_process":24,"buffer":17,"double-ended-queue":43,"level-sublevel":61,"leveldown":"leveldown","levelup":75,"through2":132,"vuvuzela":133}],2:[function(_dereq_,module,exports){ +"use strict"; + +var createBlob = _dereq_('./blob.js'); +var errors = _dereq_('./errors'); +var utils = _dereq_("../utils"); +var hasUpload; + +function ajax(options, adapterCallback) { + + var requestCompleted = false; + var callback = utils.getArguments(function (args) { + if (requestCompleted) { + return; + } + adapterCallback.apply(this, args); + requestCompleted = true; + }); + + if (typeof options === "function") { + callback = options; + options = {}; + } + + options = utils.clone(options); + + var defaultOptions = { + method : "GET", + headers: {}, + json: true, + processData: true, + timeout: 10000, + cache: false + }; + + options = utils.extend(true, defaultOptions, options); + + // cache-buster, specifically designed to work around IE's aggressive caching + // see http://www.dashbay.com/2011/05/internet-explorer-caches-ajax/ + if (options.method === 'GET' && !options.cache) { + var hasArgs = options.url.indexOf('?') !== -1; + options.url += (hasArgs ? '&' : '?') + '_nonce=' + utils.uuid(16); + } + + function onSuccess(obj, resp, cb) { + if (!options.binary && !options.json && options.processData && + typeof obj !== 'string') { + obj = JSON.stringify(obj); + } else if (!options.binary && options.json && typeof obj === 'string') { + try { + obj = JSON.parse(obj); + } catch (e) { + // Probably a malformed JSON from server + return cb(e); + } + } + if (Array.isArray(obj)) { + obj = obj.map(function (v) { + var obj; + if (v.ok) { + return v; + } else if (v.error && v.error === 'conflict') { + obj = errors.REV_CONFLICT; + obj.id = v.id; + return obj; + } else if (v.error && v.error === 'forbidden') { + obj = errors.FORBIDDEN; + obj.id = v.id; + obj.reason = v.reason; + return obj; + } else if (v.missing) { + obj = errors.MISSING_DOC; + obj.missing = v.missing; + return obj; + } else { + return v; + } + }); + } + cb(null, obj, resp); + } + + function onError(err, cb) { + var errParsed, errObj, errType, key; + try { + errParsed = JSON.parse(err.responseText); + //would prefer not to have a try/catch clause + for (key in errors) { + if (errors.hasOwnProperty(key) && + errors[key].name === errParsed.error) { + errType = errors[key]; + break; + } + } + if (!errType) { + errType = errors.UNKNOWN_ERROR; + if (err.status) { + errType.status = err.status; + } + if (err.statusText) { + err.name = err.statusText; + } + } + errObj = errors.error(errType, errParsed.reason); + } catch (e) { + for (var key in errors) { + if (errors.hasOwnProperty(key) && errors[key].status === err.status) { + errType = errors[key]; + break; + } + } + if (!errType) { + errType = errors.UNKNOWN_ERROR; + if (err.status) { + errType.status = err.status; + } + if (err.statusText) { + err.name = err.statusText; + } + } + errObj = errors.error(errType); + } + if (err.withCredentials && err.status === 0) { + // apparently this is what we get when the method + // is reported as not allowed by CORS. so fudge it + errObj.status = 405; + errObj.statusText = "Method Not Allowed"; + } + cb(errObj); + } + + var timer; + var xhr; + if (options.xhr) { + xhr = new options.xhr(); + } else { + xhr = new XMLHttpRequest(); + } + xhr.open(options.method, options.url); + xhr.withCredentials = true; + + if (options.json) { + options.headers.Accept = 'application/json'; + options.headers['Content-Type'] = options.headers['Content-Type'] || + 'application/json'; + if (options.body && + options.processData && + typeof options.body !== "string") { + options.body = JSON.stringify(options.body); + } + } + + if (options.binary) { + xhr.responseType = 'arraybuffer'; + } + + var createCookie = function (name, value, days) { + var expires = ""; + if (days) { + var date = new Date(); + date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); + expires = "; expires=" + date.toGMTString(); + } + document.cookie = name + "=" + value + expires + "; path=/"; + }; + + for (var key in options.headers) { + if (key === 'Cookie') { + var cookie = options.headers[key].split('='); + createCookie(cookie[0], cookie[1], 10); + } else { + xhr.setRequestHeader(key, options.headers[key]); + } + } + + if (!("body" in options)) { + options.body = null; + } + + var abortReq = function () { + if (requestCompleted) { + return; + } + xhr.abort(); + onError(xhr, callback); + }; + + xhr.onreadystatechange = function () { + if (xhr.readyState !== 4 || requestCompleted) { + return; + } + clearTimeout(timer); + if (xhr.status >= 200 && xhr.status < 300) { + var data; + if (options.binary) { + data = createBlob([xhr.response || ''], { + type: xhr.getResponseHeader('Content-Type') + }); + } else { + data = xhr.responseText; + } + onSuccess(data, xhr, callback); + } else { + onError(xhr, callback); + } + }; + + if (options.timeout > 0) { + timer = setTimeout(abortReq, options.timeout); + xhr.onprogress = function () { + clearTimeout(timer); + timer = setTimeout(abortReq, options.timeout); + }; + if (typeof hasUpload === 'undefined') { + // IE throws an error if you try to access it directly + hasUpload = Object.keys(xhr).indexOf('upload') !== -1; + } + if (hasUpload) { // does not exist in ie9 + xhr.upload.onprogress = xhr.onprogress; + } + } + if (options.body && (options.body instanceof Blob)) { + utils.readAsBinaryString(options.body, function (binary) { + xhr.send(utils.fixBinary(binary)); + }); + } else { + xhr.send(options.body); + } + return {abort: abortReq}; +} + +module.exports = ajax; + +},{"../utils":13,"./blob.js":3,"./errors":5}],3:[function(_dereq_,module,exports){ +(function (global){ +"use strict"; + +//Abstracts constructing a Blob object, so it also works in older +//browsers that don't support the native Blob constructor. (i.e. +//old QtWebKit versions, at least). +function createBlob(parts, properties) { + parts = parts || []; + properties = properties || {}; + try { + return new Blob(parts, properties); + } catch (e) { + if (e.name !== "TypeError") { + throw e; + } + var BlobBuilder = global.BlobBuilder || + global.MSBlobBuilder || + global.MozBlobBuilder || + global.WebKitBlobBuilder; + var builder = new BlobBuilder(); + for (var i = 0; i < parts.length; i += 1) { + builder.append(parts[i]); + } + return builder.getBlob(properties.type); + } +} + +module.exports = createBlob; + + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],4:[function(_dereq_,module,exports){ +'use strict'; +exports.Map = LazyMap; // TODO: use ES6 map +exports.Set = LazySet; // TODO: use ES6 set +// based on https://github.com/montagejs/collections +function LazyMap() { + this.store = {}; +} +LazyMap.prototype.mangle = function (key) { + if (typeof key !== "string") { + throw new TypeError("key must be a string but Got " + key); + } + return '$' + key; +}; +LazyMap.prototype.unmangle = function (key) { + return key.substring(1); +}; +LazyMap.prototype.get = function (key) { + var mangled = this.mangle(key); + if (mangled in this.store) { + return this.store[mangled]; + } else { + return void 0; + } +}; +LazyMap.prototype.set = function (key, value) { + var mangled = this.mangle(key); + this.store[mangled] = value; + return true; +}; +LazyMap.prototype.has = function (key) { + var mangled = this.mangle(key); + return mangled in this.store; +}; +LazyMap.prototype["delete"] = function (key) { + var mangled = this.mangle(key); + if (mangled in this.store) { + delete this.store[mangled]; + return true; + } + return false; +}; +LazyMap.prototype.forEach = function (cb) { + var self = this; + var keys = Object.keys(self.store); + keys.forEach(function (key) { + var value = self.store[key]; + key = self.unmangle(key); + cb(value, key); + }); +}; + +function LazySet(array) { + this.store = new LazyMap(); + + // init with an array + if (array && Array.isArray(array)) { + for (var i = 0, len = array.length; i < len; i++) { + this.add(array[i]); + } + } +} +LazySet.prototype.add = function (key) { + return this.store.set(key, true); +}; +LazySet.prototype.has = function (key) { + return this.store.has(key); +}; +LazySet.prototype["delete"] = function (key) { + return this.store["delete"](key); +}; +},{}],5:[function(_dereq_,module,exports){ +"use strict"; + +function PouchError(opts) { + this.status = opts.status; + this.name = opts.error; + this.message = opts.reason; + this.error = true; +} + +PouchError.prototype__proto__ = Error.prototype; + +PouchError.prototype.toString = function () { + return JSON.stringify({ + status: this.status, + name: this.name, + message: this.message + }); +}; + +exports.UNAUTHORIZED = new PouchError({ + status: 401, + error: 'unauthorized', + reason: "Name or password is incorrect." +}); +exports.MISSING_BULK_DOCS = new PouchError({ + status: 400, + error: 'bad_request', + reason: "Missing JSON list of 'docs'" +}); +exports.MISSING_DOC = new PouchError({ + status: 404, + error: 'not_found', + reason: 'missing' +}); +exports.REV_CONFLICT = new PouchError({ + status: 409, + error: 'conflict', + reason: 'Document update conflict' +}); +exports.INVALID_ID = new PouchError({ + status: 400, + error: 'invalid_id', + reason: '_id field must contain a string' +}); +exports.MISSING_ID = new PouchError({ + status: 412, + error: 'missing_id', + reason: '_id is required for puts' +}); +exports.RESERVED_ID = new PouchError({ + status: 400, + error: 'bad_request', + reason: 'Only reserved document ids may start with underscore.' +}); +exports.NOT_OPEN = new PouchError({ + status: 412, + error: 'precondition_failed', + reason: 'Database not open' +}); +exports.UNKNOWN_ERROR = new PouchError({ + status: 500, + error: 'unknown_error', + reason: 'Database encountered an unknown error' +}); +exports.BAD_ARG = new PouchError({ + status: 500, + error: 'badarg', + reason: 'Some query argument is invalid' +}); +exports.INVALID_REQUEST = new PouchError({ + status: 400, + error: 'invalid_request', + reason: 'Request was invalid' +}); +exports.QUERY_PARSE_ERROR = new PouchError({ + status: 400, + error: 'query_parse_error', + reason: 'Some query parameter is invalid' +}); +exports.DOC_VALIDATION = new PouchError({ + status: 500, + error: 'doc_validation', + reason: 'Bad special document member' +}); +exports.BAD_REQUEST = new PouchError({ + status: 400, + error: 'bad_request', + reason: 'Something wrong with the request' +}); +exports.NOT_AN_OBJECT = new PouchError({ + status: 400, + error: 'bad_request', + reason: 'Document must be a JSON object' +}); +exports.DB_MISSING = new PouchError({ + status: 404, + error: 'not_found', + reason: 'Database not found' +}); +exports.IDB_ERROR = new PouchError({ + status: 500, + error: 'indexed_db_went_bad', + reason: 'unknown' +}); +exports.WSQ_ERROR = new PouchError({ + status: 500, + error: 'web_sql_went_bad', + reason: 'unknown' +}); +exports.LDB_ERROR = new PouchError({ + status: 500, + error: 'levelDB_went_went_bad', + reason: 'unknown' +}); +exports.FORBIDDEN = new PouchError({ + status: 403, + error: 'forbidden', + reason: 'Forbidden by design doc validate_doc_update function' +}); +exports.error = function (error, reason, name) { + function CustomPouchError(msg) { + this.message = reason; + if (name) { + this.name = name; + } + } + CustomPouchError.prototype = error; + return new CustomPouchError(reason); +}; + +},{}],6:[function(_dereq_,module,exports){ +(function (process,global){ +'use strict'; + +var crypto = _dereq_('crypto'); +var Md5 = _dereq_('spark-md5'); +var setImmediateShim = global.setImmediate || global.setTimeout; +var MD5_CHUNK_SIZE = 32768; + +function sliceShim(arrayBuffer, begin, end) { + if (typeof arrayBuffer.slice === 'function') { + if (!begin) { + return arrayBuffer.slice(); + } else if (!end) { + return arrayBuffer.slice(begin); + } else { + return arrayBuffer.slice(begin, end); + } + } + // + // shim for IE courtesy of http://stackoverflow.com/a/21440217 + // + + //If `begin`/`end` is unspecified, Chrome assumes 0, so we do the same + //Chrome also converts the values to integers via flooring + begin = Math.floor(begin || 0); + end = Math.floor(end || 0); + + var len = arrayBuffer.byteLength; + + //If either `begin` or `end` is negative, it refers to an + //index from the end of the array, as opposed to from the beginning. + //The range specified by the `begin` and `end` values is clamped to the + //valid index range for the current array. + begin = begin < 0 ? Math.max(begin + len, 0) : Math.min(len, begin); + end = end < 0 ? Math.max(end + len, 0) : Math.min(len, end); + + //If the computed length of the new ArrayBuffer would be negative, it + //is clamped to zero. + if (end - begin <= 0) { + return new ArrayBuffer(0); + } + + var result = new ArrayBuffer(end - begin); + var resultBytes = new Uint8Array(result); + var sourceBytes = new Uint8Array(arrayBuffer, begin, end - begin); + + resultBytes.set(sourceBytes); + + return result; +} + +// convert a 64-bit int to a binary string +function intToString(int) { + var bytes = [ + (int & 0xff), + ((int >>> 8) & 0xff), + ((int >>> 16) & 0xff), + ((int >>> 24) & 0xff) + ]; + return bytes.map(function (byte) { + return String.fromCharCode(byte); + }).join(''); +} + +// convert an array of 64-bit ints into +// a base64-encoded string +function rawToBase64(raw) { + var res = ''; + for (var i = 0; i < raw.length; i++) { + res += intToString(raw[i]); + } + return global.btoa(res); +} + +module.exports = function (data, callback) { + if (!process.browser) { + var base64 = crypto.createHash('md5').update(data).digest('base64'); + callback(null, base64); + return; + } + var inputIsString = typeof data === 'string'; + var len = inputIsString ? data.length : data.byteLength; + var chunkSize = Math.min(MD5_CHUNK_SIZE, len); + var chunks = Math.ceil(len / chunkSize); + var currentChunk = 0; + var buffer = inputIsString ? new Md5() : new Md5.ArrayBuffer(); + + function append(buffer, data, start, end) { + if (inputIsString) { + buffer.appendBinary(data.substring(start, end)); + } else { + buffer.append(sliceShim(data, start, end)); + } + } + + function loadNextChunk() { + var start = currentChunk * chunkSize; + var end = start + chunkSize; + if ((start + chunkSize) >= data.size) { + end = data.size; + } + currentChunk++; + if (currentChunk < chunks) { + append(buffer, data, start, end); + setImmediateShim(loadNextChunk); + } else { + append(buffer, data, start, end); + var raw = buffer.end(true); + var base64 = rawToBase64(raw); + callback(null, base64); + buffer.destroy(); + } + } + loadNextChunk(); +}; + +}).call(this,_dereq_('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"_process":24,"crypto":16,"spark-md5":117}],7:[function(_dereq_,module,exports){ +'use strict'; + +var fs = _dereq_('fs'); +var path = _dereq_('path'); +var utils = _dereq_('../utils'); +var merge = _dereq_('../merge'); +var levelup = _dereq_('levelup'); +var through = _dereq_('through2').obj; +var leveldown = _dereq_("leveldown"); + +var stores = [ + 'document-store', + 'by-sequence', + 'attach-store', + 'attach-binary-store' +]; +function formatSeq(n) { + return ('0000000000000000' + n).slice(-16); +} +var UPDATE_SEQ_KEY = '_local_last_update_seq'; +var DOC_COUNT_KEY = '_local_doc_count'; +var UUID_KEY = '_local_uuid'; + +exports.toSublevel = function (name, db, callback) { + var base = path.resolve(name); + function move(store, index, cb) { + var storePath = path.join(base, store); + var opts; + if (index === 3) { + opts = { + valueEncoding: 'binary' + }; + } else { + opts = { + valueEncoding: 'json' + }; + } + var sub = db.sublevel(store, opts); + var orig = levelup(storePath, opts); + var from = orig.createReadStream(); + var to = sub.createWriteStream(); + from.on('end', function () { + orig.close(function (err) { + cb(err, storePath); + }); + }); + from.pipe(to); + } + fs.unlink(base + '.uuid', function (err) { + if (err) { + return callback(); + } + var todo = 4; + var done = []; + stores.forEach(function (store, i) { + move(store, i, function (err, storePath) { + if (err) { + return callback(err); + } + done.push(storePath); + if (!(--todo)) { + done.forEach(function (item) { + leveldown.destroy(item, function () { + if (++todo === done.length) { + fs.rmdir(base, callback); + } + }); + }); + } + }); + }); + }); +}; +exports.localAndMetaStores = function (db, stores, callback) { + var batches = []; + stores.bySeqStore.get(UUID_KEY, function (err, value) { + if (err) { + // no uuid key, so don't need to migrate; + return callback(); + } + batches.push({ + key: UUID_KEY, + value: value, + prefix: stores.metaStore, + type: 'put', + valueEncoding: 'json' + }); + batches.push({ + key: UUID_KEY, + prefix: stores.bySeqStore, + type: 'del' + }); + stores.bySeqStore.get(DOC_COUNT_KEY, function (err, value) { + if (value) { + // if no doc count key, + // just skip + // we can live with this + batches.push({ + key: DOC_COUNT_KEY, + value: value, + prefix: stores.metaStore, + type: 'put', + valueEncoding: 'json' + }); + batches.push({ + key: DOC_COUNT_KEY, + prefix: stores.bySeqStore, + type: 'del' + }); + } + stores.bySeqStore.get(UPDATE_SEQ_KEY, function (err, value) { + if (value) { + // if no UPDATE_SEQ_KEY + // just skip + // we've gone to far to stop. + batches.push({ + key: UPDATE_SEQ_KEY, + value: value, + prefix: stores.metaStore, + type: 'put', + valueEncoding: 'json' + }); + batches.push({ + key: UPDATE_SEQ_KEY, + prefix: stores.bySeqStore, + type: 'del' + }); + } + var deletedSeqs = {}; + stores.docStore.createReadStream({ + startKey: '_', + endKey: '_\xFF' + }).pipe(through(function (ch, _, next) { + if (!utils.isLocalId(ch.key)) { + return next(); + } + batches.push({ + key: ch.key, + prefix: stores.docStore, + type: 'del' + }); + var winner = merge.winningRev(ch.value); + Object.keys(ch.value.rev_map).forEach(function (key) { + if (key !== 'winner') { + this.push(formatSeq(ch.value.rev_map[key])); + } + }, this); + var winningSeq = ch.value.rev_map[winner]; + stores.bySeqStore.get(formatSeq(winningSeq), function (err, value) { + if (!err) { + batches.push({ + key: ch.key, + value: value, + prefix: stores.localStore, + type: 'put', + valueEncoding: 'json' + }); + } + next(); + }); + + })).pipe(through(function (seq, _, next) { + if (deletedSeqs[seq]) { + return next(); + } + deletedSeqs[seq] = true; + stores.bySeqStore.get(seq, function (err, resp) { + if (err || !utils.isLocalId(resp._id)) { + return next(); + } + batches.push({ + key: seq, + prefix: stores.bySeqStore, + type: 'del' + }); + next(); + }); + }, function (next) { + db.batch(batches, callback); + })); + }); + }); + }); + +}; +},{"../merge":10,"../utils":13,"fs":15,"leveldown":"leveldown","levelup":75,"path":23,"through2":132}],8:[function(_dereq_,module,exports){ +'use strict'; + +// originally parseUri 1.2.2, now patched by us +// (c) Steven Levithan <stevenlevithan.com> +// MIT License +var options = { + strictMode: false, + key: ["source", "protocol", "authority", "userInfo", "user", "password", + "host", "port", "relative", "path", "directory", "file", "query", + "anchor"], + q: { + name: "queryKey", + parser: /(?:^|&)([^&=]*)=?([^&]*)/g + }, + parser: { + /* jshint maxlen: false */ + strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, + loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ + } +}; +function parseUri(str) { + var o = options; + var m = o.parser[o.strictMode ? "strict" : "loose"].exec(str); + var uri = {}; + var i = 14; + + while (i--) { + var key = o.key[i]; + var value = m[i] || ""; + var encoded = ['user', 'password'].indexOf(key) !== -1; + uri[key] = encoded ? decodeURIComponent(value) : value; + } + + uri[o.q.name] = {}; + uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) { + if ($1) { + uri[o.q.name][$1] = $2; + } + }); + + return uri; +} + + +module.exports = parseUri; +},{}],9:[function(_dereq_,module,exports){ +"use strict"; + +// BEGIN Math.uuid.js + +/*! +Math.uuid.js (v1.4) +http://www.broofa.com +mailto:robert@broofa.com + +Copyright (c) 2010 Robert Kieffer +Dual licensed under the MIT and GPL licenses. +*/ + +/* + * Generate a random uuid. + * + * USAGE: Math.uuid(length, radix) + * length - the desired number of characters + * radix - the number of allowable values for each character. + * + * EXAMPLES: + * // No arguments - returns RFC4122, version 4 ID + * >>> Math.uuid() + * "92329D39-6F5C-4520-ABFC-AAB64544E172" + * + * // One argument - returns ID of the specified length + * >>> Math.uuid(15) // 15 character ID (default base=62) + * "VcydxgltxrVZSTV" + * + * // Two arguments - returns ID of the specified length, and radix. + * // (Radix must be <= 62) + * >>> Math.uuid(8, 2) // 8 character ID (base=2) + * "01001010" + * >>> Math.uuid(8, 10) // 8 character ID (base=10) + * "47473046" + * >>> Math.uuid(8, 16) // 8 character ID (base=16) + * "098F4D35" + */ +var chars = ( + '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' + + 'abcdefghijklmnopqrstuvwxyz' +).split(''); +function getValue(radix) { + return 0 | Math.random() * radix; +} +function uuid(len, radix) { + radix = radix || chars.length; + var out = ''; + var i = -1; + + if (len) { + // Compact form + while (++i < len) { + out += chars[getValue(radix)]; + } + return out; + } + // rfc4122, version 4 form + // Fill in random data. At i==19 set the high bits of clock sequence as + // per rfc4122, sec. 4.1.5 + while (++i < 36) { + switch (i) { + case 8: + case 13: + case 18: + case 23: + out += '-'; + break; + case 19: + out += chars[(getValue(16) & 0x3) | 0x8]; + break; + default: + out += chars[getValue(16)]; + } + } + + return out; +} + + + +module.exports = uuid; + + +},{}],10:[function(_dereq_,module,exports){ +'use strict'; +var extend = _dereq_('pouchdb-extend'); + + +// for a better overview of what this is doing, read: +// https://github.com/apache/couchdb/blob/master/src/couchdb/couch_key_tree.erl +// +// But for a quick intro, CouchDB uses a revision tree to store a documents +// history, A -> B -> C, when a document has conflicts, that is a branch in the +// tree, A -> (B1 | B2 -> C), We store these as a nested array in the format +// +// KeyTree = [Path ... ] +// Path = {pos: position_from_root, ids: Tree} +// Tree = [Key, Opts, [Tree, ...]], in particular single node: [Key, []] + +// Turn a path as a flat array into a tree with a single branch +function pathToTree(path) { + var doc = path.shift(); + var root = [doc.id, doc.opts, []]; + var leaf = root; + var nleaf; + + while (path.length) { + doc = path.shift(); + nleaf = [doc.id, doc.opts, []]; + leaf[2].push(nleaf); + leaf = nleaf; + } + return root; +} + +// Merge two trees together +// The roots of tree1 and tree2 must be the same revision +function mergeTree(in_tree1, in_tree2) { + var queue = [{tree1: in_tree1, tree2: in_tree2}]; + var conflicts = false; + while (queue.length > 0) { + var item = queue.pop(); + var tree1 = item.tree1; + var tree2 = item.tree2; + + if (tree1[1].status || tree2[1].status) { + tree1[1].status = + (tree1[1].status === 'available' || + tree2[1].status === 'available') ? 'available' : 'missing'; + } + + for (var i = 0; i < tree2[2].length; i++) { + if (!tree1[2][0]) { + conflicts = 'new_leaf'; + tree1[2][0] = tree2[2][i]; + continue; + } + + var merged = false; + for (var j = 0; j < tree1[2].length; j++) { + if (tree1[2][j][0] === tree2[2][i][0]) { + queue.push({tree1: tree1[2][j], tree2: tree2[2][i]}); + merged = true; + } + } + if (!merged) { + conflicts = 'new_branch'; + tree1[2].push(tree2[2][i]); + tree1[2].sort(); + } + } + } + return {conflicts: conflicts, tree: in_tree1}; +} + +function doMerge(tree, path, dontExpand) { + var restree = []; + var conflicts = false; + var merged = false; + var res; + + if (!tree.length) { + return {tree: [path], conflicts: 'new_leaf'}; + } + + tree.forEach(function (branch) { + if (branch.pos === path.pos && branch.ids[0] === path.ids[0]) { + // Paths start at the same position and have the same root, so they need + // merged + res = mergeTree(branch.ids, path.ids); + restree.push({pos: branch.pos, ids: res.tree}); + conflicts = conflicts || res.conflicts; + merged = true; + } else if (dontExpand !== true) { + // The paths start at a different position, take the earliest path and + // traverse up until it as at the same point from root as the path we + // want to merge. If the keys match we return the longer path with the + // other merged After stemming we dont want to expand the trees + + var t1 = branch.pos < path.pos ? branch : path; + var t2 = branch.pos < path.pos ? path : branch; + var diff = t2.pos - t1.pos; + + var candidateParents = []; + + var trees = []; + trees.push({ids: t1.ids, diff: diff, parent: null, parentIdx: null}); + while (trees.length > 0) { + var item = trees.pop(); + if (item.diff === 0) { + if (item.ids[0] === t2.ids[0]) { + candidateParents.push(item); + } + continue; + } + if (!item.ids) { + continue; + } + /*jshint loopfunc:true */ + item.ids[2].forEach(function (el, idx) { + trees.push( + {ids: el, diff: item.diff - 1, parent: item.ids, parentIdx: idx}); + }); + } + + var el = candidateParents[0]; + + if (!el) { + restree.push(branch); + } else { + res = mergeTree(el.ids, t2.ids); + el.parent[2][el.parentIdx] = res.tree; + restree.push({pos: t1.pos, ids: t1.ids}); + conflicts = conflicts || res.conflicts; + merged = true; + } + } else { + restree.push(branch); + } + }); + + // We didnt find + if (!merged) { + restree.push(path); + } + + restree.sort(function (a, b) { + return a.pos - b.pos; + }); + + return { + tree: restree, + conflicts: conflicts || 'internal_node' + }; +} + +// To ensure we dont grow the revision tree infinitely, we stem old revisions +function stem(tree, depth) { + // First we break out the tree into a complete list of root to leaf paths, + // we cut off the start of the path and generate a new set of flat trees + var stemmedPaths = PouchMerge.rootToLeaf(tree).map(function (path) { + var stemmed = path.ids.slice(-depth); + return { + pos: path.pos + (path.ids.length - stemmed.length), + ids: pathToTree(stemmed) + }; + }); + // Then we remerge all those flat trees together, ensuring that we dont + // connect trees that would go beyond the depth limit + return stemmedPaths.reduce(function (prev, current, i, arr) { + return doMerge(prev, current, true).tree; + }, [stemmedPaths.shift()]); +} + +var PouchMerge = {}; + +PouchMerge.merge = function (tree, path, depth) { + // Ugh, nicer way to not modify arguments in place? + tree = extend(true, [], tree); + path = extend(true, {}, path); + var newTree = doMerge(tree, path); + return { + tree: stem(newTree.tree, depth), + conflicts: newTree.conflicts + }; +}; + +// We fetch all leafs of the revision tree, and sort them based on tree length +// and whether they were deleted, undeleted documents with the longest revision +// tree (most edits) win +// The final sort algorithm is slightly documented in a sidebar here: +// http://guide.couchdb.org/draft/conflicts.html +PouchMerge.winningRev = function (metadata) { + var leafs = []; + PouchMerge.traverseRevTree(metadata.rev_tree, + function (isLeaf, pos, id, something, opts) { + if (isLeaf) { + leafs.push({pos: pos, id: id, deleted: !!opts.deleted}); + } + }); + leafs.sort(function (a, b) { + if (a.deleted !== b.deleted) { + return a.deleted > b.deleted ? 1 : -1; + } + if (a.pos !== b.pos) { + return b.pos - a.pos; + } + return a.id < b.id ? 1 : -1; + }); + + return leafs[0].pos + '-' + leafs[0].id; +}; + +// Pretty much all below can be combined into a higher order function to +// traverse revisions +// The return value from the callback will be passed as context to all +// children of that node +PouchMerge.traverseRevTree = function (revs, callback) { + var toVisit = revs.slice(); + + var node; + while ((node = toVisit.pop())) { + var pos = node.pos; + var tree = node.ids; + var branches = tree[2]; + var newCtx = + callback(branches.length === 0, pos, tree[0], node.ctx, tree[1]); + for (var i = 0, len = branches.length; i < len; i++) { + toVisit.push({pos: pos + 1, ids: branches[i], ctx: newCtx}); + } + } +}; + +PouchMerge.collectLeaves = function (revs) { + var leaves = []; + PouchMerge.traverseRevTree(revs, function (isLeaf, pos, id, acc, opts) { + if (isLeaf) { + leaves.unshift({rev: pos + "-" + id, pos: pos, opts: opts}); + } + }); + leaves.sort(function (a, b) { + return b.pos - a.pos; + }); + leaves.map(function (leaf) { delete leaf.pos; }); + return leaves; +}; + +// returns revs of all conflicts that is leaves such that +// 1. are not deleted and +// 2. are different than winning revision +PouchMerge.collectConflicts = function (metadata) { + var win = PouchMerge.winningRev(metadata); + var leaves = PouchMerge.collectLeaves(metadata.rev_tree); + var conflicts = []; + leaves.forEach(function (leaf) { + if (leaf.rev !== win && !leaf.opts.deleted) { + conflicts.push(leaf.rev); + } + }); + return conflicts; +}; + +PouchMerge.rootToLeaf = function (tree) { + var paths = []; + PouchMerge.traverseRevTree(tree, function (isLeaf, pos, id, history, opts) { + history = history ? history.slice(0) : []; + history.push({id: id, opts: opts}); + if (isLeaf) { + var rootPos = pos + 1 - history.length; + paths.unshift({pos: rootPos, ids: history}); + } + return history; + }); + return paths; +}; + + +module.exports = PouchMerge; + +},{"pouchdb-extend":116}],11:[function(_dereq_,module,exports){ +(function (global){ +"use strict"; + +var adapterConfig = _dereq_('adapter-config'); +var adapterName = adapterConfig.name; +var adapter = _dereq_('./levelalt')(adapterConfig); +var PouchDB = global.PouchDB || _dereq_('pouchdb'); +PouchDB.adapter(adapterName, adapter); +PouchDB.preferredAdapters.push(adapterName); + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./levelalt":12,"adapter-config":"adapter-config","pouchdb":"pouchdb"}],12:[function(_dereq_,module,exports){ +'use strict'; + +var LevelPouch = _dereq_('../adapters/leveldb'); +var leveldown = _dereq_('leveldown'); +var utils = _dereq_('../utils'); +module.exports = altFactory; +function altFactory(adapterConfig) { + function LevelPouchAlt(opts, callback) { + var _opts = utils.extend({ + db: leveldown + }, opts); + + LevelPouch.call(this, _opts, callback); + } + + // overrides for normal LevelDB behavior on Node + LevelPouchAlt.valid = function () { + return adapterConfig.valid(); + }; + LevelPouchAlt.use_prefix = adapterConfig.use_prefix; + + LevelPouchAlt.destroy = utils.toPromise(function (name, opts, callback) { + if (typeof opts === 'function') { + callback = opts; + opts = {}; + } + var _opts = utils.extend({ + db: leveldown + }, opts); + + return LevelPouch.destroy(name, _opts, callback); + }); + return LevelPouchAlt; + +} +},{"../adapters/leveldb":1,"../utils":13,"leveldown":"leveldown"}],13:[function(_dereq_,module,exports){ +(function (process,global){ +/*jshint strict: false */ +/*global chrome */ +var merge = _dereq_('./merge'); +exports.extend = _dereq_('pouchdb-extend'); +exports.ajax = _dereq_('./deps/ajax'); +exports.createBlob = _dereq_('./deps/blob'); +exports.uuid = _dereq_('./deps/uuid'); +exports.getArguments = _dereq_('argsarray'); +var buffer = _dereq_('./deps/buffer'); +var errors = _dereq_('./deps/errors'); +var EventEmitter = _dereq_('events').EventEmitter; +var collections = _dereq_('./deps/collections'); +exports.Map = collections.Map; +exports.Set = collections.Set; + +if (typeof global.Promise === 'function') { + exports.Promise = global.Promise; +} else { + exports.Promise = _dereq_('bluebird'); +} +var Promise = exports.Promise; + +function toObject(array) { + var obj = {}; + array.forEach(function (item) { obj[item] = true; }); + return obj; +} +// List of top level reserved words for doc +var reservedWords = toObject([ + '_id', + '_rev', + '_attachments', + '_deleted', + '_revisions', + '_revs_info', + '_conflicts', + '_deleted_conflicts', + '_local_seq', + '_rev_tree', + //replication documents + '_replication_id', + '_replication_state', + '_replication_state_time', + '_replication_state_reason', + '_replication_stats' +]); + +// List of reserved words that should end up the document +var dataWords = toObject([ + '_attachments', + //replication documents + '_replication_id', + '_replication_state', + '_replication_state_time', + '_replication_state_reason', + '_replication_stats' +]); + +exports.lastIndexOf = function (str, char) { + for (var i = str.length - 1; i >= 0; i--) { + if (str.charAt(i) === char) { + return i; + } + } + return -1; +}; + +exports.clone = function (obj) { + return exports.extend(true, {}, obj); +}; + +// like underscore/lodash _.pick() +exports.pick = function (obj, arr) { + var res = {}; + for (var i = 0, len = arr.length; i < len; i++) { + var prop = arr[i]; + res[prop] = obj[prop]; + } + return res; +}; + +exports.inherits = _dereq_('inherits'); + +// Determine id an ID is valid +// - invalid IDs begin with an underescore that does not begin '_design' or +// '_local' +// - any other string value is a valid id +// Returns the specific error object for each case +exports.invalidIdError = function (id) { + var err; + if (!id) { + err = new TypeError(errors.MISSING_ID.message); + err.status = 412; + } else if (typeof id !== 'string') { + err = new TypeError(errors.INVALID_ID.message); + err.status = 400; + } else if (/^_/.test(id) && !(/^_(design|local)/).test(id)) { + err = new TypeError(errors.RESERVED_ID.message); + err.status = 400; + } + if (err) { + throw err; + } +}; + +function isChromeApp() { + return (typeof chrome !== "undefined" && + typeof chrome.storage !== "undefined" && + typeof chrome.storage.local !== "undefined"); +} + +// Pretty dumb name for a function, just wraps callback calls so we dont +// to if (callback) callback() everywhere +exports.call = exports.getArguments(function (args) { + if (!args.length) { + return; + } + var fun = args.shift(); + if (typeof fun === 'function') { + fun.apply(this, args); + } +}); + +exports.isLocalId = function (id) { + return (/^_local/).test(id); +}; + +// check if a specific revision of a doc has been deleted +// - metadata: the metadata object from the doc store +// - rev: (optional) the revision to check. defaults to winning revision +exports.isDeleted = function (metadata, rev) { + if (!rev) { + rev = merge.winningRev(metadata); + } + var dashIndex = rev.indexOf('-'); + if (dashIndex !== -1) { + rev = rev.substring(dashIndex + 1); + } + var deleted = false; + merge.traverseRevTree(metadata.rev_tree, + function (isLeaf, pos, id, acc, opts) { + if (id === rev) { + deleted = !!opts.deleted; + } + }); + + return deleted; +}; + +exports.revExists = function (metadata, rev) { + var found = false; + merge.traverseRevTree(metadata.rev_tree, function (leaf, pos, id, acc, opts) { + if ((pos + '-' + id) === rev) { + found = true; + } + }); + return found; +}; + +exports.filterChange = function filterChange(opts) { + var req = {}; + var hasFilter = opts.filter && typeof opts.filter === 'function'; + req.query = opts.query_params; + + return function filter(change) { + if (opts.filter && hasFilter && !opts.filter.call(this, change.doc, req)) { + return false; + } + if (!opts.include_docs) { + delete change.doc; + } else if (!opts.attachments) { + for (var att in change.doc._attachments) { + if (change.doc._attachments.hasOwnProperty(att)) { + change.doc._attachments[att].stub = true; + } + } + } + return true; + }; +}; + +// Preprocess documents, parse their revisions, assign an id and a +// revision for new writes that are missing them, etc +exports.parseDoc = function (doc, newEdits) { + + var nRevNum; + var newRevId; + var revInfo; + var error; + var opts = {status: 'available'}; + if (doc._deleted) { + opts.deleted = true; + } + + if (newEdits) { + if (!doc._id) { + doc._id = exports.uuid(); + } + newRevId = exports.uuid(32, 16).toLowerCase(); + if (doc._rev) { + revInfo = /^(\d+)-(.+)$/.exec(doc._rev); + if (!revInfo) { + error = new Error('bad_request'); + error.message = 'Invalid rev format'; + error.error = true; + return error; + } + doc._rev_tree = [{ + pos: parseInt(revInfo[1], 10), + ids: [revInfo[2], {status: 'missing'}, [[newRevId, opts, []]]] + }]; + nRevNum = parseInt(revInfo[1], 10) + 1; + } else { + doc._rev_tree = [{ + pos: 1, + ids : [newRevId, opts, []] + }]; + nRevNum = 1; + } + } else { + if (doc._revisions) { + doc._rev_tree = [{ + pos: doc._revisions.start - doc._revisions.ids.length + 1, + ids: doc._revisions.ids.reduce(function (acc, x) { + if (acc === null) { + return [x, opts, []]; + } else { + return [x, {status: 'missing'}, [acc]]; + } + }, null) + }]; + nRevNum = doc._revisions.start; + newRevId = doc._revisions.ids[0]; + } + if (!doc._rev_tree) { + revInfo = /^(\d+)-(.+)$/.exec(doc._rev); + if (!revInfo) { + error = new Error('bad_request'); + error.message = 'Invalid rev format'; + error.error = true; + return error; + } + nRevNum = parseInt(revInfo[1], 10); + newRevId = revInfo[2]; + doc._rev_tree = [{ + pos: parseInt(revInfo[1], 10), + ids: [revInfo[2], opts, []] + }]; + } + } + + exports.invalidIdError(doc._id); + + doc._rev = [nRevNum, newRevId].join('-'); + + var result = {metadata : {}, data : {}}; + for (var key in doc) { + if (doc.hasOwnProperty(key)) { + var specialKey = key[0] === '_'; + if (specialKey && !reservedWords[key]) { + error = new Error(errors.DOC_VALIDATION.message + ': ' + key); + error.status = errors.DOC_VALIDATION.status; + throw error; + } else if (specialKey && !dataWords[key]) { + result.metadata[key.slice(1)] = doc[key]; + } else { + result.data[key] = doc[key]; + } + } + } + return result; +}; + +exports.isCordova = function () { + return (typeof cordova !== "undefined" || + typeof PhoneGap !== "undefined" || + typeof phonegap !== "undefined"); +}; + +exports.hasLocalStorage = function () { + if (isChromeApp()) { + return false; + } + try { + return global.localStorage; + } catch (e) { + return false; + } +}; +exports.Changes = Changes; +exports.inherits(Changes, EventEmitter); +function Changes() { + if (!(this instanceof Changes)) { + return new Changes(); + } + var self = this; + EventEmitter.call(this); + this.isChrome = isChromeApp(); + this.listeners = {}; + this.hasLocal = false; + if (!this.isChrome) { + this.hasLocal = exports.hasLocalStorage(); + } + if (this.isChrome) { + chrome.storage.onChanged.addListener(function (e) { + // make sure it's event addressed to us + if (e.db_name != null) { + //object only has oldValue, newValue members + self.emit(e.dbName.newValue); + } + }); + } else if (this.hasLocal) { + if (global.addEventListener) { + global.addEventListener("storage", function (e) { + self.emit(e.key); + }); + } else { + global.attachEvent("storage", function (e) { + self.emit(e.key); + }); + } + } + +} +Changes.prototype.addListener = function (dbName, id, db, opts) { + if (this.listeners[id]) { + return; + } + function eventFunction() { + db.changes({ + include_docs: opts.include_docs, + attachments: opts.attachments, + conflicts: opts.conflicts, + continuous: false, + descending: false, + filter: opts.filter, + doc_ids: opts.doc_ids, + view: opts.view, + since: opts.since, + query_params: opts.query_params, + onChange: function (c) { + if (c.seq > opts.since && !opts.cancelled) { + opts.since = c.seq; + exports.call(opts.onChange, c); + } + } + }); + } + this.listeners[id] = eventFunction; + this.on(dbName, eventFunction); +}; + +Changes.prototype.removeListener = function (dbName, id) { + if (!(id in this.listeners)) { + return; + } + EventEmitter.prototype.removeListener.call(this, dbName, + this.listeners[id]); +}; + + +Changes.prototype.notifyLocalWindows = function (dbName) { + //do a useless change on a storage thing + //in order to get other windows's listeners to activate + if (this.isChrome) { + chrome.storage.local.set({dbName: dbName}); + } else if (this.hasLocal) { + localStorage[dbName] = (localStorage[dbName] === "a") ? "b" : "a"; + } +}; + +Changes.prototype.notify = function (dbName) { + this.emit(dbName); + this.notifyLocalWindows(dbName); +}; + +if (!process.browser || !('atob' in global)) { + exports.atob = function (str) { + var base64 = new buffer(str, 'base64'); + // Node.js will just skip the characters it can't encode instead of + // throwing and exception + if (base64.toString('base64') !== str) { + throw ("Cannot base64 encode full string"); + } + return base64.toString('binary'); + }; +} else { + exports.atob = function (str) { + return atob(str); + }; +} + +if (!process.browser || !('btoa' in global)) { + exports.btoa = function (str) { + return new buffer(str, 'binary').toString('base64'); + }; +} else { + exports.btoa = function (str) { + return btoa(str); + }; +} + +// From http://stackoverflow.com/questions/14967647/ (continues on next line) +// encode-decode-image-with-base64-breaks-image (2013-04-21) +exports.fixBinary = function (bin) { + if (!process.browser) { + // don't need to do this in Node + return bin; + } + + var length = bin.length; + var buf = new ArrayBuffer(length); + var arr = new Uint8Array(buf); + for (var i = 0; i < length; i++) { + arr[i] = bin.charCodeAt(i); + } + return buf; +}; + +// shim for browsers that don't support it +exports.readAsBinaryString = function (blob, callback) { + var reader = new FileReader(); + var hasBinaryString = typeof reader.readAsBinaryString === 'function'; + reader.onloadend = function (e) { + var result = e.target.result || ''; + if (hasBinaryString) { + return callback(result); + } + callback(exports.arrayBufferToBinaryString(result)); + }; + if (hasBinaryString) { + reader.readAsBinaryString(blob); + } else { + reader.readAsArrayBuffer(blob); + } +}; + +exports.once = function (fun) { + var called = false; + return exports.getArguments(function (args) { + if (called) { + throw new Error('once called more than once'); + } else { + called = true; + fun.apply(this, args); + } + }); +}; + +exports.toPromise = function (func) { + //create the function we will be returning + return exports.getArguments(function (args) { + var self = this; + var tempCB = + (typeof args[args.length - 1] === 'function') ? args.pop() : false; + // if the last argument is a function, assume its a callback + var usedCB; + if (tempCB) { + // if it was a callback, create a new callback which calls it, + // but do so async so we don't trap any errors + usedCB = function (err, resp) { + process.nextTick(function () { + tempCB(err, resp); + }); + }; + } + var promise = new Promise(function (fulfill, reject) { + var resp; + try { + var callback = exports.once(function (err, mesg) { + if (err) { + reject(err); + } else { + fulfill(mesg); + } + }); + // create a callback for this invocation + // apply the function in the orig context + args.push(callback); + resp = func.apply(self, args); + if (resp && typeof resp.then === 'function') { + fulfill(resp); + } + } catch (e) { + reject(e); + } + }); + // if there is a callback, call it back + if (usedCB) { + promise.then(function (result) { + usedCB(null, result); + }, usedCB); + } + promise.cancel = function () { + return this; + }; + return promise; + }); +}; + +exports.adapterFun = function (name, callback) { + var log = _dereq_('debug')('pouchdb:api'); + + function logApiCall(self, name, args) { + if (!log.enabled) { + return; + } + var logArgs = [self._db_name, name]; + for (var i = 0; i < args.length - 1; i++) { + logArgs.push(args[i]); + } + log.apply(null, logArgs); + + // override the callback itself to log the response + var origCallback = args[args.length - 1]; + args[args.length - 1] = function (err, res) { + var responseArgs = [self._db_name, name]; + responseArgs = responseArgs.concat( + err ? ['error', err] : ['success', res] + ); + log.apply(null, responseArgs); + origCallback(err, res); + }; + } + + + return exports.toPromise(exports.getArguments(function (args) { + if (this._closed) { + return Promise.reject(new Error('database is closed')); + } + var self = this; + logApiCall(self, name, args); + if (!this.taskqueue.isReady) { + return new exports.Promise(function (fulfill, reject) { + self.taskqueue.addTask(function (failed) { + if (failed) { + reject(failed); + } else { + fulfill(self[name].apply(self, args)); + } + }); + }); + } + return callback.apply(this, args); + })); +}; + +//Can't find original post, but this is close +//http://stackoverflow.com/questions/6965107/ (continues on next line) +//converting-between-strings-and-arraybuffers +exports.arrayBufferToBinaryString = function (buffer) { + var binary = ""; + var bytes = new Uint8Array(buffer); + var length = bytes.byteLength; + for (var i = 0; i < length; i++) { + binary += String.fromCharCode(bytes[i]); + } + return binary; +}; + +exports.cancellableFun = function (fun, self, opts) { + + opts = opts ? exports.clone(true, {}, opts) : {}; + + var emitter = new EventEmitter(); + var oldComplete = opts.complete || function () { }; + var complete = opts.complete = exports.once(function (err, resp) { + if (err) { + oldComplete(err); + } else { + emitter.emit('end', resp); + oldComplete(null, resp); + } + emitter.removeAllListeners(); + }); + var oldOnChange = opts.onChange || function () {}; + var lastChange = 0; + self.on('destroyed', function () { + emitter.removeAllListeners(); + }); + opts.onChange = function (change) { + oldOnChange(change); + if (change.seq <= lastChange) { + return; + } + lastChange = change.seq; + emitter.emit('change', change); + if (change.deleted) { + emitter.emit('delete', change); + } else if (change.changes.length === 1 && + change.changes[0].rev.slice(0, 1) === '1-') { + emitter.emit('create', change); + } else { + emitter.emit('update', change); + } + }; + var promise = new Promise(function (fulfill, reject) { + opts.complete = function (err, res) { + if (err) { + reject(err); + } else { + fulfill(res); + } + }; + }); + + promise.then(function (result) { + complete(null, result); + }, complete); + + // this needs to be overwridden by caller, dont fire complete until + // the task is ready + promise.cancel = function () { + promise.isCancelled = true; + if (self.taskqueue.isReady) { + opts.complete(null, {status: 'cancelled'}); + } + }; + + if (!self.taskqueue.isReady) { + self.taskqueue.addTask(function () { + if (promise.isCancelled) { + opts.complete(null, {status: 'cancelled'}); + } else { + fun(self, opts, promise); + } + }); + } else { + fun(self, opts, promise); + } + promise.on = emitter.on.bind(emitter); + promise.once = emitter.once.bind(emitter); + promise.addListener = emitter.addListener.bind(emitter); + promise.removeListener = emitter.removeListener.bind(emitter); + promise.removeAllListeners = emitter.removeAllListeners.bind(emitter); + promise.setMaxListeners = emitter.setMaxListeners.bind(emitter); + promise.listeners = emitter.listeners.bind(emitter); + promise.emit = emitter.emit.bind(emitter); + return promise; +}; + +exports.MD5 = exports.toPromise(_dereq_('./deps/md5')); + +// designed to give info to browser users, who are disturbed +// when they see 404s in the console +exports.explain404 = function (str) { + if (process.browser && 'console' in global && 'info' in console) { + console.info('The above 404 is totally normal. ' + str); + } +}; + +exports.parseUri = _dereq_('./deps/parse-uri'); + +exports.compare = function (left, right) { + return left < right ? -1 : left > right ? 1 : 0; +}; + +exports.updateDoc = function updateDoc(prev, docInfo, results, + i, cb, write, newEdits) { + + if (exports.revExists(prev, docInfo.metadata.rev)) { + results[i] = docInfo; + return cb(); + } + + var previouslyDeleted = exports.isDeleted(prev); + var deleted = exports.isDeleted(docInfo.metadata); + var isRoot = /^1-/.test(docInfo.metadata.rev); + + if (previouslyDeleted && !deleted && newEdits && isRoot) { + var newDoc = docInfo.data; + newDoc._rev = merge.winningRev(prev); + newDoc._id = docInfo.metadata.id; + docInfo = exports.parseDoc(newDoc, newEdits); + } + + var merged = merge.merge(prev.rev_tree, docInfo.metadata.rev_tree[0], 1000); + + var inConflict = newEdits && (((previouslyDeleted && deleted) || + (!previouslyDeleted && merged.conflicts !== 'new_leaf') || + (previouslyDeleted && !deleted && merged.conflicts === 'new_branch'))); + + if (inConflict) { + var err = errors.REV_CONFLICT; + results[i] = err; + return cb(); + } + + docInfo.metadata.rev_tree = merged.tree; + + // recalculate + var winningRev = merge.winningRev(docInfo.metadata); + deleted = exports.isDeleted(docInfo.metadata, winningRev); + + write(docInfo, winningRev, deleted, cb, true, i); +}; + +exports.processDocs = function processDocs(docInfos, api, fetchedDocs, + tx, results, writeDoc, opts) { + + if (!docInfos.length) { + return; + } + + function insertDoc(docInfo, resultsIdx, callback) { + // Cant insert new deleted documents + var winningRev = merge.winningRev(docInfo.metadata); + var deleted = exports.isDeleted(docInfo.metadata, winningRev); + if ('was_delete' in opts && deleted) { + results[resultsIdx] = errors.MISSING_DOC; + return callback(); + } + writeDoc(docInfo, winningRev, deleted, callback, false, resultsIdx); + } + + var newEdits = opts.new_edits; + var idsToDocs = new exports.Map(); + + docInfos.forEach(function (currentDoc, resultsIdx) { + + if (currentDoc._id && exports.isLocalId(currentDoc._id)) { + api[currentDoc._deleted ? '_removeLocal' : '_putLocal']( + currentDoc, {ctx: tx}, function (err, resp) { + if (err) { + results[resultsIdx] = err; + } else { + results[resultsIdx] = {}; + } + }); + return; + } + + var id = currentDoc.metadata.id; + if (idsToDocs.has(id)) { + idsToDocs.get(id).push([currentDoc, resultsIdx]); + } else { + idsToDocs.set(id, [[currentDoc, resultsIdx]]); + } + }); + + // in the case of new_edits, the user can provide multiple docs + // with the same id. these need to be processed sequentially + idsToDocs.forEach(function (docs, id) { + var numDone = 0; + + function docWritten() { + if (++numDone < docs.length) { + nextDoc(); + } + } + function nextDoc() { + var value = docs[numDone]; + var currentDoc = value[0]; + var resultsIdx = value[1]; + + if (fetchedDocs.has(id)) { + exports.updateDoc(fetchedDocs.get(id), currentDoc, results, + resultsIdx, docWritten, writeDoc, newEdits); + } else { + insertDoc(currentDoc, resultsIdx, docWritten); + } + } + nextDoc(); + }); +}; + +exports.preprocessAttachments = function preprocessAttachments( + docInfos, blobType, callback) { + + if (!docInfos.length) { + return callback(); + } + + var docv = 0; + + function parseBase64(data) { + try { + return exports.atob(data); + } catch (e) { + var err = errors.error(errors.BAD_ARG, + "Attachments need to be base64 encoded"); + return {error: err}; + } + } + + function preprocessAttachment(att, callback) { + if (att.stub) { + return callback(); + } + if (typeof att.data === 'string') { + // input is a base64 string + + var asBinary = parseBase64(att.data); + if (asBinary.error) { + return callback(asBinary.error); + } + + att.length = asBinary.length; + if (blobType === 'blob') { + att.data = exports.createBlob([exports.fixBinary(asBinary)], + {type: att.content_type}); + } else if (blobType === 'base64') { + att.data = exports.btoa(asBinary); + } else { // binary + att.data = asBinary; + } + exports.MD5(asBinary).then(function (result) { + att.digest = 'md5-' + result; + callback(); + }); + } else { // input is a blob + exports.readAsBinaryString(att.data, function (binary) { + if (blobType === 'binary') { + att.data = binary; + } else if (blobType === 'base64') { + att.data = exports.btoa(binary); + } + exports.MD5(binary).then(function (result) { + att.digest = 'md5-' + result; + att.length = binary.length; + callback(); + }); + }); + } + } + + var overallErr; + + docInfos.forEach(function (docInfo) { + var attachments = docInfo.data && docInfo.data._attachments ? + Object.keys(docInfo.data._attachments) : []; + var recv = 0; + + if (!attachments.length) { + return done(); + } + + function processedAttachment(err) { + overallErr = err; + recv++; + if (recv === attachments.length) { + done(); + } + } + + for (var key in docInfo.data._attachments) { + if (docInfo.data._attachments.hasOwnProperty(key)) { + preprocessAttachment(docInfo.data._attachments[key], + processedAttachment); + } + } + }); + + function done() { + docv++; + if (docInfos.length === docv) { + if (overallErr) { + callback(overallErr); + } else { + callback(); + } + } + } +}; +}).call(this,_dereq_('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./deps/ajax":2,"./deps/blob":3,"./deps/buffer":16,"./deps/collections":4,"./deps/errors":5,"./deps/md5":6,"./deps/parse-uri":8,"./deps/uuid":9,"./merge":10,"_process":24,"argsarray":14,"bluebird":101,"debug":40,"events":21,"inherits":44,"pouchdb-extend":116}],14:[function(_dereq_,module,exports){ +'use strict'; + +module.exports = argsArray; + +function argsArray(fun) { + return function () { + var len = arguments.length; + if (len) { + var args = []; + var i = -1; + while (++i < len) { + args[i] = arguments[i]; + } + return fun.call(this, args); + } else { + return fun.call(this, []); + } + }; +} +},{}],15:[function(_dereq_,module,exports){ + +},{}],16:[function(_dereq_,module,exports){ +module.exports=_dereq_(15) +},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/lib/_empty.js":15}],17:[function(_dereq_,module,exports){ +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org> + * @license MIT + */ + +var base64 = _dereq_('base64-js') +var ieee754 = _dereq_('ieee754') +var isArray = _dereq_('is-array') + +exports.Buffer = Buffer +exports.SlowBuffer = Buffer +exports.INSPECT_MAX_BYTES = 50 +Buffer.poolSize = 8192 // not used by this implementation + +var kMaxLength = 0x3fffffff + +/** + * If `Buffer.TYPED_ARRAY_SUPPORT`: + * === true Use Uint8Array implementation (fastest) + * === false Use Object implementation (most compatible, even IE6) + * + * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, + * Opera 11.6+, iOS 4.2+. + * + * Note: + * + * - Implementation must support adding new properties to `Uint8Array` instances. + * Firefox 4-29 lacked support, fixed in Firefox 30+. + * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. + * + * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. + * + * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of + * incorrect length in some situations. + * + * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they will + * get the Object implementation, which is slower but will work correctly. + */ +Buffer.TYPED_ARRAY_SUPPORT = (function () { + try { + var buf = new ArrayBuffer(0) + var arr = new Uint8Array(buf) + arr.foo = function () { return 42 } + return 42 === arr.foo() && // typed array instances can be augmented + typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` + new Uint8Array(1).subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` + } catch (e) { + return false + } +})() + +/** + * Class: Buffer + * ============= + * + * The Buffer constructor returns instances of `Uint8Array` that are augmented + * with function properties for all the node `Buffer` API functions. We use + * `Uint8Array` so that square bracket notation works as expected -- it returns + * a single octet. + * + * By augmenting the instances, we can avoid modifying the `Uint8Array` + * prototype. + */ +function Buffer (subject, encoding, noZero) { + if (!(this instanceof Buffer)) + return new Buffer(subject, encoding, noZero) + + var type = typeof subject + + // Find the length + var length + if (type === 'number') + length = subject > 0 ? subject >>> 0 : 0 + else if (type === 'string') { + if (encoding === 'base64') + subject = base64clean(subject) + length = Buffer.byteLength(subject, encoding) + } else if (type === 'object' && subject !== null) { // assume object is array-like + if (subject.type === 'Buffer' && isArray(subject.data)) + subject = subject.data + length = +subject.length > 0 ? Math.floor(+subject.length) : 0 + } else + throw new TypeError('must start with number, buffer, array or string') + + if (this.length > kMaxLength) + throw new RangeError('Attempt to allocate Buffer larger than maximum ' + + 'size: 0x' + kMaxLength.toString(16) + ' bytes') + + var buf + if (Buffer.TYPED_ARRAY_SUPPORT) { + // Preferred: Return an augmented `Uint8Array` instance for best performance + buf = Buffer._augment(new Uint8Array(length)) + } else { + // Fallback: Return THIS instance of Buffer (created by `new`) + buf = this + buf.length = length + buf._isBuffer = true + } + + var i + if (Buffer.TYPED_ARRAY_SUPPORT && typeof subject.byteLength === 'number') { + // Speed optimization -- use set if we're copying from a typed array + buf._set(subject) + } else if (isArrayish(subject)) { + // Treat array-ish objects as a byte array + if (Buffer.isBuffer(subject)) { + for (i = 0; i < length; i++) + buf[i] = subject.readUInt8(i) + } else { + for (i = 0; i < length; i++) + buf[i] = ((subject[i] % 256) + 256) % 256 + } + } else if (type === 'string') { + buf.write(subject, 0, encoding) + } else if (type === 'number' && !Buffer.TYPED_ARRAY_SUPPORT && !noZero) { + for (i = 0; i < length; i++) { + buf[i] = 0 + } + } + + return buf +} + +Buffer.isBuffer = function (b) { + return !!(b != null && b._isBuffer) +} + +Buffer.compare = function (a, b) { + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) + throw new TypeError('Arguments must be Buffers') + + var x = a.length + var y = b.length + for (var i = 0, len = Math.min(x, y); i < len && a[i] === b[i]; i++) {} + if (i !== len) { + x = a[i] + y = b[i] + } + if (x < y) return -1 + if (y < x) return 1 + return 0 +} + +Buffer.isEncoding = function (encoding) { + switch (String(encoding).toLowerCase()) { + case 'hex': + case 'utf8': + case 'utf-8': + case 'ascii': + case 'binary': + case 'base64': + case 'raw': + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return true + default: + return false + } +} + +Buffer.concat = function (list, totalLength) { + if (!isArray(list)) throw new TypeError('Usage: Buffer.concat(list[, length])') + + if (list.length === 0) { + return new Buffer(0) + } else if (list.length === 1) { + return list[0] + } + + var i + if (totalLength === undefined) { + totalLength = 0 + for (i = 0; i < list.length; i++) { + totalLength += list[i].length + } + } + + var buf = new Buffer(totalLength) + var pos = 0 + for (i = 0; i < list.length; i++) { + var item = list[i] + item.copy(buf, pos) + pos += item.length + } + return buf +} + +Buffer.byteLength = function (str, encoding) { + var ret + str = str + '' + switch (encoding || 'utf8') { + case 'ascii': + case 'binary': + case 'raw': + ret = str.length + break + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + ret = str.length * 2 + break + case 'hex': + ret = str.length >>> 1 + break + case 'utf8': + case 'utf-8': + ret = utf8ToBytes(str).length + break + case 'base64': + ret = base64ToBytes(str).length + break + default: + ret = str.length + } + return ret +} + +// pre-set for values that may exist in the future +Buffer.prototype.length = undefined +Buffer.prototype.parent = undefined + +// toString(encoding, start=0, end=buffer.length) +Buffer.prototype.toString = function (encoding, start, end) { + var loweredCase = false + + start = start >>> 0 + end = end === undefined || end === Infinity ? this.length : end >>> 0 + + if (!encoding) encoding = 'utf8' + if (start < 0) start = 0 + if (end > this.length) end = this.length + if (end <= start) return '' + + while (true) { + switch (encoding) { + case 'hex': + return hexSlice(this, start, end) + + case 'utf8': + case 'utf-8': + return utf8Slice(this, start, end) + + case 'ascii': + return asciiSlice(this, start, end) + + case 'binary': + return binarySlice(this, start, end) + + case 'base64': + return base64Slice(this, start, end) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return utf16leSlice(this, start, end) + + default: + if (loweredCase) + throw new TypeError('Unknown encoding: ' + encoding) + encoding = (encoding + '').toLowerCase() + loweredCase = true + } + } +} + +Buffer.prototype.equals = function (b) { + if(!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + return Buffer.compare(this, b) === 0 +} + +Buffer.prototype.inspect = function () { + var str = '' + var max = exports.INSPECT_MAX_BYTES + if (this.length > 0) { + str = this.toString('hex', 0, max).match(/.{2}/g).join(' ') + if (this.length > max) + str += ' ... ' + } + return '<Buffer ' + str + '>' +} + +Buffer.prototype.compare = function (b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + return Buffer.compare(this, b) +} + +// `get` will be removed in Node 0.13+ +Buffer.prototype.get = function (offset) { + console.log('.get() is deprecated. Access using array indexes instead.') + return this.readUInt8(offset) +} + +// `set` will be removed in Node 0.13+ +Buffer.prototype.set = function (v, offset) { + console.log('.set() is deprecated. Access using array indexes instead.') + return this.writeUInt8(v, offset) +} + +function hexWrite (buf, string, offset, length) { + offset = Number(offset) || 0 + var remaining = buf.length - offset + if (!length) { + length = remaining + } else { + length = Number(length) + if (length > remaining) { + length = remaining + } + } + + // must be an even number of digits + var strLen = string.length + if (strLen % 2 !== 0) throw new Error('Invalid hex string') + + if (length > strLen / 2) { + length = strLen / 2 + } + for (var i = 0; i < length; i++) { + var byte = parseInt(string.substr(i * 2, 2), 16) + if (isNaN(byte)) throw new Error('Invalid hex string') + buf[offset + i] = byte + } + return i +} + +function utf8Write (buf, string, offset, length) { + var charsWritten = blitBuffer(utf8ToBytes(string), buf, offset, length) + return charsWritten +} + +function asciiWrite (buf, string, offset, length) { + var charsWritten = blitBuffer(asciiToBytes(string), buf, offset, length) + return charsWritten +} + +function binaryWrite (buf, string, offset, length) { + return asciiWrite(buf, string, offset, length) +} + +function base64Write (buf, string, offset, length) { + var charsWritten = blitBuffer(base64ToBytes(string), buf, offset, length) + return charsWritten +} + +function utf16leWrite (buf, string, offset, length) { + var charsWritten = blitBuffer(utf16leToBytes(string), buf, offset, length) + return charsWritten +} + +Buffer.prototype.write = function (string, offset, length, encoding) { + // Support both (string, offset, length, encoding) + // and the legacy (string, encoding, offset, length) + if (isFinite(offset)) { + if (!isFinite(length)) { + encoding = length + length = undefined + } + } else { // legacy + var swap = encoding + encoding = offset + offset = length + length = swap + } + + offset = Number(offset) || 0 + var remaining = this.length - offset + if (!length) { + length = remaining + } else { + length = Number(length) + if (length > remaining) { + length = remaining + } + } + encoding = String(encoding || 'utf8').toLowerCase() + + var ret + switch (encoding) { + case 'hex': + ret = hexWrite(this, string, offset, length) + break + case 'utf8': + case 'utf-8': + ret = utf8Write(this, string, offset, length) + break + case 'ascii': + ret = asciiWrite(this, string, offset, length) + break + case 'binary': + ret = binaryWrite(this, string, offset, length) + break + case 'base64': + ret = base64Write(this, string, offset, length) + break + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + ret = utf16leWrite(this, string, offset, length) + break + default: + throw new TypeError('Unknown encoding: ' + encoding) + } + return ret +} + +Buffer.prototype.toJSON = function () { + return { + type: 'Buffer', + data: Array.prototype.slice.call(this._arr || this, 0) + } +} + +function base64Slice (buf, start, end) { + if (start === 0 && end === buf.length) { + return base64.fromByteArray(buf) + } else { + return base64.fromByteArray(buf.slice(start, end)) + } +} + +function utf8Slice (buf, start, end) { + var res = '' + var tmp = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; i++) { + if (buf[i] <= 0x7F) { + res += decodeUtf8Char(tmp) + String.fromCharCode(buf[i]) + tmp = '' + } else { + tmp += '%' + buf[i].toString(16) + } + } + + return res + decodeUtf8Char(tmp) +} + +function asciiSlice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; i++) { + ret += String.fromCharCode(buf[i]) + } + return ret +} + +function binarySlice (buf, start, end) { + return asciiSlice(buf, start, end) +} + +function hexSlice (buf, start, end) { + var len = buf.length + + if (!start || start < 0) start = 0 + if (!end || end < 0 || end > len) end = len + + var out = '' + for (var i = start; i < end; i++) { + out += toHex(buf[i]) + } + return out +} + +function utf16leSlice (buf, start, end) { + var bytes = buf.slice(start, end) + var res = '' + for (var i = 0; i < bytes.length; i += 2) { + res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256) + } + return res +} + +Buffer.prototype.slice = function (start, end) { + var len = this.length + start = ~~start + end = end === undefined ? len : ~~end + + if (start < 0) { + start += len; + if (start < 0) + start = 0 + } else if (start > len) { + start = len + } + + if (end < 0) { + end += len + if (end < 0) + end = 0 + } else if (end > len) { + end = len + } + + if (end < start) + end = start + + if (Buffer.TYPED_ARRAY_SUPPORT) { + return Buffer._augment(this.subarray(start, end)) + } else { + var sliceLen = end - start + var newBuf = new Buffer(sliceLen, undefined, true) + for (var i = 0; i < sliceLen; i++) { + newBuf[i] = this[i + start] + } + return newBuf + } +} + +/* + * Need to make sure that buffer isn't trying to write out of bounds. + */ +function checkOffset (offset, ext, length) { + if ((offset % 1) !== 0 || offset < 0) + throw new RangeError('offset is not uint') + if (offset + ext > length) + throw new RangeError('Trying to access beyond buffer length') +} + +Buffer.prototype.readUInt8 = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 1, this.length) + return this[offset] +} + +Buffer.prototype.readUInt16LE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 2, this.length) + return this[offset] | (this[offset + 1] << 8) +} + +Buffer.prototype.readUInt16BE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 2, this.length) + return (this[offset] << 8) | this[offset + 1] +} + +Buffer.prototype.readUInt32LE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length) + + return ((this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16)) + + (this[offset + 3] * 0x1000000) +} + +Buffer.prototype.readUInt32BE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length) + + return (this[offset] * 0x1000000) + + ((this[offset + 1] << 16) | + (this[offset + 2] << 8) | + this[offset + 3]) +} + +Buffer.prototype.readInt8 = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 1, this.length) + if (!(this[offset] & 0x80)) + return (this[offset]) + return ((0xff - this[offset] + 1) * -1) +} + +Buffer.prototype.readInt16LE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 2, this.length) + var val = this[offset] | (this[offset + 1] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt16BE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 2, this.length) + var val = this[offset + 1] | (this[offset] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt32LE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length) + + return (this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16) | + (this[offset + 3] << 24) +} + +Buffer.prototype.readInt32BE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length) + + return (this[offset] << 24) | + (this[offset + 1] << 16) | + (this[offset + 2] << 8) | + (this[offset + 3]) +} + +Buffer.prototype.readFloatLE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, true, 23, 4) +} + +Buffer.prototype.readFloatBE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, false, 23, 4) +} + +Buffer.prototype.readDoubleLE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, true, 52, 8) +} + +Buffer.prototype.readDoubleBE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, false, 52, 8) +} + +function checkInt (buf, value, offset, ext, max, min) { + if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance') + if (value > max || value < min) throw new TypeError('value is out of bounds') + if (offset + ext > buf.length) throw new TypeError('index out of range') +} + +Buffer.prototype.writeUInt8 = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 1, 0xff, 0) + if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) + this[offset] = value + return offset + 1 +} + +function objectWriteUInt16 (buf, value, offset, littleEndian) { + if (value < 0) value = 0xffff + value + 1 + for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) { + buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> + (littleEndian ? i : 1 - i) * 8 + } +} + +Buffer.prototype.writeUInt16LE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 2, 0xffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = value + this[offset + 1] = (value >>> 8) + } else objectWriteUInt16(this, value, offset, true) + return offset + 2 +} + +Buffer.prototype.writeUInt16BE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 2, 0xffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 8) + this[offset + 1] = value + } else objectWriteUInt16(this, value, offset, false) + return offset + 2 +} + +function objectWriteUInt32 (buf, value, offset, littleEndian) { + if (value < 0) value = 0xffffffff + value + 1 + for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) { + buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff + } +} + +Buffer.prototype.writeUInt32LE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 4, 0xffffffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset + 3] = (value >>> 24) + this[offset + 2] = (value >>> 16) + this[offset + 1] = (value >>> 8) + this[offset] = value + } else objectWriteUInt32(this, value, offset, true) + return offset + 4 +} + +Buffer.prototype.writeUInt32BE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 4, 0xffffffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = value + } else objectWriteUInt32(this, value, offset, false) + return offset + 4 +} + +Buffer.prototype.writeInt8 = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 1, 0x7f, -0x80) + if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) + if (value < 0) value = 0xff + value + 1 + this[offset] = value + return offset + 1 +} + +Buffer.prototype.writeInt16LE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 2, 0x7fff, -0x8000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = value + this[offset + 1] = (value >>> 8) + } else objectWriteUInt16(this, value, offset, true) + return offset + 2 +} + +Buffer.prototype.writeInt16BE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 2, 0x7fff, -0x8000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 8) + this[offset + 1] = value + } else objectWriteUInt16(this, value, offset, false) + return offset + 2 +} + +Buffer.prototype.writeInt32LE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = value + this[offset + 1] = (value >>> 8) + this[offset + 2] = (value >>> 16) + this[offset + 3] = (value >>> 24) + } else objectWriteUInt32(this, value, offset, true) + return offset + 4 +} + +Buffer.prototype.writeInt32BE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (value < 0) value = 0xffffffff + value + 1 + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = value + } else objectWriteUInt32(this, value, offset, false) + return offset + 4 +} + +function checkIEEE754 (buf, value, offset, ext, max, min) { + if (value > max || value < min) throw new TypeError('value is out of bounds') + if (offset + ext > buf.length) throw new TypeError('index out of range') +} + +function writeFloat (buf, value, offset, littleEndian, noAssert) { + if (!noAssert) + checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) + ieee754.write(buf, value, offset, littleEndian, 23, 4) + return offset + 4 +} + +Buffer.prototype.writeFloatLE = function (value, offset, noAssert) { + return writeFloat(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeFloatBE = function (value, offset, noAssert) { + return writeFloat(this, value, offset, false, noAssert) +} + +function writeDouble (buf, value, offset, littleEndian, noAssert) { + if (!noAssert) + checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) + ieee754.write(buf, value, offset, littleEndian, 52, 8) + return offset + 8 +} + +Buffer.prototype.writeDoubleLE = function (value, offset, noAssert) { + return writeDouble(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeDoubleBE = function (value, offset, noAssert) { + return writeDouble(this, value, offset, false, noAssert) +} + +// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) +Buffer.prototype.copy = function (target, target_start, start, end) { + var source = this + + if (!start) start = 0 + if (!end && end !== 0) end = this.length + if (!target_start) target_start = 0 + + // Copy 0 bytes; we're done + if (end === start) return + if (target.length === 0 || source.length === 0) return + + // Fatal error conditions + if (end < start) throw new TypeError('sourceEnd < sourceStart') + if (target_start < 0 || target_start >= target.length) + throw new TypeError('targetStart out of bounds') + if (start < 0 || start >= source.length) throw new TypeError('sourceStart out of bounds') + if (end < 0 || end > source.length) throw new TypeError('sourceEnd out of bounds') + + // Are we oob? + if (end > this.length) + end = this.length + if (target.length - target_start < end - start) + end = target.length - target_start + start + + var len = end - start + + if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) { + for (var i = 0; i < len; i++) { + target[i + target_start] = this[i + start] + } + } else { + target._set(this.subarray(start, start + len), target_start) + } +} + +// fill(value, start=0, end=buffer.length) +Buffer.prototype.fill = function (value, start, end) { + if (!value) value = 0 + if (!start) start = 0 + if (!end) end = this.length + + if (end < start) throw new TypeError('end < start') + + // Fill 0 bytes; we're done + if (end === start) return + if (this.length === 0) return + + if (start < 0 || start >= this.length) throw new TypeError('start out of bounds') + if (end < 0 || end > this.length) throw new TypeError('end out of bounds') + + var i + if (typeof value === 'number') { + for (i = start; i < end; i++) { + this[i] = value + } + } else { + var bytes = utf8ToBytes(value.toString()) + var len = bytes.length + for (i = start; i < end; i++) { + this[i] = bytes[i % len] + } + } + + return this +} + +/** + * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance. + * Added in Node 0.12. Only available in browsers that support ArrayBuffer. + */ +Buffer.prototype.toArrayBuffer = function () { + if (typeof Uint8Array !== 'undefined') { + if (Buffer.TYPED_ARRAY_SUPPORT) { + return (new Buffer(this)).buffer + } else { + var buf = new Uint8Array(this.length) + for (var i = 0, len = buf.length; i < len; i += 1) { + buf[i] = this[i] + } + return buf.buffer + } + } else { + throw new TypeError('Buffer.toArrayBuffer not supported in this browser') + } +} + +// HELPER FUNCTIONS +// ================ + +var BP = Buffer.prototype + +/** + * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods + */ +Buffer._augment = function (arr) { + arr.constructor = Buffer + arr._isBuffer = true + + // save reference to original Uint8Array get/set methods before overwriting + arr._get = arr.get + arr._set = arr.set + + // deprecated, will be removed in node 0.13+ + arr.get = BP.get + arr.set = BP.set + + arr.write = BP.write + arr.toString = BP.toString + arr.toLocaleString = BP.toString + arr.toJSON = BP.toJSON + arr.equals = BP.equals + arr.compare = BP.compare + arr.copy = BP.copy + arr.slice = BP.slice + arr.readUInt8 = BP.readUInt8 + arr.readUInt16LE = BP.readUInt16LE + arr.readUInt16BE = BP.readUInt16BE + arr.readUInt32LE = BP.readUInt32LE + arr.readUInt32BE = BP.readUInt32BE + arr.readInt8 = BP.readInt8 + arr.readInt16LE = BP.readInt16LE + arr.readInt16BE = BP.readInt16BE + arr.readInt32LE = BP.readInt32LE + arr.readInt32BE = BP.readInt32BE + arr.readFloatLE = BP.readFloatLE + arr.readFloatBE = BP.readFloatBE + arr.readDoubleLE = BP.readDoubleLE + arr.readDoubleBE = BP.readDoubleBE + arr.writeUInt8 = BP.writeUInt8 + arr.writeUInt16LE = BP.writeUInt16LE + arr.writeUInt16BE = BP.writeUInt16BE + arr.writeUInt32LE = BP.writeUInt32LE + arr.writeUInt32BE = BP.writeUInt32BE + arr.writeInt8 = BP.writeInt8 + arr.writeInt16LE = BP.writeInt16LE + arr.writeInt16BE = BP.writeInt16BE + arr.writeInt32LE = BP.writeInt32LE + arr.writeInt32BE = BP.writeInt32BE + arr.writeFloatLE = BP.writeFloatLE + arr.writeFloatBE = BP.writeFloatBE + arr.writeDoubleLE = BP.writeDoubleLE + arr.writeDoubleBE = BP.writeDoubleBE + arr.fill = BP.fill + arr.inspect = BP.inspect + arr.toArrayBuffer = BP.toArrayBuffer + + return arr +} + +var INVALID_BASE64_RE = /[^+\/0-9A-z]/g + +function base64clean (str) { + // Node strips out invalid characters like \n and \t from the string, base64-js does not + str = stringtrim(str).replace(INVALID_BASE64_RE, '') + // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not + while (str.length % 4 !== 0) { + str = str + '=' + } + return str +} + +function stringtrim (str) { + if (str.trim) return str.trim() + return str.replace(/^\s+|\s+$/g, '') +} + +function isArrayish (subject) { + return isArray(subject) || Buffer.isBuffer(subject) || + subject && typeof subject === 'object' && + typeof subject.length === 'number' +} + +function toHex (n) { + if (n < 16) return '0' + n.toString(16) + return n.toString(16) +} + +function utf8ToBytes (str) { + var byteArray = [] + for (var i = 0; i < str.length; i++) { + var b = str.charCodeAt(i) + if (b <= 0x7F) { + byteArray.push(b) + } else { + var start = i + if (b >= 0xD800 && b <= 0xDFFF) i++ + var h = encodeURIComponent(str.slice(start, i+1)).substr(1).split('%') + for (var j = 0; j < h.length; j++) { + byteArray.push(parseInt(h[j], 16)) + } + } + } + return byteArray +} + +function asciiToBytes (str) { + var byteArray = [] + for (var i = 0; i < str.length; i++) { + // Node's code seems to be doing this and not & 0x7F.. + byteArray.push(str.charCodeAt(i) & 0xFF) + } + return byteArray +} + +function utf16leToBytes (str) { + var c, hi, lo + var byteArray = [] + for (var i = 0; i < str.length; i++) { + c = str.charCodeAt(i) + hi = c >> 8 + lo = c % 256 + byteArray.push(lo) + byteArray.push(hi) + } + + return byteArray +} + +function base64ToBytes (str) { + return base64.toByteArray(str) +} + +function blitBuffer (src, dst, offset, length) { + for (var i = 0; i < length; i++) { + if ((i + offset >= dst.length) || (i >= src.length)) + break + dst[i + offset] = src[i] + } + return i +} + +function decodeUtf8Char (str) { + try { + return decodeURIComponent(str) + } catch (err) { + return String.fromCharCode(0xFFFD) // UTF 8 invalid char + } +} + +},{"base64-js":18,"ieee754":19,"is-array":20}],18:[function(_dereq_,module,exports){ +var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + +;(function (exports) { + 'use strict'; + + var Arr = (typeof Uint8Array !== 'undefined') + ? Uint8Array + : Array + + var PLUS = '+'.charCodeAt(0) + var SLASH = '/'.charCodeAt(0) + var NUMBER = '0'.charCodeAt(0) + var LOWER = 'a'.charCodeAt(0) + var UPPER = 'A'.charCodeAt(0) + + function decode (elt) { + var code = elt.charCodeAt(0) + if (code === PLUS) + return 62 // '+' + if (code === SLASH) + return 63 // '/' + if (code < NUMBER) + return -1 //no match + if (code < NUMBER + 10) + return code - NUMBER + 26 + 26 + if (code < UPPER + 26) + return code - UPPER + if (code < LOWER + 26) + return code - LOWER + 26 + } + + function b64ToByteArray (b64) { + var i, j, l, tmp, placeHolders, arr + + if (b64.length % 4 > 0) { + throw new Error('Invalid string. Length must be a multiple of 4') + } + + // the number of equal signs (place holders) + // if there are two placeholders, than the two characters before it + // represent one byte + // if there is only one, then the three characters before it represent 2 bytes + // this is just a cheap hack to not do indexOf twice + var len = b64.length + placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0 + + // base64 is 4/3 + up to two characters of the original data + arr = new Arr(b64.length * 3 / 4 - placeHolders) + + // if there are placeholders, only get up to the last complete 4 chars + l = placeHolders > 0 ? b64.length - 4 : b64.length + + var L = 0 + + function push (v) { + arr[L++] = v + } + + for (i = 0, j = 0; i < l; i += 4, j += 3) { + tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3)) + push((tmp & 0xFF0000) >> 16) + push((tmp & 0xFF00) >> 8) + push(tmp & 0xFF) + } + + if (placeHolders === 2) { + tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4) + push(tmp & 0xFF) + } else if (placeHolders === 1) { + tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2) + push((tmp >> 8) & 0xFF) + push(tmp & 0xFF) + } + + return arr + } + + function uint8ToBase64 (uint8) { + var i, + extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes + output = "", + temp, length + + function encode (num) { + return lookup.charAt(num) + } + + function tripletToBase64 (num) { + return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F) + } + + // go through the array every three bytes, we'll deal with trailing stuff later + for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) { + temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) + output += tripletToBase64(temp) + } + + // pad the end with zeros, but make sure to not forget the extra bytes + switch (extraBytes) { + case 1: + temp = uint8[uint8.length - 1] + output += encode(temp >> 2) + output += encode((temp << 4) & 0x3F) + output += '==' + break + case 2: + temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]) + output += encode(temp >> 10) + output += encode((temp >> 4) & 0x3F) + output += encode((temp << 2) & 0x3F) + output += '=' + break + } + + return output + } + + exports.toByteArray = b64ToByteArray + exports.fromByteArray = uint8ToBase64 +}(typeof exports === 'undefined' ? (this.base64js = {}) : exports)) + +},{}],19:[function(_dereq_,module,exports){ +exports.read = function(buffer, offset, isLE, mLen, nBytes) { + var e, m, + eLen = nBytes * 8 - mLen - 1, + eMax = (1 << eLen) - 1, + eBias = eMax >> 1, + nBits = -7, + i = isLE ? (nBytes - 1) : 0, + d = isLE ? -1 : 1, + s = buffer[offset + i]; + + i += d; + + e = s & ((1 << (-nBits)) - 1); + s >>= (-nBits); + nBits += eLen; + for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8); + + m = e & ((1 << (-nBits)) - 1); + e >>= (-nBits); + nBits += mLen; + for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8); + + if (e === 0) { + e = 1 - eBias; + } else if (e === eMax) { + return m ? NaN : ((s ? -1 : 1) * Infinity); + } else { + m = m + Math.pow(2, mLen); + e = e - eBias; + } + return (s ? -1 : 1) * m * Math.pow(2, e - mLen); +}; + +exports.write = function(buffer, value, offset, isLE, mLen, nBytes) { + var e, m, c, + eLen = nBytes * 8 - mLen - 1, + eMax = (1 << eLen) - 1, + eBias = eMax >> 1, + rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0), + i = isLE ? 0 : (nBytes - 1), + d = isLE ? 1 : -1, + s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0; + + value = Math.abs(value); + + if (isNaN(value) || value === Infinity) { + m = isNaN(value) ? 1 : 0; + e = eMax; + } else { + e = Math.floor(Math.log(value) / Math.LN2); + if (value * (c = Math.pow(2, -e)) < 1) { + e--; + c *= 2; + } + if (e + eBias >= 1) { + value += rt / c; + } else { + value += rt * Math.pow(2, 1 - eBias); + } + if (value * c >= 2) { + e++; + c /= 2; + } + + if (e + eBias >= eMax) { + m = 0; + e = eMax; + } else if (e + eBias >= 1) { + m = (value * c - 1) * Math.pow(2, mLen); + e = e + eBias; + } else { + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); + e = 0; + } + } + + for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8); + + e = (e << mLen) | m; + eLen += mLen; + for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8); + + buffer[offset + i - d] |= s * 128; +}; + +},{}],20:[function(_dereq_,module,exports){ + +/** + * isArray + */ + +var isArray = Array.isArray; + +/** + * toString + */ + +var str = Object.prototype.toString; + +/** + * Whether or not the given `val` + * is an array. + * + * example: + * + * isArray([]); + * // > true + * isArray(arguments); + * // > false + * isArray(''); + * // > false + * + * @param {mixed} val + * @return {bool} + */ + +module.exports = isArray || function (val) { + return !! val && '[object Array]' == str.call(val); +}; + +},{}],21:[function(_dereq_,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +function EventEmitter() { + this._events = this._events || {}; + this._maxListeners = this._maxListeners || undefined; +} +module.exports = EventEmitter; + +// Backwards-compat with node 0.10.x +EventEmitter.EventEmitter = EventEmitter; + +EventEmitter.prototype._events = undefined; +EventEmitter.prototype._maxListeners = undefined; + +// By default EventEmitters will print a warning if more than 10 listeners are +// added to it. This is a useful default which helps finding memory leaks. +EventEmitter.defaultMaxListeners = 10; + +// Obviously not all Emitters should be limited to 10. This function allows +// that to be increased. Set to zero for unlimited. +EventEmitter.prototype.setMaxListeners = function(n) { + if (!isNumber(n) || n < 0 || isNaN(n)) + throw TypeError('n must be a positive number'); + this._maxListeners = n; + return this; +}; + +EventEmitter.prototype.emit = function(type) { + var er, handler, len, args, i, listeners; + + if (!this._events) + this._events = {}; + + // If there is no 'error' event listener then throw. + if (type === 'error') { + if (!this._events.error || + (isObject(this._events.error) && !this._events.error.length)) { + er = arguments[1]; + if (er instanceof Error) { + throw er; // Unhandled 'error' event + } + throw TypeError('Uncaught, unspecified "error" event.'); + } + } + + handler = this._events[type]; + + if (isUndefined(handler)) + return false; + + if (isFunction(handler)) { + switch (arguments.length) { + // fast cases + case 1: + handler.call(this); + break; + case 2: + handler.call(this, arguments[1]); + break; + case 3: + handler.call(this, arguments[1], arguments[2]); + break; + // slower + default: + len = arguments.length; + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + handler.apply(this, args); + } + } else if (isObject(handler)) { + len = arguments.length; + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + + listeners = handler.slice(); + len = listeners.length; + for (i = 0; i < len; i++) + listeners[i].apply(this, args); + } + + return true; +}; + +EventEmitter.prototype.addListener = function(type, listener) { + var m; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events) + this._events = {}; + + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (this._events.newListener) + this.emit('newListener', type, + isFunction(listener.listener) ? + listener.listener : listener); + + if (!this._events[type]) + // Optimize the case of one listener. Don't need the extra array object. + this._events[type] = listener; + else if (isObject(this._events[type])) + // If we've already got an array, just append. + this._events[type].push(listener); + else + // Adding the second element, need to change to array. + this._events[type] = [this._events[type], listener]; + + // Check for listener leak + if (isObject(this._events[type]) && !this._events[type].warned) { + var m; + if (!isUndefined(this._maxListeners)) { + m = this._maxListeners; + } else { + m = EventEmitter.defaultMaxListeners; + } + + if (m && m > 0 && this._events[type].length > m) { + this._events[type].warned = true; + console.error('(node) warning: possible EventEmitter memory ' + + 'leak detected. %d listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.', + this._events[type].length); + if (typeof console.trace === 'function') { + // not supported in IE 10 + console.trace(); + } + } + } + + return this; +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.once = function(type, listener) { + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + var fired = false; + + function g() { + this.removeListener(type, g); + + if (!fired) { + fired = true; + listener.apply(this, arguments); + } + } + + g.listener = listener; + this.on(type, g); + + return this; +}; + +// emits a 'removeListener' event iff the listener was removed +EventEmitter.prototype.removeListener = function(type, listener) { + var list, position, length, i; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events || !this._events[type]) + return this; + + list = this._events[type]; + length = list.length; + position = -1; + + if (list === listener || + (isFunction(list.listener) && list.listener === listener)) { + delete this._events[type]; + if (this._events.removeListener) + this.emit('removeListener', type, listener); + + } else if (isObject(list)) { + for (i = length; i-- > 0;) { + if (list[i] === listener || + (list[i].listener && list[i].listener === listener)) { + position = i; + break; + } + } + + if (position < 0) + return this; + + if (list.length === 1) { + list.length = 0; + delete this._events[type]; + } else { + list.splice(position, 1); + } + + if (this._events.removeListener) + this.emit('removeListener', type, listener); + } + + return this; +}; + +EventEmitter.prototype.removeAllListeners = function(type) { + var key, listeners; + + if (!this._events) + return this; + + // not listening for removeListener, no need to emit + if (!this._events.removeListener) { + if (arguments.length === 0) + this._events = {}; + else if (this._events[type]) + delete this._events[type]; + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + for (key in this._events) { + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = {}; + return this; + } + + listeners = this._events[type]; + + if (isFunction(listeners)) { + this.removeListener(type, listeners); + } else { + // LIFO order + while (listeners.length) + this.removeListener(type, listeners[listeners.length - 1]); + } + delete this._events[type]; + + return this; +}; + +EventEmitter.prototype.listeners = function(type) { + var ret; + if (!this._events || !this._events[type]) + ret = []; + else if (isFunction(this._events[type])) + ret = [this._events[type]]; + else + ret = this._events[type].slice(); + return ret; +}; + +EventEmitter.listenerCount = function(emitter, type) { + var ret; + if (!emitter._events || !emitter._events[type]) + ret = 0; + else if (isFunction(emitter._events[type])) + ret = 1; + else + ret = emitter._events[type].length; + return ret; +}; + +function isFunction(arg) { + return typeof arg === 'function'; +} + +function isNumber(arg) { + return typeof arg === 'number'; +} + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} + +function isUndefined(arg) { + return arg === void 0; +} + +},{}],22:[function(_dereq_,module,exports){ +module.exports = Array.isArray || function (arr) { + return Object.prototype.toString.call(arr) == '[object Array]'; +}; + +},{}],23:[function(_dereq_,module,exports){ +(function (process){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// resolves . and .. elements in a path array with directory names there +// must be no slashes, empty elements, or device names (c:\) in the array +// (so also no leading and trailing slashes - it does not distinguish +// relative and absolute paths) +function normalizeArray(parts, allowAboveRoot) { + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = parts.length - 1; i >= 0; i--) { + var last = parts[i]; + if (last === '.') { + parts.splice(i, 1); + } else if (last === '..') { + parts.splice(i, 1); + up++; + } else if (up) { + parts.splice(i, 1); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up--; up) { + parts.unshift('..'); + } + } + + return parts; +} + +// Split a filename into [root, dir, basename, ext], unix version +// 'root' is just a slash, or nothing. +var splitPathRe = + /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; +var splitPath = function(filename) { + return splitPathRe.exec(filename).slice(1); +}; + +// path.resolve([from ...], to) +// posix version +exports.resolve = function() { + var resolvedPath = '', + resolvedAbsolute = false; + + for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) ? arguments[i] : process.cwd(); + + // Skip empty and invalid entries + if (typeof path !== 'string') { + throw new TypeError('Arguments to path.resolve must be strings'); + } else if (!path) { + continue; + } + + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = path.charAt(0) === '/'; + } + + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) + + // Normalize the path + resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { + return !!p; + }), !resolvedAbsolute).join('/'); + + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; +}; + +// path.normalize(path) +// posix version +exports.normalize = function(path) { + var isAbsolute = exports.isAbsolute(path), + trailingSlash = substr(path, -1) === '/'; + + // Normalize the path + path = normalizeArray(filter(path.split('/'), function(p) { + return !!p; + }), !isAbsolute).join('/'); + + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + + return (isAbsolute ? '/' : '') + path; +}; + +// posix version +exports.isAbsolute = function(path) { + return path.charAt(0) === '/'; +}; + +// posix version +exports.join = function() { + var paths = Array.prototype.slice.call(arguments, 0); + return exports.normalize(filter(paths, function(p, index) { + if (typeof p !== 'string') { + throw new TypeError('Arguments to path.join must be strings'); + } + return p; + }).join('/')); +}; + + +// path.relative(from, to) +// posix version +exports.relative = function(from, to) { + from = exports.resolve(from).substr(1); + to = exports.resolve(to).substr(1); + + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + + var end = arr.length - 1; + for (; end >= 0; end--) { + if (arr[end] !== '') break; + } + + if (start > end) return []; + return arr.slice(start, end - start + 1); + } + + var fromParts = trim(from.split('/')); + var toParts = trim(to.split('/')); + + var length = Math.min(fromParts.length, toParts.length); + var samePartsLength = length; + for (var i = 0; i < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i; + break; + } + } + + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); + } + + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + + return outputParts.join('/'); +}; + +exports.sep = '/'; +exports.delimiter = ':'; + +exports.dirname = function(path) { + var result = splitPath(path), + root = result[0], + dir = result[1]; + + if (!root && !dir) { + // No dirname whatsoever + return '.'; + } + + if (dir) { + // It has a dirname, strip trailing slash + dir = dir.substr(0, dir.length - 1); + } + + return root + dir; +}; + + +exports.basename = function(path, ext) { + var f = splitPath(path)[2]; + // TODO: make this comparison case-insensitive on windows? + if (ext && f.substr(-1 * ext.length) === ext) { + f = f.substr(0, f.length - ext.length); + } + return f; +}; + + +exports.extname = function(path) { + return splitPath(path)[3]; +}; + +function filter (xs, f) { + if (xs.filter) return xs.filter(f); + var res = []; + for (var i = 0; i < xs.length; i++) { + if (f(xs[i], i, xs)) res.push(xs[i]); + } + return res; +} + +// String.prototype.substr - negative index don't work in IE8 +var substr = 'ab'.substr(-1) === 'b' + ? function (str, start, len) { return str.substr(start, len) } + : function (str, start, len) { + if (start < 0) start = str.length + start; + return str.substr(start, len); + } +; + +}).call(this,_dereq_('_process')) +},{"_process":24}],24:[function(_dereq_,module,exports){ +// shim for using process in browser + +var process = module.exports = {}; + +process.nextTick = (function () { + var canSetImmediate = typeof window !== 'undefined' + && window.setImmediate; + var canMutationObserver = typeof window !== 'undefined' + && window.MutationObserver; + var canPost = typeof window !== 'undefined' + && window.postMessage && window.addEventListener + ; + + if (canSetImmediate) { + return function (f) { return window.setImmediate(f) }; + } + + var queue = []; + + if (canMutationObserver) { + var hiddenDiv = document.createElement("div"); + var observer = new MutationObserver(function () { + var queueList = queue.slice(); + queue.length = 0; + queueList.forEach(function (fn) { + fn(); + }); + }); + + observer.observe(hiddenDiv, { attributes: true }); + + return function nextTick(fn) { + if (!queue.length) { + hiddenDiv.setAttribute('yes', 'no'); + } + queue.push(fn); + }; + } + + if (canPost) { + window.addEventListener('message', function (ev) { + var source = ev.source; + if ((source === window || source === null) && ev.data === 'process-tick') { + ev.stopPropagation(); + if (queue.length > 0) { + var fn = queue.shift(); + fn(); + } + } + }, true); + + return function nextTick(fn) { + queue.push(fn); + window.postMessage('process-tick', '*'); + }; + } + + return function nextTick(fn) { + setTimeout(fn, 0); + }; +})(); + +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +// TODO(shtylman) +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; + +},{}],25:[function(_dereq_,module,exports){ +module.exports = _dereq_("./lib/_stream_duplex.js") + +},{"./lib/_stream_duplex.js":26}],26:[function(_dereq_,module,exports){ +(function (process){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a duplex stream is just a stream that is both readable and writable. +// Since JS doesn't have multiple prototypal inheritance, this class +// prototypally inherits from Readable, and then parasitically from +// Writable. + +module.exports = Duplex; + +/*<replacement>*/ +var objectKeys = Object.keys || function (obj) { + var keys = []; + for (var key in obj) keys.push(key); + return keys; +} +/*</replacement>*/ + + +/*<replacement>*/ +var util = _dereq_('core-util-is'); +util.inherits = _dereq_('inherits'); +/*</replacement>*/ + +var Readable = _dereq_('./_stream_readable'); +var Writable = _dereq_('./_stream_writable'); + +util.inherits(Duplex, Readable); + +forEach(objectKeys(Writable.prototype), function(method) { + if (!Duplex.prototype[method]) + Duplex.prototype[method] = Writable.prototype[method]; +}); + +function Duplex(options) { + if (!(this instanceof Duplex)) + return new Duplex(options); + + Readable.call(this, options); + Writable.call(this, options); + + if (options && options.readable === false) + this.readable = false; + + if (options && options.writable === false) + this.writable = false; + + this.allowHalfOpen = true; + if (options && options.allowHalfOpen === false) + this.allowHalfOpen = false; + + this.once('end', onend); +} + +// the no-half-open enforcer +function onend() { + // if we allow half-open state, or if the writable side ended, + // then we're ok. + if (this.allowHalfOpen || this._writableState.ended) + return; + + // no more data can be written. + // But allow more writes to happen in this tick. + process.nextTick(this.end.bind(this)); +} + +function forEach (xs, f) { + for (var i = 0, l = xs.length; i < l; i++) { + f(xs[i], i); + } +} + +}).call(this,_dereq_('_process')) +},{"./_stream_readable":28,"./_stream_writable":30,"_process":24,"core-util-is":31,"inherits":44}],27:[function(_dereq_,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a passthrough stream. +// basically just the most minimal sort of Transform stream. +// Every written chunk gets output as-is. + +module.exports = PassThrough; + +var Transform = _dereq_('./_stream_transform'); + +/*<replacement>*/ +var util = _dereq_('core-util-is'); +util.inherits = _dereq_('inherits'); +/*</replacement>*/ + +util.inherits(PassThrough, Transform); + +function PassThrough(options) { + if (!(this instanceof PassThrough)) + return new PassThrough(options); + + Transform.call(this, options); +} + +PassThrough.prototype._transform = function(chunk, encoding, cb) { + cb(null, chunk); +}; + +},{"./_stream_transform":29,"core-util-is":31,"inherits":44}],28:[function(_dereq_,module,exports){ +(function (process){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +module.exports = Readable; + +/*<replacement>*/ +var isArray = _dereq_('isarray'); +/*</replacement>*/ + + +/*<replacement>*/ +var Buffer = _dereq_('buffer').Buffer; +/*</replacement>*/ + +Readable.ReadableState = ReadableState; + +var EE = _dereq_('events').EventEmitter; + +/*<replacement>*/ +if (!EE.listenerCount) EE.listenerCount = function(emitter, type) { + return emitter.listeners(type).length; +}; +/*</replacement>*/ + +var Stream = _dereq_('stream'); + +/*<replacement>*/ +var util = _dereq_('core-util-is'); +util.inherits = _dereq_('inherits'); +/*</replacement>*/ + +var StringDecoder; + +util.inherits(Readable, Stream); + +function ReadableState(options, stream) { + options = options || {}; + + // the point at which it stops calling _read() to fill the buffer + // Note: 0 is a valid value, means "don't call _read preemptively ever" + var hwm = options.highWaterMark; + this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024; + + // cast to ints. + this.highWaterMark = ~~this.highWaterMark; + + this.buffer = []; + this.length = 0; + this.pipes = null; + this.pipesCount = 0; + this.flowing = false; + this.ended = false; + this.endEmitted = false; + this.reading = false; + + // In streams that never have any data, and do push(null) right away, + // the consumer can miss the 'end' event if they do some I/O before + // consuming the stream. So, we don't emit('end') until some reading + // happens. + this.calledRead = false; + + // a flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, becuase any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. + this.sync = true; + + // whenever we return null, then we set a flag to say + // that we're awaiting a 'readable' event emission. + this.needReadable = false; + this.emittedReadable = false; + this.readableListening = false; + + + // object stream flag. Used to make read(n) ignore n and to + // make all the buffer merging and length checks go away + this.objectMode = !!options.objectMode; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // when piping, we only care about 'readable' events that happen + // after read()ing all the bytes and not getting any pushback. + this.ranOut = false; + + // the number of writers that are awaiting a drain event in .pipe()s + this.awaitDrain = 0; + + // if true, a maybeReadMore has been scheduled + this.readingMore = false; + + this.decoder = null; + this.encoding = null; + if (options.encoding) { + if (!StringDecoder) + StringDecoder = _dereq_('string_decoder/').StringDecoder; + this.decoder = new StringDecoder(options.encoding); + this.encoding = options.encoding; + } +} + +function Readable(options) { + if (!(this instanceof Readable)) + return new Readable(options); + + this._readableState = new ReadableState(options, this); + + // legacy + this.readable = true; + + Stream.call(this); +} + +// Manually shove something into the read() buffer. +// This returns true if the highWaterMark has not been hit yet, +// similar to how Writable.write() returns true if you should +// write() some more. +Readable.prototype.push = function(chunk, encoding) { + var state = this._readableState; + + if (typeof chunk === 'string' && !state.objectMode) { + encoding = encoding || state.defaultEncoding; + if (encoding !== state.encoding) { + chunk = new Buffer(chunk, encoding); + encoding = ''; + } + } + + return readableAddChunk(this, state, chunk, encoding, false); +}; + +// Unshift should *always* be something directly out of read() +Readable.prototype.unshift = function(chunk) { + var state = this._readableState; + return readableAddChunk(this, state, chunk, '', true); +}; + +function readableAddChunk(stream, state, chunk, encoding, addToFront) { + var er = chunkInvalid(state, chunk); + if (er) { + stream.emit('error', er); + } else if (chunk === null || chunk === undefined) { + state.reading = false; + if (!state.ended) + onEofChunk(stream, state); + } else if (state.objectMode || chunk && chunk.length > 0) { + if (state.ended && !addToFront) { + var e = new Error('stream.push() after EOF'); + stream.emit('error', e); + } else if (state.endEmitted && addToFront) { + var e = new Error('stream.unshift() after end event'); + stream.emit('error', e); + } else { + if (state.decoder && !addToFront && !encoding) + chunk = state.decoder.write(chunk); + + // update the buffer info. + state.length += state.objectMode ? 1 : chunk.length; + if (addToFront) { + state.buffer.unshift(chunk); + } else { + state.reading = false; + state.buffer.push(chunk); + } + + if (state.needReadable) + emitReadable(stream); + + maybeReadMore(stream, state); + } + } else if (!addToFront) { + state.reading = false; + } + + return needMoreData(state); +} + + + +// if it's past the high water mark, we can push in some more. +// Also, if we have no data yet, we can stand some +// more bytes. This is to work around cases where hwm=0, +// such as the repl. Also, if the push() triggered a +// readable event, and the user called read(largeNumber) such that +// needReadable was set, then we ought to push more, so that another +// 'readable' event will be triggered. +function needMoreData(state) { + return !state.ended && + (state.needReadable || + state.length < state.highWaterMark || + state.length === 0); +} + +// backwards compatibility. +Readable.prototype.setEncoding = function(enc) { + if (!StringDecoder) + StringDecoder = _dereq_('string_decoder/').StringDecoder; + this._readableState.decoder = new StringDecoder(enc); + this._readableState.encoding = enc; +}; + +// Don't raise the hwm > 128MB +var MAX_HWM = 0x800000; +function roundUpToNextPowerOf2(n) { + if (n >= MAX_HWM) { + n = MAX_HWM; + } else { + // Get the next highest power of 2 + n--; + for (var p = 1; p < 32; p <<= 1) n |= n >> p; + n++; + } + return n; +} + +function howMuchToRead(n, state) { + if (state.length === 0 && state.ended) + return 0; + + if (state.objectMode) + return n === 0 ? 0 : 1; + + if (n === null || isNaN(n)) { + // only flow one buffer at a time + if (state.flowing && state.buffer.length) + return state.buffer[0].length; + else + return state.length; + } + + if (n <= 0) + return 0; + + // If we're asking for more than the target buffer level, + // then raise the water mark. Bump up to the next highest + // power of 2, to prevent increasing it excessively in tiny + // amounts. + if (n > state.highWaterMark) + state.highWaterMark = roundUpToNextPowerOf2(n); + + // don't have that much. return null, unless we've ended. + if (n > state.length) { + if (!state.ended) { + state.needReadable = true; + return 0; + } else + return state.length; + } + + return n; +} + +// you can override either this method, or the async _read(n) below. +Readable.prototype.read = function(n) { + var state = this._readableState; + state.calledRead = true; + var nOrig = n; + var ret; + + if (typeof n !== 'number' || n > 0) + state.emittedReadable = false; + + // if we're doing read(0) to trigger a readable event, but we + // already have a bunch of data in the buffer, then just trigger + // the 'readable' event and move on. + if (n === 0 && + state.needReadable && + (state.length >= state.highWaterMark || state.ended)) { + emitReadable(this); + return null; + } + + n = howMuchToRead(n, state); + + // if we've ended, and we're now clear, then finish it up. + if (n === 0 && state.ended) { + ret = null; + + // In cases where the decoder did not receive enough data + // to produce a full chunk, then immediately received an + // EOF, state.buffer will contain [<Buffer >, <Buffer 00 ...>]. + // howMuchToRead will see this and coerce the amount to + // read to zero (because it's looking at the length of the + // first <Buffer > in state.buffer), and we'll end up here. + // + // This can only happen via state.decoder -- no other venue + // exists for pushing a zero-length chunk into state.buffer + // and triggering this behavior. In this case, we return our + // remaining data and end the stream, if appropriate. + if (state.length > 0 && state.decoder) { + ret = fromList(n, state); + state.length -= ret.length; + } + + if (state.length === 0) + endReadable(this); + + return ret; + } + + // All the actual chunk generation logic needs to be + // *below* the call to _read. The reason is that in certain + // synthetic stream cases, such as passthrough streams, _read + // may be a completely synchronous operation which may change + // the state of the read buffer, providing enough data when + // before there was *not* enough. + // + // So, the steps are: + // 1. Figure out what the state of things will be after we do + // a read from the buffer. + // + // 2. If that resulting state will trigger a _read, then call _read. + // Note that this may be asynchronous, or synchronous. Yes, it is + // deeply ugly to write APIs this way, but that still doesn't mean + // that the Readable class should behave improperly, as streams are + // designed to be sync/async agnostic. + // Take note if the _read call is sync or async (ie, if the read call + // has returned yet), so that we know whether or not it's safe to emit + // 'readable' etc. + // + // 3. Actually pull the requested chunks out of the buffer and return. + + // if we need a readable event, then we need to do some reading. + var doRead = state.needReadable; + + // if we currently have less than the highWaterMark, then also read some + if (state.length - n <= state.highWaterMark) + doRead = true; + + // however, if we've ended, then there's no point, and if we're already + // reading, then it's unnecessary. + if (state.ended || state.reading) + doRead = false; + + if (doRead) { + state.reading = true; + state.sync = true; + // if the length is currently zero, then we *need* a readable event. + if (state.length === 0) + state.needReadable = true; + // call internal read method + this._read(state.highWaterMark); + state.sync = false; + } + + // If _read called its callback synchronously, then `reading` + // will be false, and we need to re-evaluate how much data we + // can return to the user. + if (doRead && !state.reading) + n = howMuchToRead(nOrig, state); + + if (n > 0) + ret = fromList(n, state); + else + ret = null; + + if (ret === null) { + state.needReadable = true; + n = 0; + } + + state.length -= n; + + // If we have nothing in the buffer, then we want to know + // as soon as we *do* get something into the buffer. + if (state.length === 0 && !state.ended) + state.needReadable = true; + + // If we happened to read() exactly the remaining amount in the + // buffer, and the EOF has been seen at this point, then make sure + // that we emit 'end' on the very next tick. + if (state.ended && !state.endEmitted && state.length === 0) + endReadable(this); + + return ret; +}; + +function chunkInvalid(state, chunk) { + var er = null; + if (!Buffer.isBuffer(chunk) && + 'string' !== typeof chunk && + chunk !== null && + chunk !== undefined && + !state.objectMode) { + er = new TypeError('Invalid non-string/buffer chunk'); + } + return er; +} + + +function onEofChunk(stream, state) { + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) { + state.buffer.push(chunk); + state.length += state.objectMode ? 1 : chunk.length; + } + } + state.ended = true; + + // if we've ended and we have some data left, then emit + // 'readable' now to make sure it gets picked up. + if (state.length > 0) + emitReadable(stream); + else + endReadable(stream); +} + +// Don't emit readable right away in sync mode, because this can trigger +// another read() call => stack overflow. This way, it might trigger +// a nextTick recursion warning, but that's not so bad. +function emitReadable(stream) { + var state = stream._readableState; + state.needReadable = false; + if (state.emittedReadable) + return; + + state.emittedReadable = true; + if (state.sync) + process.nextTick(function() { + emitReadable_(stream); + }); + else + emitReadable_(stream); +} + +function emitReadable_(stream) { + stream.emit('readable'); +} + + +// at this point, the user has presumably seen the 'readable' event, +// and called read() to consume some data. that may have triggered +// in turn another _read(n) call, in which case reading = true if +// it's in progress. +// However, if we're not ended, or reading, and the length < hwm, +// then go ahead and try to read some more preemptively. +function maybeReadMore(stream, state) { + if (!state.readingMore) { + state.readingMore = true; + process.nextTick(function() { + maybeReadMore_(stream, state); + }); + } +} + +function maybeReadMore_(stream, state) { + var len = state.length; + while (!state.reading && !state.flowing && !state.ended && + state.length < state.highWaterMark) { + stream.read(0); + if (len === state.length) + // didn't get any data, stop spinning. + break; + else + len = state.length; + } + state.readingMore = false; +} + +// abstract method. to be overridden in specific implementation classes. +// call cb(er, data) where data is <= n in length. +// for virtual (non-string, non-buffer) streams, "length" is somewhat +// arbitrary, and perhaps not very meaningful. +Readable.prototype._read = function(n) { + this.emit('error', new Error('not implemented')); +}; + +Readable.prototype.pipe = function(dest, pipeOpts) { + var src = this; + var state = this._readableState; + + switch (state.pipesCount) { + case 0: + state.pipes = dest; + break; + case 1: + state.pipes = [state.pipes, dest]; + break; + default: + state.pipes.push(dest); + break; + } + state.pipesCount += 1; + + var doEnd = (!pipeOpts || pipeOpts.end !== false) && + dest !== process.stdout && + dest !== process.stderr; + + var endFn = doEnd ? onend : cleanup; + if (state.endEmitted) + process.nextTick(endFn); + else + src.once('end', endFn); + + dest.on('unpipe', onunpipe); + function onunpipe(readable) { + if (readable !== src) return; + cleanup(); + } + + function onend() { + dest.end(); + } + + // when the dest drains, it reduces the awaitDrain counter + // on the source. This would be more elegant with a .once() + // handler in flow(), but adding and removing repeatedly is + // too slow. + var ondrain = pipeOnDrain(src); + dest.on('drain', ondrain); + + function cleanup() { + // cleanup event handlers once the pipe is broken + dest.removeListener('close', onclose); + dest.removeListener('finish', onfinish); + dest.removeListener('drain', ondrain); + dest.removeListener('error', onerror); + dest.removeListener('unpipe', onunpipe); + src.removeListener('end', onend); + src.removeListener('end', cleanup); + + // if the reader is waiting for a drain event from this + // specific writer, then it would cause it to never start + // flowing again. + // So, if this is awaiting a drain, then we just call it now. + // If we don't know, then assume that we are waiting for one. + if (!dest._writableState || dest._writableState.needDrain) + ondrain(); + } + + // if the dest has an error, then stop piping into it. + // however, don't suppress the throwing behavior for this. + function onerror(er) { + unpipe(); + dest.removeListener('error', onerror); + if (EE.listenerCount(dest, 'error') === 0) + dest.emit('error', er); + } + // This is a brutally ugly hack to make sure that our error handler + // is attached before any userland ones. NEVER DO THIS. + if (!dest._events || !dest._events.error) + dest.on('error', onerror); + else if (isArray(dest._events.error)) + dest._events.error.unshift(onerror); + else + dest._events.error = [onerror, dest._events.error]; + + + + // Both close and finish should trigger unpipe, but only once. + function onclose() { + dest.removeListener('finish', onfinish); + unpipe(); + } + dest.once('close', onclose); + function onfinish() { + dest.removeListener('close', onclose); + unpipe(); + } + dest.once('finish', onfinish); + + function unpipe() { + src.unpipe(dest); + } + + // tell the dest that it's being piped to + dest.emit('pipe', src); + + // start the flow if it hasn't been started already. + if (!state.flowing) { + // the handler that waits for readable events after all + // the data gets sucked out in flow. + // This would be easier to follow with a .once() handler + // in flow(), but that is too slow. + this.on('readable', pipeOnReadable); + + state.flowing = true; + process.nextTick(function() { + flow(src); + }); + } + + return dest; +}; + +function pipeOnDrain(src) { + return function() { + var dest = this; + var state = src._readableState; + state.awaitDrain--; + if (state.awaitDrain === 0) + flow(src); + }; +} + +function flow(src) { + var state = src._readableState; + var chunk; + state.awaitDrain = 0; + + function write(dest, i, list) { + var written = dest.write(chunk); + if (false === written) { + state.awaitDrain++; + } + } + + while (state.pipesCount && null !== (chunk = src.read())) { + + if (state.pipesCount === 1) + write(state.pipes, 0, null); + else + forEach(state.pipes, write); + + src.emit('data', chunk); + + // if anyone needs a drain, then we have to wait for that. + if (state.awaitDrain > 0) + return; + } + + // if every destination was unpiped, either before entering this + // function, or in the while loop, then stop flowing. + // + // NB: This is a pretty rare edge case. + if (state.pipesCount === 0) { + state.flowing = false; + + // if there were data event listeners added, then switch to old mode. + if (EE.listenerCount(src, 'data') > 0) + emitDataEvents(src); + return; + } + + // at this point, no one needed a drain, so we just ran out of data + // on the next readable event, start it over again. + state.ranOut = true; +} + +function pipeOnReadable() { + if (this._readableState.ranOut) { + this._readableState.ranOut = false; + flow(this); + } +} + + +Readable.prototype.unpipe = function(dest) { + var state = this._readableState; + + // if we're not piping anywhere, then do nothing. + if (state.pipesCount === 0) + return this; + + // just one destination. most common case. + if (state.pipesCount === 1) { + // passed in one, but it's not the right one. + if (dest && dest !== state.pipes) + return this; + + if (!dest) + dest = state.pipes; + + // got a match. + state.pipes = null; + state.pipesCount = 0; + this.removeListener('readable', pipeOnReadable); + state.flowing = false; + if (dest) + dest.emit('unpipe', this); + return this; + } + + // slow case. multiple pipe destinations. + + if (!dest) { + // remove all. + var dests = state.pipes; + var len = state.pipesCount; + state.pipes = null; + state.pipesCount = 0; + this.removeListener('readable', pipeOnReadable); + state.flowing = false; + + for (var i = 0; i < len; i++) + dests[i].emit('unpipe', this); + return this; + } + + // try to find the right one. + var i = indexOf(state.pipes, dest); + if (i === -1) + return this; + + state.pipes.splice(i, 1); + state.pipesCount -= 1; + if (state.pipesCount === 1) + state.pipes = state.pipes[0]; + + dest.emit('unpipe', this); + + return this; +}; + +// set up data events if they are asked for +// Ensure readable listeners eventually get something +Readable.prototype.on = function(ev, fn) { + var res = Stream.prototype.on.call(this, ev, fn); + + if (ev === 'data' && !this._readableState.flowing) + emitDataEvents(this); + + if (ev === 'readable' && this.readable) { + var state = this._readableState; + if (!state.readableListening) { + state.readableListening = true; + state.emittedReadable = false; + state.needReadable = true; + if (!state.reading) { + this.read(0); + } else if (state.length) { + emitReadable(this, state); + } + } + } + + return res; +}; +Readable.prototype.addListener = Readable.prototype.on; + +// pause() and resume() are remnants of the legacy readable stream API +// If the user uses them, then switch into old mode. +Readable.prototype.resume = function() { + emitDataEvents(this); + this.read(0); + this.emit('resume'); +}; + +Readable.prototype.pause = function() { + emitDataEvents(this, true); + this.emit('pause'); +}; + +function emitDataEvents(stream, startPaused) { + var state = stream._readableState; + + if (state.flowing) { + // https://github.com/isaacs/readable-stream/issues/16 + throw new Error('Cannot switch to old mode now.'); + } + + var paused = startPaused || false; + var readable = false; + + // convert to an old-style stream. + stream.readable = true; + stream.pipe = Stream.prototype.pipe; + stream.on = stream.addListener = Stream.prototype.on; + + stream.on('readable', function() { + readable = true; + + var c; + while (!paused && (null !== (c = stream.read()))) + stream.emit('data', c); + + if (c === null) { + readable = false; + stream._readableState.needReadable = true; + } + }); + + stream.pause = function() { + paused = true; + this.emit('pause'); + }; + + stream.resume = function() { + paused = false; + if (readable) + process.nextTick(function() { + stream.emit('readable'); + }); + else + this.read(0); + this.emit('resume'); + }; + + // now make it start, just in case it hadn't already. + stream.emit('readable'); +} + +// wrap an old-style stream as the async data source. +// This is *not* part of the readable stream interface. +// It is an ugly unfortunate mess of history. +Readable.prototype.wrap = function(stream) { + var state = this._readableState; + var paused = false; + + var self = this; + stream.on('end', function() { + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) + self.push(chunk); + } + + self.push(null); + }); + + stream.on('data', function(chunk) { + if (state.decoder) + chunk = state.decoder.write(chunk); + + // don't skip over falsy values in objectMode + //if (state.objectMode && util.isNullOrUndefined(chunk)) + if (state.objectMode && (chunk === null || chunk === undefined)) + return; + else if (!state.objectMode && (!chunk || !chunk.length)) + return; + + var ret = self.push(chunk); + if (!ret) { + paused = true; + stream.pause(); + } + }); + + // proxy all the other methods. + // important when wrapping filters and duplexes. + for (var i in stream) { + if (typeof stream[i] === 'function' && + typeof this[i] === 'undefined') { + this[i] = function(method) { return function() { + return stream[method].apply(stream, arguments); + }}(i); + } + } + + // proxy certain important events. + var events = ['error', 'close', 'destroy', 'pause', 'resume']; + forEach(events, function(ev) { + stream.on(ev, self.emit.bind(self, ev)); + }); + + // when we try to consume some more bytes, simply unpause the + // underlying stream. + self._read = function(n) { + if (paused) { + paused = false; + stream.resume(); + } + }; + + return self; +}; + + + +// exposed for testing purposes only. +Readable._fromList = fromList; + +// Pluck off n bytes from an array of buffers. +// Length is the combined lengths of all the buffers in the list. +function fromList(n, state) { + var list = state.buffer; + var length = state.length; + var stringMode = !!state.decoder; + var objectMode = !!state.objectMode; + var ret; + + // nothing in the list, definitely empty. + if (list.length === 0) + return null; + + if (length === 0) + ret = null; + else if (objectMode) + ret = list.shift(); + else if (!n || n >= length) { + // read it all, truncate the array. + if (stringMode) + ret = list.join(''); + else + ret = Buffer.concat(list, length); + list.length = 0; + } else { + // read just some of it. + if (n < list[0].length) { + // just take a part of the first list item. + // slice is the same for buffers and strings. + var buf = list[0]; + ret = buf.slice(0, n); + list[0] = buf.slice(n); + } else if (n === list[0].length) { + // first list is a perfect match + ret = list.shift(); + } else { + // complex case. + // we have enough to cover it, but it spans past the first buffer. + if (stringMode) + ret = ''; + else + ret = new Buffer(n); + + var c = 0; + for (var i = 0, l = list.length; i < l && c < n; i++) { + var buf = list[0]; + var cpy = Math.min(n - c, buf.length); + + if (stringMode) + ret += buf.slice(0, cpy); + else + buf.copy(ret, c, 0, cpy); + + if (cpy < buf.length) + list[0] = buf.slice(cpy); + else + list.shift(); + + c += cpy; + } + } + } + + return ret; +} + +function endReadable(stream) { + var state = stream._readableState; + + // If we get here before consuming all the bytes, then that is a + // bug in node. Should never happen. + if (state.length > 0) + throw new Error('endReadable called on non-empty stream'); + + if (!state.endEmitted && state.calledRead) { + state.ended = true; + process.nextTick(function() { + // Check that we didn't get one last unshift. + if (!state.endEmitted && state.length === 0) { + state.endEmitted = true; + stream.readable = false; + stream.emit('end'); + } + }); + } +} + +function forEach (xs, f) { + for (var i = 0, l = xs.length; i < l; i++) { + f(xs[i], i); + } +} + +function indexOf (xs, x) { + for (var i = 0, l = xs.length; i < l; i++) { + if (xs[i] === x) return i; + } + return -1; +} + +}).call(this,_dereq_('_process')) +},{"_process":24,"buffer":17,"core-util-is":31,"events":21,"inherits":44,"isarray":22,"stream":36,"string_decoder/":37}],29:[function(_dereq_,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + +// a transform stream is a readable/writable stream where you do +// something with the data. Sometimes it's called a "filter", +// but that's not a great name for it, since that implies a thing where +// some bits pass through, and others are simply ignored. (That would +// be a valid example of a transform, of course.) +// +// While the output is causally related to the input, it's not a +// necessarily symmetric or synchronous transformation. For example, +// a zlib stream might take multiple plain-text writes(), and then +// emit a single compressed chunk some time in the future. +// +// Here's how this works: +// +// The Transform stream has all the aspects of the readable and writable +// stream classes. When you write(chunk), that calls _write(chunk,cb) +// internally, and returns false if there's a lot of pending writes +// buffered up. When you call read(), that calls _read(n) until +// there's enough pending readable data buffered up. +// +// In a transform stream, the written data is placed in a buffer. When +// _read(n) is called, it transforms the queued up data, calling the +// buffered _write cb's as it consumes chunks. If consuming a single +// written chunk would result in multiple output chunks, then the first +// outputted bit calls the readcb, and subsequent chunks just go into +// the read buffer, and will cause it to emit 'readable' if necessary. +// +// This way, back-pressure is actually determined by the reading side, +// since _read has to be called to start processing a new chunk. However, +// a pathological inflate type of transform can cause excessive buffering +// here. For example, imagine a stream where every byte of input is +// interpreted as an integer from 0-255, and then results in that many +// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in +// 1kb of data being output. In this case, you could write a very small +// amount of input, and end up with a very large amount of output. In +// such a pathological inflating mechanism, there'd be no way to tell +// the system to stop doing the transform. A single 4MB write could +// cause the system to run out of memory. +// +// However, even in such a pathological case, only a single written chunk +// would be consumed, and then the rest would wait (un-transformed) until +// the results of the previous transformed chunk were consumed. + +module.exports = Transform; + +var Duplex = _dereq_('./_stream_duplex'); + +/*<replacement>*/ +var util = _dereq_('core-util-is'); +util.inherits = _dereq_('inherits'); +/*</replacement>*/ + +util.inherits(Transform, Duplex); + + +function TransformState(options, stream) { + this.afterTransform = function(er, data) { + return afterTransform(stream, er, data); + }; + + this.needTransform = false; + this.transforming = false; + this.writecb = null; + this.writechunk = null; +} + +function afterTransform(stream, er, data) { + var ts = stream._transformState; + ts.transforming = false; + + var cb = ts.writecb; + + if (!cb) + return stream.emit('error', new Error('no writecb in Transform class')); + + ts.writechunk = null; + ts.writecb = null; + + if (data !== null && data !== undefined) + stream.push(data); + + if (cb) + cb(er); + + var rs = stream._readableState; + rs.reading = false; + if (rs.needReadable || rs.length < rs.highWaterMark) { + stream._read(rs.highWaterMark); + } +} + + +function Transform(options) { + if (!(this instanceof Transform)) + return new Transform(options); + + Duplex.call(this, options); + + var ts = this._transformState = new TransformState(options, this); + + // when the writable side finishes, then flush out anything remaining. + var stream = this; + + // start out asking for a readable event once data is transformed. + this._readableState.needReadable = true; + + // we have implemented the _read method, and done the other things + // that Readable wants before the first _read call, so unset the + // sync guard flag. + this._readableState.sync = false; + + this.once('finish', function() { + if ('function' === typeof this._flush) + this._flush(function(er) { + done(stream, er); + }); + else + done(stream); + }); +} + +Transform.prototype.push = function(chunk, encoding) { + this._transformState.needTransform = false; + return Duplex.prototype.push.call(this, chunk, encoding); +}; + +// This is the part where you do stuff! +// override this function in implementation classes. +// 'chunk' is an input chunk. +// +// Call `push(newChunk)` to pass along transformed output +// to the readable side. You may call 'push' zero or more times. +// +// Call `cb(err)` when you are done with this chunk. If you pass +// an error, then that'll put the hurt on the whole operation. If you +// never call cb(), then you'll never get another chunk. +Transform.prototype._transform = function(chunk, encoding, cb) { + throw new Error('not implemented'); +}; + +Transform.prototype._write = function(chunk, encoding, cb) { + var ts = this._transformState; + ts.writecb = cb; + ts.writechunk = chunk; + ts.writeencoding = encoding; + if (!ts.transforming) { + var rs = this._readableState; + if (ts.needTransform || + rs.needReadable || + rs.length < rs.highWaterMark) + this._read(rs.highWaterMark); + } +}; + +// Doesn't matter what the args are here. +// _transform does all the work. +// That we got here means that the readable side wants more data. +Transform.prototype._read = function(n) { + var ts = this._transformState; + + if (ts.writechunk !== null && ts.writecb && !ts.transforming) { + ts.transforming = true; + this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); + } else { + // mark that we need a transform, so that any data that comes in + // will get processed, now that we've asked for it. + ts.needTransform = true; + } +}; + + +function done(stream, er) { + if (er) + return stream.emit('error', er); + + // if there's nothing in the write buffer, then that means + // that nothing more will ever be provided + var ws = stream._writableState; + var rs = stream._readableState; + var ts = stream._transformState; + + if (ws.length) + throw new Error('calling transform done when ws.length != 0'); + + if (ts.transforming) + throw new Error('calling transform done when still transforming'); + + return stream.push(null); +} + +},{"./_stream_duplex":26,"core-util-is":31,"inherits":44}],30:[function(_dereq_,module,exports){ +(function (process){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// A bit simpler than readable streams. +// Implement an async ._write(chunk, cb), and it'll handle all +// the drain event emission and buffering. + +module.exports = Writable; + +/*<replacement>*/ +var Buffer = _dereq_('buffer').Buffer; +/*</replacement>*/ + +Writable.WritableState = WritableState; + + +/*<replacement>*/ +var util = _dereq_('core-util-is'); +util.inherits = _dereq_('inherits'); +/*</replacement>*/ + +var Stream = _dereq_('stream'); + +util.inherits(Writable, Stream); + +function WriteReq(chunk, encoding, cb) { + this.chunk = chunk; + this.encoding = encoding; + this.callback = cb; +} + +function WritableState(options, stream) { + options = options || {}; + + // the point at which write() starts returning false + // Note: 0 is a valid value, means that we always return false if + // the entire buffer is not flushed immediately on write() + var hwm = options.highWaterMark; + this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024; + + // object stream flag to indicate whether or not this stream + // contains buffers or objects. + this.objectMode = !!options.objectMode; + + // cast to ints. + this.highWaterMark = ~~this.highWaterMark; + + this.needDrain = false; + // at the start of calling end() + this.ending = false; + // when end() has been called, and returned + this.ended = false; + // when 'finish' is emitted + this.finished = false; + + // should we decode strings into buffers before passing to _write? + // this is here so that some node-core streams can optimize string + // handling at a lower level. + var noDecode = options.decodeStrings === false; + this.decodeStrings = !noDecode; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // not an actual buffer we keep track of, but a measurement + // of how much we're waiting to get pushed to some underlying + // socket or file. + this.length = 0; + + // a flag to see when we're in the middle of a write. + this.writing = false; + + // a flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, becuase any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. + this.sync = true; + + // a flag to know if we're processing previously buffered items, which + // may call the _write() callback in the same tick, so that we don't + // end up in an overlapped onwrite situation. + this.bufferProcessing = false; + + // the callback that's passed to _write(chunk,cb) + this.onwrite = function(er) { + onwrite(stream, er); + }; + + // the callback that the user supplies to write(chunk,encoding,cb) + this.writecb = null; + + // the amount that is being written when _write is called. + this.writelen = 0; + + this.buffer = []; + + // True if the error was already emitted and should not be thrown again + this.errorEmitted = false; +} + +function Writable(options) { + var Duplex = _dereq_('./_stream_duplex'); + + // Writable ctor is applied to Duplexes, though they're not + // instanceof Writable, they're instanceof Readable. + if (!(this instanceof Writable) && !(this instanceof Duplex)) + return new Writable(options); + + this._writableState = new WritableState(options, this); + + // legacy. + this.writable = true; + + Stream.call(this); +} + +// Otherwise people can pipe Writable streams, which is just wrong. +Writable.prototype.pipe = function() { + this.emit('error', new Error('Cannot pipe. Not readable.')); +}; + + +function writeAfterEnd(stream, state, cb) { + var er = new Error('write after end'); + // TODO: defer error events consistently everywhere, not just the cb + stream.emit('error', er); + process.nextTick(function() { + cb(er); + }); +} + +// If we get something that is not a buffer, string, null, or undefined, +// and we're not in objectMode, then that's an error. +// Otherwise stream chunks are all considered to be of length=1, and the +// watermarks determine how many objects to keep in the buffer, rather than +// how many bytes or characters. +function validChunk(stream, state, chunk, cb) { + var valid = true; + if (!Buffer.isBuffer(chunk) && + 'string' !== typeof chunk && + chunk !== null && + chunk !== undefined && + !state.objectMode) { + var er = new TypeError('Invalid non-string/buffer chunk'); + stream.emit('error', er); + process.nextTick(function() { + cb(er); + }); + valid = false; + } + return valid; +} + +Writable.prototype.write = function(chunk, encoding, cb) { + var state = this._writableState; + var ret = false; + + if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (Buffer.isBuffer(chunk)) + encoding = 'buffer'; + else if (!encoding) + encoding = state.defaultEncoding; + + if (typeof cb !== 'function') + cb = function() {}; + + if (state.ended) + writeAfterEnd(this, state, cb); + else if (validChunk(this, state, chunk, cb)) + ret = writeOrBuffer(this, state, chunk, encoding, cb); + + return ret; +}; + +function decodeChunk(state, chunk, encoding) { + if (!state.objectMode && + state.decodeStrings !== false && + typeof chunk === 'string') { + chunk = new Buffer(chunk, encoding); + } + return chunk; +} + +// if we're already writing something, then just put this +// in the queue, and wait our turn. Otherwise, call _write +// If we return false, then we need a drain event, so set that flag. +function writeOrBuffer(stream, state, chunk, encoding, cb) { + chunk = decodeChunk(state, chunk, encoding); + if (Buffer.isBuffer(chunk)) + encoding = 'buffer'; + var len = state.objectMode ? 1 : chunk.length; + + state.length += len; + + var ret = state.length < state.highWaterMark; + // we must ensure that previous needDrain will not be reset to false. + if (!ret) + state.needDrain = true; + + if (state.writing) + state.buffer.push(new WriteReq(chunk, encoding, cb)); + else + doWrite(stream, state, len, chunk, encoding, cb); + + return ret; +} + +function doWrite(stream, state, len, chunk, encoding, cb) { + state.writelen = len; + state.writecb = cb; + state.writing = true; + state.sync = true; + stream._write(chunk, encoding, state.onwrite); + state.sync = false; +} + +function onwriteError(stream, state, sync, er, cb) { + if (sync) + process.nextTick(function() { + cb(er); + }); + else + cb(er); + + stream._writableState.errorEmitted = true; + stream.emit('error', er); +} + +function onwriteStateUpdate(state) { + state.writing = false; + state.writecb = null; + state.length -= state.writelen; + state.writelen = 0; +} + +function onwrite(stream, er) { + var state = stream._writableState; + var sync = state.sync; + var cb = state.writecb; + + onwriteStateUpdate(state); + + if (er) + onwriteError(stream, state, sync, er, cb); + else { + // Check if we're actually ready to finish, but don't emit yet + var finished = needFinish(stream, state); + + if (!finished && !state.bufferProcessing && state.buffer.length) + clearBuffer(stream, state); + + if (sync) { + process.nextTick(function() { + afterWrite(stream, state, finished, cb); + }); + } else { + afterWrite(stream, state, finished, cb); + } + } +} + +function afterWrite(stream, state, finished, cb) { + if (!finished) + onwriteDrain(stream, state); + cb(); + if (finished) + finishMaybe(stream, state); +} + +// Must force callback to be called on nextTick, so that we don't +// emit 'drain' before the write() consumer gets the 'false' return +// value, and has a chance to attach a 'drain' listener. +function onwriteDrain(stream, state) { + if (state.length === 0 && state.needDrain) { + state.needDrain = false; + stream.emit('drain'); + } +} + + +// if there's something in the buffer waiting, then process it +function clearBuffer(stream, state) { + state.bufferProcessing = true; + + for (var c = 0; c < state.buffer.length; c++) { + var entry = state.buffer[c]; + var chunk = entry.chunk; + var encoding = entry.encoding; + var cb = entry.callback; + var len = state.objectMode ? 1 : chunk.length; + + doWrite(stream, state, len, chunk, encoding, cb); + + // if we didn't call the onwrite immediately, then + // it means that we need to wait until it does. + // also, that means that the chunk and cb are currently + // being processed, so move the buffer counter past them. + if (state.writing) { + c++; + break; + } + } + + state.bufferProcessing = false; + if (c < state.buffer.length) + state.buffer = state.buffer.slice(c); + else + state.buffer.length = 0; +} + +Writable.prototype._write = function(chunk, encoding, cb) { + cb(new Error('not implemented')); +}; + +Writable.prototype.end = function(chunk, encoding, cb) { + var state = this._writableState; + + if (typeof chunk === 'function') { + cb = chunk; + chunk = null; + encoding = null; + } else if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (typeof chunk !== 'undefined' && chunk !== null) + this.write(chunk, encoding); + + // ignore unnecessary end() calls. + if (!state.ending && !state.finished) + endWritable(this, state, cb); +}; + + +function needFinish(stream, state) { + return (state.ending && + state.length === 0 && + !state.finished && + !state.writing); +} + +function finishMaybe(stream, state) { + var need = needFinish(stream, state); + if (need) { + state.finished = true; + stream.emit('finish'); + } + return need; +} + +function endWritable(stream, state, cb) { + state.ending = true; + finishMaybe(stream, state); + if (cb) { + if (state.finished) + process.nextTick(cb); + else + stream.once('finish', cb); + } + state.ended = true; +} + +}).call(this,_dereq_('_process')) +},{"./_stream_duplex":26,"_process":24,"buffer":17,"core-util-is":31,"inherits":44,"stream":36}],31:[function(_dereq_,module,exports){ +(function (Buffer){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. +function isArray(ar) { + return Array.isArray(ar); +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return isObject(re) && objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return isObject(d) && objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return isObject(e) && + (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +function isBuffer(arg) { + return Buffer.isBuffer(arg); +} +exports.isBuffer = isBuffer; + +function objectToString(o) { + return Object.prototype.toString.call(o); +} +}).call(this,_dereq_("buffer").Buffer) +},{"buffer":17}],32:[function(_dereq_,module,exports){ +module.exports = _dereq_("./lib/_stream_passthrough.js") + +},{"./lib/_stream_passthrough.js":27}],33:[function(_dereq_,module,exports){ +var Stream = _dereq_('stream'); // hack to fix a circular dependency issue when used with browserify +exports = module.exports = _dereq_('./lib/_stream_readable.js'); +exports.Stream = Stream; +exports.Readable = exports; +exports.Writable = _dereq_('./lib/_stream_writable.js'); +exports.Duplex = _dereq_('./lib/_stream_duplex.js'); +exports.Transform = _dereq_('./lib/_stream_transform.js'); +exports.PassThrough = _dereq_('./lib/_stream_passthrough.js'); + +},{"./lib/_stream_duplex.js":26,"./lib/_stream_passthrough.js":27,"./lib/_stream_readable.js":28,"./lib/_stream_transform.js":29,"./lib/_stream_writable.js":30,"stream":36}],34:[function(_dereq_,module,exports){ +module.exports = _dereq_("./lib/_stream_transform.js") + +},{"./lib/_stream_transform.js":29}],35:[function(_dereq_,module,exports){ +module.exports = _dereq_("./lib/_stream_writable.js") + +},{"./lib/_stream_writable.js":30}],36:[function(_dereq_,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +module.exports = Stream; + +var EE = _dereq_('events').EventEmitter; +var inherits = _dereq_('inherits'); + +inherits(Stream, EE); +Stream.Readable = _dereq_('readable-stream/readable.js'); +Stream.Writable = _dereq_('readable-stream/writable.js'); +Stream.Duplex = _dereq_('readable-stream/duplex.js'); +Stream.Transform = _dereq_('readable-stream/transform.js'); +Stream.PassThrough = _dereq_('readable-stream/passthrough.js'); + +// Backwards-compat with node 0.4.x +Stream.Stream = Stream; + + + +// old-style streams. Note that the pipe method (the only relevant +// part of this class) is overridden in the Readable class. + +function Stream() { + EE.call(this); +} + +Stream.prototype.pipe = function(dest, options) { + var source = this; + + function ondata(chunk) { + if (dest.writable) { + if (false === dest.write(chunk) && source.pause) { + source.pause(); + } + } + } + + source.on('data', ondata); + + function ondrain() { + if (source.readable && source.resume) { + source.resume(); + } + } + + dest.on('drain', ondrain); + + // If the 'end' option is not supplied, dest.end() will be called when + // source gets the 'end' or 'close' events. Only dest.end() once. + if (!dest._isStdio && (!options || options.end !== false)) { + source.on('end', onend); + source.on('close', onclose); + } + + var didOnEnd = false; + function onend() { + if (didOnEnd) return; + didOnEnd = true; + + dest.end(); + } + + + function onclose() { + if (didOnEnd) return; + didOnEnd = true; + + if (typeof dest.destroy === 'function') dest.destroy(); + } + + // don't leave dangling pipes when there are errors. + function onerror(er) { + cleanup(); + if (EE.listenerCount(this, 'error') === 0) { + throw er; // Unhandled stream error in pipe. + } + } + + source.on('error', onerror); + dest.on('error', onerror); + + // remove all the event listeners that were added. + function cleanup() { + source.removeListener('data', ondata); + dest.removeListener('drain', ondrain); + + source.removeListener('end', onend); + source.removeListener('close', onclose); + + source.removeListener('error', onerror); + dest.removeListener('error', onerror); + + source.removeListener('end', cleanup); + source.removeListener('close', cleanup); + + dest.removeListener('close', cleanup); + } + + source.on('end', cleanup); + source.on('close', cleanup); + + dest.on('close', cleanup); + + dest.emit('pipe', source); + + // Allow for unix-like usage: A.pipe(B).pipe(C) + return dest; +}; + +},{"events":21,"inherits":44,"readable-stream/duplex.js":25,"readable-stream/passthrough.js":32,"readable-stream/readable.js":33,"readable-stream/transform.js":34,"readable-stream/writable.js":35}],37:[function(_dereq_,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var Buffer = _dereq_('buffer').Buffer; + +var isBufferEncoding = Buffer.isEncoding + || function(encoding) { + switch (encoding && encoding.toLowerCase()) { + case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true; + default: return false; + } + } + + +function assertEncoding(encoding) { + if (encoding && !isBufferEncoding(encoding)) { + throw new Error('Unknown encoding: ' + encoding); + } +} + +// StringDecoder provides an interface for efficiently splitting a series of +// buffers into a series of JS strings without breaking apart multi-byte +// characters. CESU-8 is handled as part of the UTF-8 encoding. +// +// @TODO Handling all encodings inside a single object makes it very difficult +// to reason about this code, so it should be split up in the future. +// @TODO There should be a utf8-strict encoding that rejects invalid UTF-8 code +// points as used by CESU-8. +var StringDecoder = exports.StringDecoder = function(encoding) { + this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, ''); + assertEncoding(encoding); + switch (this.encoding) { + case 'utf8': + // CESU-8 represents each of Surrogate Pair by 3-bytes + this.surrogateSize = 3; + break; + case 'ucs2': + case 'utf16le': + // UTF-16 represents each of Surrogate Pair by 2-bytes + this.surrogateSize = 2; + this.detectIncompleteChar = utf16DetectIncompleteChar; + break; + case 'base64': + // Base-64 stores 3 bytes in 4 chars, and pads the remainder. + this.surrogateSize = 3; + this.detectIncompleteChar = base64DetectIncompleteChar; + break; + default: + this.write = passThroughWrite; + return; + } + + // Enough space to store all bytes of a single character. UTF-8 needs 4 + // bytes, but CESU-8 may require up to 6 (3 bytes per surrogate). + this.charBuffer = new Buffer(6); + // Number of bytes received for the current incomplete multi-byte character. + this.charReceived = 0; + // Number of bytes expected for the current incomplete multi-byte character. + this.charLength = 0; +}; + + +// write decodes the given buffer and returns it as JS string that is +// guaranteed to not contain any partial multi-byte characters. Any partial +// character found at the end of the buffer is buffered up, and will be +// returned when calling write again with the remaining bytes. +// +// Note: Converting a Buffer containing an orphan surrogate to a String +// currently works, but converting a String to a Buffer (via `new Buffer`, or +// Buffer#write) will replace incomplete surrogates with the unicode +// replacement character. See https://codereview.chromium.org/121173009/ . +StringDecoder.prototype.write = function(buffer) { + var charStr = ''; + // if our last write ended with an incomplete multibyte character + while (this.charLength) { + // determine how many remaining bytes this buffer has to offer for this char + var available = (buffer.length >= this.charLength - this.charReceived) ? + this.charLength - this.charReceived : + buffer.length; + + // add the new bytes to the char buffer + buffer.copy(this.charBuffer, this.charReceived, 0, available); + this.charReceived += available; + + if (this.charReceived < this.charLength) { + // still not enough chars in this buffer? wait for more ... + return ''; + } + + // remove bytes belonging to the current character from the buffer + buffer = buffer.slice(available, buffer.length); + + // get the character that was split + charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding); + + // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character + var charCode = charStr.charCodeAt(charStr.length - 1); + if (charCode >= 0xD800 && charCode <= 0xDBFF) { + this.charLength += this.surrogateSize; + charStr = ''; + continue; + } + this.charReceived = this.charLength = 0; + + // if there are no more bytes in this buffer, just emit our char + if (buffer.length === 0) { + return charStr; + } + break; + } + + // determine and set charLength / charReceived + this.detectIncompleteChar(buffer); + + var end = buffer.length; + if (this.charLength) { + // buffer the incomplete character bytes we got + buffer.copy(this.charBuffer, 0, buffer.length - this.charReceived, end); + end -= this.charReceived; + } + + charStr += buffer.toString(this.encoding, 0, end); + + var end = charStr.length - 1; + var charCode = charStr.charCodeAt(end); + // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character + if (charCode >= 0xD800 && charCode <= 0xDBFF) { + var size = this.surrogateSize; + this.charLength += size; + this.charReceived += size; + this.charBuffer.copy(this.charBuffer, size, 0, size); + buffer.copy(this.charBuffer, 0, 0, size); + return charStr.substring(0, end); + } + + // or just emit the charStr + return charStr; +}; + +// detectIncompleteChar determines if there is an incomplete UTF-8 character at +// the end of the given buffer. If so, it sets this.charLength to the byte +// length that character, and sets this.charReceived to the number of bytes +// that are available for this character. +StringDecoder.prototype.detectIncompleteChar = function(buffer) { + // determine how many bytes we have to check at the end of this buffer + var i = (buffer.length >= 3) ? 3 : buffer.length; + + // Figure out if one of the last i bytes of our buffer announces an + // incomplete char. + for (; i > 0; i--) { + var c = buffer[buffer.length - i]; + + // See http://en.wikipedia.org/wiki/UTF-8#Description + + // 110XXXXX + if (i == 1 && c >> 5 == 0x06) { + this.charLength = 2; + break; + } + + // 1110XXXX + if (i <= 2 && c >> 4 == 0x0E) { + this.charLength = 3; + break; + } + + // 11110XXX + if (i <= 3 && c >> 3 == 0x1E) { + this.charLength = 4; + break; + } + } + this.charReceived = i; +}; + +StringDecoder.prototype.end = function(buffer) { + var res = ''; + if (buffer && buffer.length) + res = this.write(buffer); + + if (this.charReceived) { + var cr = this.charReceived; + var buf = this.charBuffer; + var enc = this.encoding; + res += buf.slice(0, cr).toString(enc); + } + + return res; +}; + +function passThroughWrite(buffer) { + return buffer.toString(this.encoding); +} + +function utf16DetectIncompleteChar(buffer) { + this.charReceived = buffer.length % 2; + this.charLength = this.charReceived ? 2 : 0; +} + +function base64DetectIncompleteChar(buffer) { + this.charReceived = buffer.length % 3; + this.charLength = this.charReceived ? 3 : 0; +} + +},{"buffer":17}],38:[function(_dereq_,module,exports){ +module.exports = function isBuffer(arg) { + return arg && typeof arg === 'object' + && typeof arg.copy === 'function' + && typeof arg.fill === 'function' + && typeof arg.readUInt8 === 'function'; +} +},{}],39:[function(_dereq_,module,exports){ +(function (process,global){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var formatRegExp = /%[sdj%]/g; +exports.format = function(f) { + if (!isString(f)) { + var objects = []; + for (var i = 0; i < arguments.length; i++) { + objects.push(inspect(arguments[i])); + } + return objects.join(' '); + } + + var i = 1; + var args = arguments; + var len = args.length; + var str = String(f).replace(formatRegExp, function(x) { + if (x === '%') return '%'; + if (i >= len) return x; + switch (x) { + case '%s': return String(args[i++]); + case '%d': return Number(args[i++]); + case '%j': + try { + return JSON.stringify(args[i++]); + } catch (_) { + return '[Circular]'; + } + default: + return x; + } + }); + for (var x = args[i]; i < len; x = args[++i]) { + if (isNull(x) || !isObject(x)) { + str += ' ' + x; + } else { + str += ' ' + inspect(x); + } + } + return str; +}; + + +// Mark that a method should not be used. +// Returns a modified function which warns once by default. +// If --no-deprecation is set, then it is a no-op. +exports.deprecate = function(fn, msg) { + // Allow for deprecating things in the process of starting up. + if (isUndefined(global.process)) { + return function() { + return exports.deprecate(fn, msg).apply(this, arguments); + }; + } + + if (process.noDeprecation === true) { + return fn; + } + + var warned = false; + function deprecated() { + if (!warned) { + if (process.throwDeprecation) { + throw new Error(msg); + } else if (process.traceDeprecation) { + console.trace(msg); + } else { + console.error(msg); + } + warned = true; + } + return fn.apply(this, arguments); + } + + return deprecated; +}; + + +var debugs = {}; +var debugEnviron; +exports.debuglog = function(set) { + if (isUndefined(debugEnviron)) + debugEnviron = process.env.NODE_DEBUG || ''; + set = set.toUpperCase(); + if (!debugs[set]) { + if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { + var pid = process.pid; + debugs[set] = function() { + var msg = exports.format.apply(exports, arguments); + console.error('%s %d: %s', set, pid, msg); + }; + } else { + debugs[set] = function() {}; + } + } + return debugs[set]; +}; + + +/** + * Echos the value of a value. Trys to print the value out + * in the best way possible given the different types. + * + * @param {Object} obj The object to print out. + * @param {Object} opts Optional options object that alters the output. + */ +/* legacy: obj, showHidden, depth, colors*/ +function inspect(obj, opts) { + // default options + var ctx = { + seen: [], + stylize: stylizeNoColor + }; + // legacy... + if (arguments.length >= 3) ctx.depth = arguments[2]; + if (arguments.length >= 4) ctx.colors = arguments[3]; + if (isBoolean(opts)) { + // legacy... + ctx.showHidden = opts; + } else if (opts) { + // got an "options" object + exports._extend(ctx, opts); + } + // set default options + if (isUndefined(ctx.showHidden)) ctx.showHidden = false; + if (isUndefined(ctx.depth)) ctx.depth = 2; + if (isUndefined(ctx.colors)) ctx.colors = false; + if (isUndefined(ctx.customInspect)) ctx.customInspect = true; + if (ctx.colors) ctx.stylize = stylizeWithColor; + return formatValue(ctx, obj, ctx.depth); +} +exports.inspect = inspect; + + +// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics +inspect.colors = { + 'bold' : [1, 22], + 'italic' : [3, 23], + 'underline' : [4, 24], + 'inverse' : [7, 27], + 'white' : [37, 39], + 'grey' : [90, 39], + 'black' : [30, 39], + 'blue' : [34, 39], + 'cyan' : [36, 39], + 'green' : [32, 39], + 'magenta' : [35, 39], + 'red' : [31, 39], + 'yellow' : [33, 39] +}; + +// Don't use 'blue' not visible on cmd.exe +inspect.styles = { + 'special': 'cyan', + 'number': 'yellow', + 'boolean': 'yellow', + 'undefined': 'grey', + 'null': 'bold', + 'string': 'green', + 'date': 'magenta', + // "name": intentionally not styling + 'regexp': 'red' +}; + + +function stylizeWithColor(str, styleType) { + var style = inspect.styles[styleType]; + + if (style) { + return '\u001b[' + inspect.colors[style][0] + 'm' + str + + '\u001b[' + inspect.colors[style][1] + 'm'; + } else { + return str; + } +} + + +function stylizeNoColor(str, styleType) { + return str; +} + + +function arrayToHash(array) { + var hash = {}; + + array.forEach(function(val, idx) { + hash[val] = true; + }); + + return hash; +} + + +function formatValue(ctx, value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if (ctx.customInspect && + value && + isFunction(value.inspect) && + // Filter out the util module, it's inspect function is special + value.inspect !== exports.inspect && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + var ret = value.inspect(recurseTimes, ctx); + if (!isString(ret)) { + ret = formatValue(ctx, ret, recurseTimes); + } + return ret; + } + + // Primitive types cannot have properties + var primitive = formatPrimitive(ctx, value); + if (primitive) { + return primitive; + } + + // Look up the keys of the object. + var keys = Object.keys(value); + var visibleKeys = arrayToHash(keys); + + if (ctx.showHidden) { + keys = Object.getOwnPropertyNames(value); + } + + // IE doesn't make error fields non-enumerable + // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx + if (isError(value) + && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { + return formatError(value); + } + + // Some type of object without properties can be shortcutted. + if (keys.length === 0) { + if (isFunction(value)) { + var name = value.name ? ': ' + value.name : ''; + return ctx.stylize('[Function' + name + ']', 'special'); + } + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } + if (isDate(value)) { + return ctx.stylize(Date.prototype.toString.call(value), 'date'); + } + if (isError(value)) { + return formatError(value); + } + } + + var base = '', array = false, braces = ['{', '}']; + + // Make Array say that they are Array + if (isArray(value)) { + array = true; + braces = ['[', ']']; + } + + // Make functions say that they are functions + if (isFunction(value)) { + var n = value.name ? ': ' + value.name : ''; + base = ' [Function' + n + ']'; + } + + // Make RegExps say that they are RegExps + if (isRegExp(value)) { + base = ' ' + RegExp.prototype.toString.call(value); + } + + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + Date.prototype.toUTCString.call(value); + } + + // Make error with message first say the error + if (isError(value)) { + base = ' ' + formatError(value); + } + + if (keys.length === 0 && (!array || value.length == 0)) { + return braces[0] + base + braces[1]; + } + + if (recurseTimes < 0) { + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } else { + return ctx.stylize('[Object]', 'special'); + } + } + + ctx.seen.push(value); + + var output; + if (array) { + output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); + } else { + output = keys.map(function(key) { + return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); + }); + } + + ctx.seen.pop(); + + return reduceToSingleString(output, base, braces); +} + + +function formatPrimitive(ctx, value) { + if (isUndefined(value)) + return ctx.stylize('undefined', 'undefined'); + if (isString(value)) { + var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return ctx.stylize(simple, 'string'); + } + if (isNumber(value)) + return ctx.stylize('' + value, 'number'); + if (isBoolean(value)) + return ctx.stylize('' + value, 'boolean'); + // For some reason typeof null is "object", so special case here. + if (isNull(value)) + return ctx.stylize('null', 'null'); +} + + +function formatError(value) { + return '[' + Error.prototype.toString.call(value) + ']'; +} + + +function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { + var output = []; + for (var i = 0, l = value.length; i < l; ++i) { + if (hasOwnProperty(value, String(i))) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + String(i), true)); + } else { + output.push(''); + } + } + keys.forEach(function(key) { + if (!key.match(/^\d+$/)) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + key, true)); + } + }); + return output; +} + + +function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { + var name, str, desc; + desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; + if (desc.get) { + if (desc.set) { + str = ctx.stylize('[Getter/Setter]', 'special'); + } else { + str = ctx.stylize('[Getter]', 'special'); + } + } else { + if (desc.set) { + str = ctx.stylize('[Setter]', 'special'); + } + } + if (!hasOwnProperty(visibleKeys, key)) { + name = '[' + key + ']'; + } + if (!str) { + if (ctx.seen.indexOf(desc.value) < 0) { + if (isNull(recurseTimes)) { + str = formatValue(ctx, desc.value, null); + } else { + str = formatValue(ctx, desc.value, recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (array) { + str = str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n').substr(2); + } else { + str = '\n' + str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = ctx.stylize('[Circular]', 'special'); + } + } + if (isUndefined(name)) { + if (array && key.match(/^\d+$/)) { + return str; + } + name = JSON.stringify('' + key); + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.substr(1, name.length - 2); + name = ctx.stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = ctx.stylize(name, 'string'); + } + } + + return name + ': ' + str; +} + + +function reduceToSingleString(output, base, braces) { + var numLinesEst = 0; + var length = output.reduce(function(prev, cur) { + numLinesEst++; + if (cur.indexOf('\n') >= 0) numLinesEst++; + return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; + }, 0); + + if (length > 60) { + return braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + } + + return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; +} + + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. +function isArray(ar) { + return Array.isArray(ar); +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return isObject(re) && objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return isObject(d) && objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return isObject(e) && + (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +exports.isBuffer = _dereq_('./support/isBuffer'); + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + + +function pad(n) { + return n < 10 ? '0' + n.toString(10) : n.toString(10); +} + + +var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', + 'Oct', 'Nov', 'Dec']; + +// 26 Feb 16:19:34 +function timestamp() { + var d = new Date(); + var time = [pad(d.getHours()), + pad(d.getMinutes()), + pad(d.getSeconds())].join(':'); + return [d.getDate(), months[d.getMonth()], time].join(' '); +} + + +// log is just a thin wrapper to console.log that prepends a timestamp +exports.log = function() { + console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); +}; + + +/** + * Inherit the prototype methods from one constructor into another. + * + * The Function.prototype.inherits from lang.js rewritten as a standalone + * function (not on Function.prototype). NOTE: If this file is to be loaded + * during bootstrapping this function needs to be rewritten using some native + * functions as prototype setup using normal JavaScript does not work as + * expected during bootstrapping (see mirror.js in r114903). + * + * @param {function} ctor Constructor function which needs to inherit the + * prototype. + * @param {function} superCtor Constructor function to inherit prototype from. + */ +exports.inherits = _dereq_('inherits'); + +exports._extend = function(origin, add) { + // Don't do anything if add isn't an object + if (!add || !isObject(add)) return origin; + + var keys = Object.keys(add); + var i = keys.length; + while (i--) { + origin[keys[i]] = add[keys[i]]; + } + return origin; +}; + +function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +} + +}).call(this,_dereq_('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./support/isBuffer":38,"_process":24,"inherits":44}],40:[function(_dereq_,module,exports){ + +/** + * This is the web browser implementation of `debug()`. + * + * Expose `debug()` as the module. + */ + +exports = module.exports = _dereq_('./debug'); +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; + +/** + * Colors. + */ + +exports.colors = [ + 'lightseagreen', + 'forestgreen', + 'goldenrod', + 'dodgerblue', + 'darkorchid', + 'crimson' +]; + +/** + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors + */ + +function useColors() { + // is webkit? http://stackoverflow.com/a/16459606/376773 + return ('WebkitAppearance' in document.documentElement.style) || + // is firebug? http://stackoverflow.com/a/398120/376773 + (window.console && (console.firebug || (console.exception && console.table))) || + // is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + (navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31); +} + +/** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ + +exports.formatters.j = function(v) { + return JSON.stringify(v); +}; + + +/** + * Colorize log arguments if enabled. + * + * @api public + */ + +function formatArgs() { + var args = arguments; + var useColors = this.useColors; + + args[0] = (useColors ? '%c' : '') + + this.namespace + + (useColors ? ' %c' : ' ') + + args[0] + + (useColors ? '%c ' : ' ') + + '+' + exports.humanize(this.diff); + + if (!useColors) return args; + + var c = 'color: ' + this.color; + args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1)); + + // the final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + var index = 0; + var lastC = 0; + args[0].replace(/%[a-z%]/g, function(match) { + if ('%' === match) return; + index++; + if ('%c' === match) { + // we only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); + + args.splice(lastC, 0, c); + return args; +} + +/** + * Invokes `console.log()` when available. + * No-op when `console.log` is not a "function". + * + * @api public + */ + +function log() { + // This hackery is required for IE8, + // where the `console.log` function doesn't have 'apply' + return 'object' == typeof console + && 'function' == typeof console.log + && Function.prototype.apply.call(console.log, console, arguments); +} + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ + +function save(namespaces) { + try { + if (null == namespaces) { + localStorage.removeItem('debug'); + } else { + localStorage.debug = namespaces; + } + } catch(e) {} +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + +function load() { + var r; + try { + r = localStorage.debug; + } catch(e) {} + return r; +} + +/** + * Enable namespaces listed in `localStorage.debug` initially. + */ + +exports.enable(load()); + +},{"./debug":41}],41:[function(_dereq_,module,exports){ + +/** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + * + * Expose `debug()` as the module. + */ + +exports = module.exports = debug; +exports.coerce = coerce; +exports.disable = disable; +exports.enable = enable; +exports.enabled = enabled; +exports.humanize = _dereq_('ms'); + +/** + * The currently active debug mode names, and names to skip. + */ + +exports.names = []; +exports.skips = []; + +/** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lowercased letter, i.e. "n". + */ + +exports.formatters = {}; + +/** + * Previously assigned color. + */ + +var prevColor = 0; + +/** + * Previous log timestamp. + */ + +var prevTime; + +/** + * Select a color. + * + * @return {Number} + * @api private + */ + +function selectColor() { + return exports.colors[prevColor++ % exports.colors.length]; +} + +/** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ + +function debug(namespace) { + + // define the `disabled` version + function disabled() { + } + disabled.enabled = false; + + // define the `enabled` version + function enabled() { + + var self = enabled; + + // set `diff` timestamp + var curr = +new Date(); + var ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; + + // add the `color` if not set + if (null == self.useColors) self.useColors = exports.useColors(); + if (null == self.color && self.useColors) self.color = selectColor(); + + var args = Array.prototype.slice.call(arguments); + + args[0] = exports.coerce(args[0]); + + if ('string' !== typeof args[0]) { + // anything else let's inspect with %o + args = ['%o'].concat(args); + } + + // apply any `formatters` transformations + var index = 0; + args[0] = args[0].replace(/%([a-z%])/g, function(match, format) { + // if we encounter an escaped % then don't increase the array index + if (match === '%') return match; + index++; + var formatter = exports.formatters[format]; + if ('function' === typeof formatter) { + var val = args[index]; + match = formatter.call(self, val); + + // now we need to remove `args[index]` since it's inlined in the `format` + args.splice(index, 1); + index--; + } + return match; + }); + + if ('function' === typeof exports.formatArgs) { + args = exports.formatArgs.apply(self, args); + } + var logFn = enabled.log || exports.log || console.log.bind(console); + logFn.apply(self, args); + } + enabled.enabled = true; + + var fn = exports.enabled(namespace) ? enabled : disabled; + + fn.namespace = namespace; + + return fn; +} + +/** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ + +function enable(namespaces) { + exports.save(namespaces); + + var split = (namespaces || '').split(/[\s,]+/); + var len = split.length; + + for (var i = 0; i < len; i++) { + if (!split[i]) continue; // ignore empty strings + namespaces = split[i].replace(/\*/g, '.*?'); + if (namespaces[0] === '-') { + exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); + } else { + exports.names.push(new RegExp('^' + namespaces + '$')); + } + } +} + +/** + * Disable debug output. + * + * @api public + */ + +function disable() { + exports.enable(''); +} + +/** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + +function enabled(name) { + var i, len; + for (i = 0, len = exports.skips.length; i < len; i++) { + if (exports.skips[i].test(name)) { + return false; + } + } + for (i = 0, len = exports.names.length; i < len; i++) { + if (exports.names[i].test(name)) { + return true; + } + } + return false; +} + +/** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + +function coerce(val) { + if (val instanceof Error) return val.stack || val.message; + return val; +} + +},{"ms":42}],42:[function(_dereq_,module,exports){ +/** + * Helpers. + */ + +var s = 1000; +var m = s * 60; +var h = m * 60; +var d = h * 24; +var y = d * 365.25; + +/** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} options + * @return {String|Number} + * @api public + */ + +module.exports = function(val, options){ + options = options || {}; + if ('string' == typeof val) return parse(val); + return options.long + ? long(val) + : short(val); +}; + +/** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function parse(str) { + var match = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str); + if (!match) return; + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'y': + return n * y; + case 'days': + case 'day': + case 'd': + return n * d; + case 'hours': + case 'hour': + case 'h': + return n * h; + case 'minutes': + case 'minute': + case 'm': + return n * m; + case 'seconds': + case 'second': + case 's': + return n * s; + case 'ms': + return n; + } +} + +/** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function short(ms) { + if (ms >= d) return Math.round(ms / d) + 'd'; + if (ms >= h) return Math.round(ms / h) + 'h'; + if (ms >= m) return Math.round(ms / m) + 'm'; + if (ms >= s) return Math.round(ms / s) + 's'; + return ms + 'ms'; +} + +/** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function long(ms) { + return plural(ms, d, 'day') + || plural(ms, h, 'hour') + || plural(ms, m, 'minute') + || plural(ms, s, 'second') + || ms + ' ms'; +} + +/** + * Pluralization helper. + */ + +function plural(ms, n, name) { + if (ms < n) return; + if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name; + return Math.ceil(ms / n) + ' ' + name + 's'; +} + +},{}],43:[function(_dereq_,module,exports){ +/** + * Copyright (c) 2013 Petka Antonov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions:</p> + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +"use strict"; +function Deque(capacity) { + this._capacity = getCapacity(capacity); + this._length = 0; + this._front = 0; + this._makeCapacity(); + if (isArray(capacity)) { + var len = capacity.length; + for (var i = 0; i < len; ++i) { + this[i] = capacity[i]; + } + this._length = len; + } +} + +Deque.prototype.toArray = function Deque$toArray() { + var len = this._length; + var ret = new Array(len); + var front = this._front; + var capacity = this._capacity; + for (var j = 0; j < len; ++j) { + ret[j] = this[(front + j) & (capacity - 1)]; + } + return ret; +}; + +Deque.prototype.push = function Deque$push(item) { + var argsLength = arguments.length; + var length = this._length; + if (argsLength > 1) { + var capacity = this._capacity; + if (length + argsLength > capacity) { + for (var i = 0; i < argsLength; ++i) { + this._checkCapacity(length + 1); + var j = (this._front + length) & (this._capacity - 1); + this[j] = arguments[i]; + length++; + this._length = length; + } + return length; + } + else { + var j = this._front; + for (var i = 0; i < argsLength; ++i) { + this[(j + length) & (capacity - 1)] = arguments[i]; + j++; + } + this._length = length + argsLength; + return length + argsLength; + } + + } + + if (argsLength === 0) return length; + + this._checkCapacity(length + 1); + var i = (this._front + length) & (this._capacity - 1); + this[i] = item; + this._length = length + 1; + return length + 1; +}; + +Deque.prototype.pop = function Deque$pop() { + var length = this._length; + if (length === 0) { + return void 0; + } + var i = (this._front + length - 1) & (this._capacity - 1); + var ret = this[i]; + this[i] = void 0; + this._length = length - 1; + return ret; +}; + +Deque.prototype.shift = function Deque$shift() { + var length = this._length; + if (length === 0) { + return void 0; + } + var front = this._front; + var ret = this[front]; + this[front] = void 0; + this._front = (front + 1) & (this._capacity - 1); + this._length = length - 1; + return ret; +}; + +Deque.prototype.unshift = function Deque$unshift(item) { + var length = this._length; + var argsLength = arguments.length; + + + if (argsLength > 1) { + var capacity = this._capacity; + if (length + argsLength > capacity) { + for (var i = argsLength - 1; i >= 0; i--) { + this._checkCapacity(length + 1); + var capacity = this._capacity; + var j = (((( this._front - 1 ) & + ( capacity - 1) ) ^ capacity ) - capacity ); + this[j] = arguments[i]; + length++; + this._length = length; + this._front = j; + } + return length; + } + else { + var front = this._front; + for (var i = argsLength - 1; i >= 0; i--) { + var j = (((( front - 1 ) & + ( capacity - 1) ) ^ capacity ) - capacity ); + this[j] = arguments[i]; + front = j; + } + this._front = front; + this._length = length + argsLength; + return length + argsLength; + } + } + + if (argsLength === 0) return length; + + this._checkCapacity(length + 1); + var capacity = this._capacity; + var i = (((( this._front - 1 ) & + ( capacity - 1) ) ^ capacity ) - capacity ); + this[i] = item; + this._length = length + 1; + this._front = i; + return length + 1; +}; + +Deque.prototype.peekBack = function Deque$peekBack() { + var length = this._length; + if (length === 0) { + return void 0; + } + var index = (this._front + length - 1) & (this._capacity - 1); + return this[index]; +}; + +Deque.prototype.peekFront = function Deque$peekFront() { + if (this._length === 0) { + return void 0; + } + return this[this._front]; +}; + +Deque.prototype.get = function Deque$get(index) { + var i = index; + if ((i !== (i | 0))) { + return void 0; + } + var len = this._length; + if (i < 0) { + i = i + len; + } + if (i < 0 || i >= len) { + return void 0; + } + return this[(this._front + i) & (this._capacity - 1)]; +}; + +Deque.prototype.isEmpty = function Deque$isEmpty() { + return this._length === 0; +}; + +Deque.prototype.clear = function Deque$clear() { + this._length = 0; + this._front = 0; + this._makeCapacity(); +}; + +Deque.prototype.toString = function Deque$toString() { + return this.toArray().toString(); +}; + +Deque.prototype.valueOf = Deque.prototype.toString; +Deque.prototype.removeFront = Deque.prototype.shift; +Deque.prototype.removeBack = Deque.prototype.pop; +Deque.prototype.insertFront = Deque.prototype.unshift; +Deque.prototype.insertBack = Deque.prototype.push; +Deque.prototype.enqueue = Deque.prototype.push; +Deque.prototype.dequeue = Deque.prototype.shift; +Deque.prototype.toJSON = Deque.prototype.toArray; + +Object.defineProperty(Deque.prototype, "length", { + get: function() { + return this._length; + }, + set: function() { + throw new RangeError(""); + } +}); + +Deque.prototype._makeCapacity = function Deque$_makeCapacity() { + var len = this._capacity; + for (var i = 0; i < len; ++i) { + this[i] = void 0; + } +}; + +Deque.prototype._checkCapacity = function Deque$_checkCapacity(size) { + if (this._capacity < size) { + this._resizeTo(getCapacity(this._capacity * 1.5 + 16)); + } +}; + +Deque.prototype._resizeTo = function Deque$_resizeTo(capacity) { + var oldFront = this._front; + var oldCapacity = this._capacity; + var oldDeque = new Array(oldCapacity); + var length = this._length; + + arrayCopy(this, 0, oldDeque, 0, oldCapacity); + this._capacity = capacity; + this._makeCapacity(); + this._front = 0; + if (oldFront + length <= oldCapacity) { + arrayCopy(oldDeque, oldFront, this, 0, length); + } else { var lengthBeforeWrapping = + length - ((oldFront + length) & (oldCapacity - 1)); + + arrayCopy(oldDeque, oldFront, this, 0, lengthBeforeWrapping); + arrayCopy(oldDeque, 0, this, lengthBeforeWrapping, + length - lengthBeforeWrapping); + } +}; + + +var isArray = Array.isArray; + +function arrayCopy(src, srcIndex, dst, dstIndex, len) { + for (var j = 0; j < len; ++j) { + dst[j + dstIndex] = src[j + srcIndex]; + } +} + +function pow2AtLeast(n) { + n = n >>> 0; + n = n - 1; + n = n | (n >> 1); + n = n | (n >> 2); + n = n | (n >> 4); + n = n | (n >> 8); + n = n | (n >> 16); + return n + 1; +} + +function getCapacity(capacity) { + if (typeof capacity !== "number") { + if (isArray(capacity)) { + capacity = capacity.length; + } + else { + return 16; + } + } + return pow2AtLeast( + Math.min( + Math.max(16, capacity), 1073741824) + ); +} + +module.exports = Deque; + +},{}],44:[function(_dereq_,module,exports){ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +} + +},{}],45:[function(_dereq_,module,exports){ +var util = _dereq_('util') +var AbstractIterator = _dereq_('abstract-leveldown').AbstractIterator +var ltgt = _dereq_('ltgt') + +module.exports = Iterator + +function Iterator (db, options) { + if (!options) options = {} + this.options = options + AbstractIterator.call(this, db) + this._order = options.reverse ? 'DESC': 'ASC' + this._limit = options.limit + this._count = 0 + this._done = false + var lower = ltgt.lowerBound(options) + var upper = ltgt.upperBound(options) + this._keyRange = lower || upper ? this.db.makeKeyRange({ + lower: lower, + upper: upper, + excludeLower: ltgt.lowerBoundExclusive(options), + excludeUpper: ltgt.upperBoundExclusive(options) + }) : null + this.callback = null +} + +util.inherits(Iterator, AbstractIterator) + +Iterator.prototype.createIterator = function() { + var self = this + + self.iterator = self.db.iterate(function () { + self.onItem.apply(self, arguments) + }, { + keyRange: self._keyRange, + autoContinue: false, + order: self._order, + onError: function(err) { console.log('horrible error', err) }, + }) +} + +// TODO the limit implementation here just ignores all reads after limit has been reached +// it should cancel the iterator instead but I don't know how +Iterator.prototype.onItem = function (value, cursor, cursorTransaction) { + if (!cursor && this.callback) { + this.callback() + this.callback = false + return + } + var shouldCall = true + + if (!!this._limit && this._limit > 0 && this._count++ >= this._limit) + shouldCall = false + + if (shouldCall) this.callback(false, cursor.key, cursor.value) + if (cursor) cursor['continue']() +} + +Iterator.prototype._next = function (callback) { + if (!callback) return new Error('next() requires a callback argument') + if (!this._started) { + this.createIterator() + this._started = true + } + this.callback = callback +} + +},{"abstract-leveldown":48,"ltgt":52,"util":39}],46:[function(_dereq_,module,exports){ +(function (process){ +/* Copyright (c) 2013 Rod Vagg, MIT License */ + +function AbstractChainedBatch (db) { + this._db = db + this._operations = [] + this._written = false +} + +AbstractChainedBatch.prototype._checkWritten = function () { + if (this._written) + throw new Error('write() already called on this batch') +} + +AbstractChainedBatch.prototype.put = function (key, value) { + this._checkWritten() + + var err = this._db._checkKeyValue(key, 'key', this._db._isBuffer) + if (err) throw err + err = this._db._checkKeyValue(value, 'value', this._db._isBuffer) + if (err) throw err + + if (!this._db._isBuffer(key)) key = String(key) + if (!this._db._isBuffer(value)) value = String(value) + + if (typeof this._put == 'function' ) + this._put(key, value) + else + this._operations.push({ type: 'put', key: key, value: value }) + + return this +} + +AbstractChainedBatch.prototype.del = function (key) { + this._checkWritten() + + var err = this._db._checkKeyValue(key, 'key', this._db._isBuffer) + if (err) throw err + + if (!this._db._isBuffer(key)) key = String(key) + + if (typeof this._del == 'function' ) + this._del(key) + else + this._operations.push({ type: 'del', key: key }) + + return this +} + +AbstractChainedBatch.prototype.clear = function () { + this._checkWritten() + + this._operations = [] + + if (typeof this._clear == 'function' ) + this._clear() + + return this +} + +AbstractChainedBatch.prototype.write = function (options, callback) { + this._checkWritten() + + if (typeof options == 'function') + callback = options + if (typeof callback != 'function') + throw new Error('write() requires a callback argument') + if (typeof options != 'object') + options = {} + + this._written = true + + if (typeof this._write == 'function' ) + return this._write(callback) + + if (typeof this._db._batch == 'function') + return this._db._batch(this._operations, options, callback) + + process.nextTick(callback) +} + +module.exports = AbstractChainedBatch +}).call(this,_dereq_('_process')) +},{"_process":24}],47:[function(_dereq_,module,exports){ +(function (process){ +/* Copyright (c) 2013 Rod Vagg, MIT License */ + +function AbstractIterator (db) { + this.db = db + this._ended = false + this._nexting = false +} + +AbstractIterator.prototype.next = function (callback) { + var self = this + + if (typeof callback != 'function') + throw new Error('next() requires a callback argument') + + if (self._ended) + return callback(new Error('cannot call next() after end()')) + if (self._nexting) + return callback(new Error('cannot call next() before previous next() has completed')) + + self._nexting = true + if (typeof self._next == 'function') { + return self._next(function () { + self._nexting = false + callback.apply(null, arguments) + }) + } + + process.nextTick(function () { + self._nexting = false + callback() + }) +} + +AbstractIterator.prototype.end = function (callback) { + if (typeof callback != 'function') + throw new Error('end() requires a callback argument') + + if (this._ended) + return callback(new Error('end() already called on iterator')) + + this._ended = true + + if (typeof this._end == 'function') + return this._end(callback) + + process.nextTick(callback) +} + +module.exports = AbstractIterator + +}).call(this,_dereq_('_process')) +},{"_process":24}],48:[function(_dereq_,module,exports){ +(function (process,Buffer){ +/* Copyright (c) 2013 Rod Vagg, MIT License */ + +var xtend = _dereq_('xtend') + , AbstractIterator = _dereq_('./abstract-iterator') + , AbstractChainedBatch = _dereq_('./abstract-chained-batch') + +function AbstractLevelDOWN (location) { + if (!arguments.length || location === undefined) + throw new Error('constructor requires at least a location argument') + + if (typeof location != 'string') + throw new Error('constructor requires a location string argument') + + this.location = location +} + +AbstractLevelDOWN.prototype.open = function (options, callback) { + if (typeof options == 'function') + callback = options + + if (typeof callback != 'function') + throw new Error('open() requires a callback argument') + + if (typeof options != 'object') + options = {} + + if (typeof this._open == 'function') + return this._open(options, callback) + + process.nextTick(callback) +} + +AbstractLevelDOWN.prototype.close = function (callback) { + if (typeof callback != 'function') + throw new Error('close() requires a callback argument') + + if (typeof this._close == 'function') + return this._close(callback) + + process.nextTick(callback) +} + +AbstractLevelDOWN.prototype.get = function (key, options, callback) { + var err + + if (typeof options == 'function') + callback = options + + if (typeof callback != 'function') + throw new Error('get() requires a callback argument') + + if (err = this._checkKeyValue(key, 'key', this._isBuffer)) + return callback(err) + + if (!this._isBuffer(key)) + key = String(key) + + if (typeof options != 'object') + options = {} + + if (typeof this._get == 'function') + return this._get(key, options, callback) + + process.nextTick(function () { callback(new Error('NotFound')) }) +} + +AbstractLevelDOWN.prototype.put = function (key, value, options, callback) { + var err + + if (typeof options == 'function') + callback = options + + if (typeof callback != 'function') + throw new Error('put() requires a callback argument') + + if (err = this._checkKeyValue(key, 'key', this._isBuffer)) + return callback(err) + + if (err = this._checkKeyValue(value, 'value', this._isBuffer)) + return callback(err) + + if (!this._isBuffer(key)) + key = String(key) + + // coerce value to string in node, don't touch it in browser + // (indexeddb can store any JS type) + if (!this._isBuffer(value) && !process.browser) + value = String(value) + + if (typeof options != 'object') + options = {} + + if (typeof this._put == 'function') + return this._put(key, value, options, callback) + + process.nextTick(callback) +} + +AbstractLevelDOWN.prototype.del = function (key, options, callback) { + var err + + if (typeof options == 'function') + callback = options + + if (typeof callback != 'function') + throw new Error('del() requires a callback argument') + + if (err = this._checkKeyValue(key, 'key', this._isBuffer)) + return callback(err) + + if (!this._isBuffer(key)) + key = String(key) + + if (typeof options != 'object') + options = {} + + if (typeof this._del == 'function') + return this._del(key, options, callback) + + process.nextTick(callback) +} + +AbstractLevelDOWN.prototype.batch = function (array, options, callback) { + if (!arguments.length) + return this._chainedBatch() + + if (typeof options == 'function') + callback = options + + if (typeof callback != 'function') + throw new Error('batch(array) requires a callback argument') + + if (!Array.isArray(array)) + return callback(new Error('batch(array) requires an array argument')) + + if (typeof options != 'object') + options = {} + + var i = 0 + , l = array.length + , e + , err + + for (; i < l; i++) { + e = array[i] + if (typeof e != 'object') + continue + + if (err = this._checkKeyValue(e.type, 'type', this._isBuffer)) + return callback(err) + + if (err = this._checkKeyValue(e.key, 'key', this._isBuffer)) + return callback(err) + + if (e.type == 'put') { + if (err = this._checkKeyValue(e.value, 'value', this._isBuffer)) + return callback(err) + } + } + + if (typeof this._batch == 'function') + return this._batch(array, options, callback) + + process.nextTick(callback) +} + +//TODO: remove from here, not a necessary primitive +AbstractLevelDOWN.prototype.approximateSize = function (start, end, callback) { + if ( start == null + || end == null + || typeof start == 'function' + || typeof end == 'function') { + throw new Error('approximateSize() requires valid `start`, `end` and `callback` arguments') + } + + if (typeof callback != 'function') + throw new Error('approximateSize() requires a callback argument') + + if (!this._isBuffer(start)) + start = String(start) + + if (!this._isBuffer(end)) + end = String(end) + + if (typeof this._approximateSize == 'function') + return this._approximateSize(start, end, callback) + + process.nextTick(function () { + callback(null, 0) + }) +} + +AbstractLevelDOWN.prototype._setupIteratorOptions = function (options) { + var self = this + + options = xtend(options) + + ;[ 'start', 'end', 'gt', 'gte', 'lt', 'lte' ].forEach(function (o) { + if (options[o] && self._isBuffer(options[o]) && options[o].length === 0) + delete options[o] + }) + + options.reverse = !!options.reverse + + // fix `start` so it takes into account gt, gte, lt, lte as appropriate + if (options.reverse && options.lt) + options.start = options.lt + if (options.reverse && options.lte) + options.start = options.lte + if (!options.reverse && options.gt) + options.start = options.gt + if (!options.reverse && options.gte) + options.start = options.gte + + if ((options.reverse && options.lt && !options.lte) + || (!options.reverse && options.gt && !options.gte)) + options.exclusiveStart = true // start should *not* include matching key + + return options +} + +AbstractLevelDOWN.prototype.iterator = function (options) { + if (typeof options != 'object') + options = {} + + options = this._setupIteratorOptions(options) + + if (typeof this._iterator == 'function') + return this._iterator(options) + + return new AbstractIterator(this) +} + +AbstractLevelDOWN.prototype._chainedBatch = function () { + return new AbstractChainedBatch(this) +} + +AbstractLevelDOWN.prototype._isBuffer = function (obj) { + return Buffer.isBuffer(obj) +} + +AbstractLevelDOWN.prototype._checkKeyValue = function (obj, type) { + + if (obj === null || obj === undefined) + return new Error(type + ' cannot be `null` or `undefined`') + + if (this._isBuffer(obj)) { + if (obj.length === 0) + return new Error(type + ' cannot be an empty Buffer') + } else if (String(obj) === '') + return new Error(type + ' cannot be an empty String') +} + +module.exports.AbstractLevelDOWN = AbstractLevelDOWN +module.exports.AbstractIterator = AbstractIterator +module.exports.AbstractChainedBatch = AbstractChainedBatch + +}).call(this,_dereq_('_process'),_dereq_("buffer").Buffer) +},{"./abstract-chained-batch":46,"./abstract-iterator":47,"_process":24,"buffer":17,"xtend":49}],49:[function(_dereq_,module,exports){ +module.exports = extend + +function extend() { + var target = {} + + for (var i = 0; i < arguments.length; i++) { + var source = arguments[i] + + for (var key in source) { + if (source.hasOwnProperty(key)) { + target[key] = source[key] + } + } + } + + return target +} + +},{}],50:[function(_dereq_,module,exports){ +/*global window:false, self:false, define:false, module:false */ + +/** + * @license IDBWrapper - A cross-browser wrapper for IndexedDB + * Copyright (c) 2011 - 2013 Jens Arps + * http://jensarps.de/ + * + * Licensed under the MIT (X11) license + */ + +(function (name, definition, global) { + if (typeof define === 'function') { + define(definition); + } else if (typeof module !== 'undefined' && module.exports) { + module.exports = definition(); + } else { + global[name] = definition(); + } +})('IDBStore', function () { + + 'use strict'; + + var defaultErrorHandler = function (error) { + throw error; + }; + + var defaults = { + storeName: 'Store', + storePrefix: 'IDBWrapper-', + dbVersion: 1, + keyPath: 'id', + autoIncrement: true, + onStoreReady: function () { + }, + onError: defaultErrorHandler, + indexes: [] + }; + + /** + * + * The IDBStore constructor + * + * @constructor + * @name IDBStore + * @version 1.4.1 + * + * @param {Object} [kwArgs] An options object used to configure the store and + * set callbacks + * @param {String} [kwArgs.storeName='Store'] The name of the store + * @param {String} [kwArgs.storePrefix='IDBWrapper-'] A prefix that is + * internally used to construct the name of the database, which will be + * kwArgs.storePrefix + kwArgs.storeName + * @param {Number} [kwArgs.dbVersion=1] The version of the store + * @param {String} [kwArgs.keyPath='id'] The key path to use. If you want to + * setup IDBWrapper to work with out-of-line keys, you need to set this to + * `null` + * @param {Boolean} [kwArgs.autoIncrement=true] If set to true, IDBStore will + * automatically make sure a unique keyPath value is present on each object + * that is stored. + * @param {Function} [kwArgs.onStoreReady] A callback to be called when the + * store is ready to be used. + * @param {Function} [kwArgs.onError=throw] A callback to be called when an + * error occurred during instantiation of the store. + * @param {Array} [kwArgs.indexes=[]] An array of indexData objects + * defining the indexes to use with the store. For every index to be used + * one indexData object needs to be passed in the array. + * An indexData object is defined as follows: + * @param {Object} [kwArgs.indexes.indexData] An object defining the index to + * use + * @param {String} kwArgs.indexes.indexData.name The name of the index + * @param {String} [kwArgs.indexes.indexData.keyPath] The key path of the index + * @param {Boolean} [kwArgs.indexes.indexData.unique] Whether the index is unique + * @param {Boolean} [kwArgs.indexes.indexData.multiEntry] Whether the index is multi entry + * @param {Function} [onStoreReady] A callback to be called when the store + * is ready to be used. + * @example + // create a store for customers with an additional index over the + // `lastname` property. + var myCustomerStore = new IDBStore({ + dbVersion: 1, + storeName: 'customer-index', + keyPath: 'customerid', + autoIncrement: true, + onStoreReady: populateTable, + indexes: [ + { name: 'lastname', keyPath: 'lastname', unique: false, multiEntry: false } + ] + }); + * @example + // create a generic store + var myCustomerStore = new IDBStore({ + storeName: 'my-data-store', + onStoreReady: function(){ + // start working with the store. + } + }); + */ + var IDBStore = function (kwArgs, onStoreReady) { + + if (typeof onStoreReady == 'undefined' && typeof kwArgs == 'function') { + onStoreReady = kwArgs; + } + if (Object.prototype.toString.call(kwArgs) != '[object Object]') { + kwArgs = {}; + } + + for (var key in defaults) { + this[key] = typeof kwArgs[key] != 'undefined' ? kwArgs[key] : defaults[key]; + } + + this.dbName = this.storePrefix + this.storeName; + this.dbVersion = parseInt(this.dbVersion, 10) || 1; + + onStoreReady && (this.onStoreReady = onStoreReady); + + var env = typeof window == 'object' ? window : self; + this.idb = env.indexedDB || env.webkitIndexedDB || env.mozIndexedDB; + this.keyRange = env.IDBKeyRange || env.webkitIDBKeyRange || env.mozIDBKeyRange; + + this.features = { + hasAutoIncrement: !env.mozIndexedDB + }; + + this.consts = { + 'READ_ONLY': 'readonly', + 'READ_WRITE': 'readwrite', + 'VERSION_CHANGE': 'versionchange', + 'NEXT': 'next', + 'NEXT_NO_DUPLICATE': 'nextunique', + 'PREV': 'prev', + 'PREV_NO_DUPLICATE': 'prevunique' + }; + + this.openDB(); + }; + + IDBStore.prototype = /** @lends IDBStore */ { + + /** + * A pointer to the IDBStore ctor + * + * @type IDBStore + */ + constructor: IDBStore, + + /** + * The version of IDBStore + * + * @type String + */ + version: '1.4.1', + + /** + * A reference to the IndexedDB object + * + * @type Object + */ + db: null, + + /** + * The full name of the IndexedDB used by IDBStore, composed of + * this.storePrefix + this.storeName + * + * @type String + */ + dbName: null, + + /** + * The version of the IndexedDB used by IDBStore + * + * @type Number + */ + dbVersion: null, + + /** + * A reference to the objectStore used by IDBStore + * + * @type Object + */ + store: null, + + /** + * The store name + * + * @type String + */ + storeName: null, + + /** + * The key path + * + * @type String + */ + keyPath: null, + + /** + * Whether IDBStore uses autoIncrement + * + * @type Boolean + */ + autoIncrement: null, + + /** + * The indexes used by IDBStore + * + * @type Array + */ + indexes: null, + + /** + * A hashmap of features of the used IDB implementation + * + * @type Object + * @proprty {Boolean} autoIncrement If the implementation supports + * native auto increment + */ + features: null, + + /** + * The callback to be called when the store is ready to be used + * + * @type Function + */ + onStoreReady: null, + + /** + * The callback to be called if an error occurred during instantiation + * of the store + * + * @type Function + */ + onError: null, + + /** + * The internal insertID counter + * + * @type Number + * @private + */ + _insertIdCount: 0, + + /** + * Opens an IndexedDB; called by the constructor. + * + * Will check if versions match and compare provided index configuration + * with existing ones, and update indexes if necessary. + * + * Will call this.onStoreReady() if everything went well and the store + * is ready to use, and this.onError() is something went wrong. + * + * @private + * + */ + openDB: function () { + + var openRequest = this.idb.open(this.dbName, this.dbVersion); + var preventSuccessCallback = false; + + openRequest.onerror = function (error) { + + var gotVersionErr = false; + if ('error' in error.target) { + gotVersionErr = error.target.error.name == 'VersionError'; + } else if ('errorCode' in error.target) { + gotVersionErr = error.target.errorCode == 12; + } + + if (gotVersionErr) { + this.onError(new Error('The version number provided is lower than the existing one.')); + } else { + this.onError(error); + } + }.bind(this); + + openRequest.onsuccess = function (event) { + + if (preventSuccessCallback) { + return; + } + + if(this.db){ + this.onStoreReady(); + return; + } + + this.db = event.target.result; + + if(typeof this.db.version == 'string'){ + this.onError(new Error('The IndexedDB implementation in this browser is outdated. Please upgrade your browser.')); + return; + } + + if(!this.db.objectStoreNames.contains(this.storeName)){ + // We should never ever get here. + // Lets notify the user anyway. + this.onError(new Error('Something is wrong with the IndexedDB implementation in this browser. Please upgrade your browser.')); + return; + } + + var emptyTransaction = this.db.transaction([this.storeName], this.consts.READ_ONLY); + this.store = emptyTransaction.objectStore(this.storeName); + + // check indexes + var existingIndexes = Array.prototype.slice.call(this.getIndexList()); + this.indexes.forEach(function(indexData){ + var indexName = indexData.name; + + if(!indexName){ + preventSuccessCallback = true; + this.onError(new Error('Cannot create index: No index name given.')); + return; + } + + this.normalizeIndexData(indexData); + + if(this.hasIndex(indexName)){ + // check if it complies + var actualIndex = this.store.index(indexName); + var complies = this.indexComplies(actualIndex, indexData); + if(!complies){ + preventSuccessCallback = true; + this.onError(new Error('Cannot modify index "' + indexName + '" for current version. Please bump version number to ' + ( this.dbVersion + 1 ) + '.')); + } + + existingIndexes.splice(existingIndexes.indexOf(indexName), 1); + } else { + preventSuccessCallback = true; + this.onError(new Error('Cannot create new index "' + indexName + '" for current version. Please bump version number to ' + ( this.dbVersion + 1 ) + '.')); + } + + }, this); + + if (existingIndexes.length) { + preventSuccessCallback = true; + this.onError(new Error('Cannot delete index(es) "' + existingIndexes.toString() + '" for current version. Please bump version number to ' + ( this.dbVersion + 1 ) + '.')); + } + + preventSuccessCallback || this.onStoreReady(); + }.bind(this); + + openRequest.onupgradeneeded = function(/* IDBVersionChangeEvent */ event){ + + this.db = event.target.result; + + if(this.db.objectStoreNames.contains(this.storeName)){ + this.store = event.target.transaction.objectStore(this.storeName); + } else { + var optionalParameters = { autoIncrement: this.autoIncrement }; + if (this.keyPath !== null) { + optionalParameters.keyPath = this.keyPath; + } + this.store = this.db.createObjectStore(this.storeName, optionalParameters); + } + + var existingIndexes = Array.prototype.slice.call(this.getIndexList()); + this.indexes.forEach(function(indexData){ + var indexName = indexData.name; + + if(!indexName){ + preventSuccessCallback = true; + this.onError(new Error('Cannot create index: No index name given.')); + } + + this.normalizeIndexData(indexData); + + if(this.hasIndex(indexName)){ + // check if it complies + var actualIndex = this.store.index(indexName); + var complies = this.indexComplies(actualIndex, indexData); + if(!complies){ + // index differs, need to delete and re-create + this.store.deleteIndex(indexName); + this.store.createIndex(indexName, indexData.keyPath, { unique: indexData.unique, multiEntry: indexData.multiEntry }); + } + + existingIndexes.splice(existingIndexes.indexOf(indexName), 1); + } else { + this.store.createIndex(indexName, indexData.keyPath, { unique: indexData.unique, multiEntry: indexData.multiEntry }); + } + + }, this); + + if (existingIndexes.length) { + existingIndexes.forEach(function(_indexName){ + this.store.deleteIndex(_indexName); + }, this); + } + + }.bind(this); + }, + + /** + * Deletes the database used for this store if the IDB implementations + * provides that functionality. + */ + deleteDatabase: function () { + if (this.idb.deleteDatabase) { + this.idb.deleteDatabase(this.dbName); + } + }, + + /********************* + * data manipulation * + *********************/ + + /** + * Puts an object into the store. If an entry with the given id exists, + * it will be overwritten. This method has a different signature for inline + * keys and out-of-line keys; please see the examples below. + * + * @param {*} [key] The key to store. This is only needed if IDBWrapper + * is set to use out-of-line keys. For inline keys - the default scenario - + * this can be omitted. + * @param {Object} value The data object to store. + * @param {Function} [onSuccess] A callback that is called if insertion + * was successful. + * @param {Function} [onError] A callback that is called if insertion + * failed. + * @returns {IDBTransaction} The transaction used for this operation. + * @example + // Storing an object, using inline keys (the default scenario): + var myCustomer = { + customerid: 2346223, + lastname: 'Doe', + firstname: 'John' + }; + myCustomerStore.put(myCustomer, mySuccessHandler, myErrorHandler); + // Note that passing success- and error-handlers is optional. + * @example + // Storing an object, using out-of-line keys: + var myCustomer = { + lastname: 'Doe', + firstname: 'John' + }; + myCustomerStore.put(2346223, myCustomer, mySuccessHandler, myErrorHandler); + // Note that passing success- and error-handlers is optional. + */ + put: function (key, value, onSuccess, onError) { + if (this.keyPath !== null) { + onError = onSuccess; + onSuccess = value; + value = key; + } + onError || (onError = defaultErrorHandler); + onSuccess || (onSuccess = noop); + + var hasSuccess = false, + result = null, + putRequest; + + var putTransaction = this.db.transaction([this.storeName], this.consts.READ_WRITE); + putTransaction.oncomplete = function () { + var callback = hasSuccess ? onSuccess : onError; + callback(result); + }; + putTransaction.onabort = onError; + putTransaction.onerror = onError; + + if (this.keyPath !== null) { // in-line keys + this._addIdPropertyIfNeeded(value); + putRequest = putTransaction.objectStore(this.storeName).put(value); + } else { // out-of-line keys + putRequest = putTransaction.objectStore(this.storeName).put(value, key); + } + putRequest.onsuccess = function (event) { + hasSuccess = true; + result = event.target.result; + }; + putRequest.onerror = onError; + + return putTransaction; + }, + + /** + * Retrieves an object from the store. If no entry exists with the given id, + * the success handler will be called with null as first and only argument. + * + * @param {*} key The id of the object to fetch. + * @param {Function} [onSuccess] A callback that is called if fetching + * was successful. Will receive the object as only argument. + * @param {Function} [onError] A callback that will be called if an error + * occurred during the operation. + * @returns {IDBTransaction} The transaction used for this operation. + */ + get: function (key, onSuccess, onError) { + onError || (onError = defaultErrorHandler); + onSuccess || (onSuccess = noop); + + var hasSuccess = false, + result = null; + + var getTransaction = this.db.transaction([this.storeName], this.consts.READ_ONLY); + getTransaction.oncomplete = function () { + var callback = hasSuccess ? onSuccess : onError; + callback(result); + }; + getTransaction.onabort = onError; + getTransaction.onerror = onError; + var getRequest = getTransaction.objectStore(this.storeName).get(key); + getRequest.onsuccess = function (event) { + hasSuccess = true; + result = event.target.result; + }; + getRequest.onerror = onError; + + return getTransaction; + }, + + /** + * Removes an object from the store. + * + * @param {*} key The id of the object to remove. + * @param {Function} [onSuccess] A callback that is called if the removal + * was successful. + * @param {Function} [onError] A callback that will be called if an error + * occurred during the operation. + * @returns {IDBTransaction} The transaction used for this operation. + */ + remove: function (key, onSuccess, onError) { + onError || (onError = defaultErrorHandler); + onSuccess || (onSuccess = noop); + + var hasSuccess = false, + result = null; + + var removeTransaction = this.db.transaction([this.storeName], this.consts.READ_WRITE); + removeTransaction.oncomplete = function () { + var callback = hasSuccess ? onSuccess : onError; + callback(result); + }; + removeTransaction.onabort = onError; + removeTransaction.onerror = onError; + + var deleteRequest = removeTransaction.objectStore(this.storeName)['delete'](key); + deleteRequest.onsuccess = function (event) { + hasSuccess = true; + result = event.target.result; + }; + deleteRequest.onerror = onError; + + return removeTransaction; + }, + + /** + * Runs a batch of put and/or remove operations on the store. + * + * @param {Array} dataArray An array of objects containing the operation to run + * and the data object (for put operations). + * @param {Function} [onSuccess] A callback that is called if all operations + * were successful. + * @param {Function} [onError] A callback that is called if an error + * occurred during one of the operations. + * @returns {IDBTransaction} The transaction used for this operation. + */ + batch: function (dataArray, onSuccess, onError) { + onError || (onError = defaultErrorHandler); + onSuccess || (onSuccess = noop); + + if(Object.prototype.toString.call(dataArray) != '[object Array]'){ + onError(new Error('dataArray argument must be of type Array.')); + } + var batchTransaction = this.db.transaction([this.storeName] , this.consts.READ_WRITE); + batchTransaction.oncomplete = function () { + var callback = hasSuccess ? onSuccess : onError; + callback(hasSuccess); + }; + batchTransaction.onabort = onError; + batchTransaction.onerror = onError; + + var count = dataArray.length; + var called = false; + var hasSuccess = false; + + var onItemSuccess = function () { + count--; + if (count === 0 && !called) { + called = true; + hasSuccess = true; + } + }; + + dataArray.forEach(function (operation) { + var type = operation.type; + var key = operation.key; + var value = operation.value; + + var onItemError = function (err) { + batchTransaction.abort(); + if (!called) { + called = true; + onError(err, type, key); + } + }; + + if (type == 'remove') { + var deleteRequest = batchTransaction.objectStore(this.storeName)['delete'](key); + deleteRequest.onsuccess = onItemSuccess; + deleteRequest.onerror = onItemError; + } else if (type == 'put') { + var putRequest; + if (this.keyPath !== null) { // in-line keys + this._addIdPropertyIfNeeded(value); + putRequest = batchTransaction.objectStore(this.storeName).put(value); + } else { // out-of-line keys + putRequest = batchTransaction.objectStore(this.storeName).put(value, key); + } + putRequest.onsuccess = onItemSuccess; + putRequest.onerror = onItemError; + } + }, this); + + return batchTransaction; + }, + + /** + * Takes an array of objects and stores them in a single transaction. + * + * @param {Array} dataArray An array of objects to store + * @param {Function} [onSuccess] A callback that is called if all operations + * were successful. + * @param {Function} [onError] A callback that is called if an error + * occurred during one of the operations. + * @returns {IDBTransaction} The transaction used for this operation. + */ + putBatch: function (dataArray, onSuccess, onError) { + var batchData = dataArray.map(function(item){ + return { type: 'put', value: item }; + }); + + return this.batch(batchData, onSuccess, onError); + }, + + /** + * Takes an array of keys and removes matching objects in a single + * transaction. + * + * @param {Array} keyArray An array of keys to remove + * @param {Function} [onSuccess] A callback that is called if all operations + * were successful. + * @param {Function} [onError] A callback that is called if an error + * occurred during one of the operations. + * @returns {IDBTransaction} The transaction used for this operation. + */ + removeBatch: function (keyArray, onSuccess, onError) { + var batchData = keyArray.map(function(key){ + return { type: 'remove', key: key }; + }); + + return this.batch(batchData, onSuccess, onError); + }, + + /** + * Takes an array of keys and fetches matching objects + * + * @param {Array} keyArray An array of keys identifying the objects to fetch + * @param {Function} [onSuccess] A callback that is called if all operations + * were successful. + * @param {Function} [onError] A callback that is called if an error + * occurred during one of the operations. + * @param {String} [arrayType='sparse'] The type of array to pass to the + * success handler. May be one of 'sparse', 'dense' or 'skip'. Defaults to + * 'sparse'. This parameter specifies how to handle the situation if a get + * operation did not throw an error, but there was no matching object in + * the database. In most cases, 'sparse' provides the most desired + * behavior. See the examples for details. + * @returns {IDBTransaction} The transaction used for this operation. + * @example + // given that there are two objects in the database with the keypath + // values 1 and 2, and the call looks like this: + myStore.getBatch([1, 5, 2], onError, function (data) { … }, arrayType); + + // this is what the `data` array will be like: + + // arrayType == 'sparse': + // data is a sparse array containing two entries and having a length of 3: + [Object, 2: Object] + 0: Object + 2: Object + length: 3 + __proto__: Array[0] + // calling forEach on data will result in the callback being called two + // times, with the index parameter matching the index of the key in the + // keyArray. + + // arrayType == 'dense': + // data is a dense array containing three entries and having a length of 3, + // where data[1] is of type undefined: + [Object, undefined, Object] + 0: Object + 1: undefined + 2: Object + length: 3 + __proto__: Array[0] + // calling forEach on data will result in the callback being called three + // times, with the index parameter matching the index of the key in the + // keyArray, but the second call will have undefined as first argument. + + // arrayType == 'skip': + // data is a dense array containing two entries and having a length of 2: + [Object, Object] + 0: Object + 1: Object + length: 2 + __proto__: Array[0] + // calling forEach on data will result in the callback being called two + // times, with the index parameter not matching the index of the key in the + // keyArray. + */ + getBatch: function (keyArray, onSuccess, onError, arrayType) { + onError || (onError = defaultErrorHandler); + onSuccess || (onSuccess = noop); + arrayType || (arrayType = 'sparse'); + + if(Object.prototype.toString.call(keyArray) != '[object Array]'){ + onError(new Error('keyArray argument must be of type Array.')); + } + var batchTransaction = this.db.transaction([this.storeName] , this.consts.READ_ONLY); + batchTransaction.oncomplete = function () { + var callback = hasSuccess ? onSuccess : onError; + callback(result); + }; + batchTransaction.onabort = onError; + batchTransaction.onerror = onError; + + var data = []; + var count = keyArray.length; + var called = false; + var hasSuccess = false; + var result = null; + + var onItemSuccess = function (event) { + if (event.target.result || arrayType == 'dense') { + data.push(event.target.result); + } else if (arrayType == 'sparse') { + data.length++; + } + count--; + if (count === 0) { + called = true; + hasSuccess = true; + result = data; + } + }; + + keyArray.forEach(function (key) { + + var onItemError = function (err) { + called = true; + result = err; + onError(err); + batchTransaction.abort(); + }; + + var getRequest = batchTransaction.objectStore(this.storeName).get(key); + getRequest.onsuccess = onItemSuccess; + getRequest.onerror = onItemError; + + }, this); + + return batchTransaction; + }, + + /** + * Fetches all entries in the store. + * + * @param {Function} [onSuccess] A callback that is called if the operation + * was successful. Will receive an array of objects. + * @param {Function} [onError] A callback that will be called if an error + * occurred during the operation. + * @returns {IDBTransaction} The transaction used for this operation. + */ + getAll: function (onSuccess, onError) { + onError || (onError = defaultErrorHandler); + onSuccess || (onSuccess = noop); + var getAllTransaction = this.db.transaction([this.storeName], this.consts.READ_ONLY); + var store = getAllTransaction.objectStore(this.storeName); + if (store.getAll) { + this._getAllNative(getAllTransaction, store, onSuccess, onError); + } else { + this._getAllCursor(getAllTransaction, store, onSuccess, onError); + } + + return getAllTransaction; + }, + + /** + * Implements getAll for IDB implementations that have a non-standard + * getAll() method. + * + * @param {Object} getAllTransaction An open READ transaction. + * @param {Object} store A reference to the store. + * @param {Function} onSuccess A callback that will be called if the + * operation was successful. + * @param {Function} onError A callback that will be called if an + * error occurred during the operation. + * @private + */ + _getAllNative: function (getAllTransaction, store, onSuccess, onError) { + var hasSuccess = false, + result = null; + + getAllTransaction.oncomplete = function () { + var callback = hasSuccess ? onSuccess : onError; + callback(result); + }; + getAllTransaction.onabort = onError; + getAllTransaction.onerror = onError; + + var getAllRequest = store.getAll(); + getAllRequest.onsuccess = function (event) { + hasSuccess = true; + result = event.target.result; + }; + getAllRequest.onerror = onError; + }, + + /** + * Implements getAll for IDB implementations that do not have a getAll() + * method. + * + * @param {Object} getAllTransaction An open READ transaction. + * @param {Object} store A reference to the store. + * @param {Function} onSuccess A callback that will be called if the + * operation was successful. + * @param {Function} onError A callback that will be called if an + * error occurred during the operation. + * @private + */ + _getAllCursor: function (getAllTransaction, store, onSuccess, onError) { + var all = [], + hasSuccess = false, + result = null; + + getAllTransaction.oncomplete = function () { + var callback = hasSuccess ? onSuccess : onError; + callback(result); + }; + getAllTransaction.onabort = onError; + getAllTransaction.onerror = onError; + + var cursorRequest = store.openCursor(); + cursorRequest.onsuccess = function (event) { + var cursor = event.target.result; + if (cursor) { + all.push(cursor.value); + cursor['continue'](); + } + else { + hasSuccess = true; + result = all; + } + }; + cursorRequest.onError = onError; + }, + + /** + * Clears the store, i.e. deletes all entries in the store. + * + * @param {Function} [onSuccess] A callback that will be called if the + * operation was successful. + * @param {Function} [onError] A callback that will be called if an + * error occurred during the operation. + * @returns {IDBTransaction} The transaction used for this operation. + */ + clear: function (onSuccess, onError) { + onError || (onError = defaultErrorHandler); + onSuccess || (onSuccess = noop); + + var hasSuccess = false, + result = null; + + var clearTransaction = this.db.transaction([this.storeName], this.consts.READ_WRITE); + clearTransaction.oncomplete = function () { + var callback = hasSuccess ? onSuccess : onError; + callback(result); + }; + clearTransaction.onabort = onError; + clearTransaction.onerror = onError; + + var clearRequest = clearTransaction.objectStore(this.storeName).clear(); + clearRequest.onsuccess = function (event) { + hasSuccess = true; + result = event.target.result; + }; + clearRequest.onerror = onError; + + return clearTransaction; + }, + + /** + * Checks if an id property needs to present on a object and adds one if + * necessary. + * + * @param {Object} dataObj The data object that is about to be stored + * @private + */ + _addIdPropertyIfNeeded: function (dataObj) { + if (!this.features.hasAutoIncrement && typeof dataObj[this.keyPath] == 'undefined') { + dataObj[this.keyPath] = this._insertIdCount++ + Date.now(); + } + }, + + /************ + * indexing * + ************/ + + /** + * Returns a DOMStringList of index names of the store. + * + * @return {DOMStringList} The list of index names + */ + getIndexList: function () { + return this.store.indexNames; + }, + + /** + * Checks if an index with the given name exists in the store. + * + * @param {String} indexName The name of the index to look for + * @return {Boolean} Whether the store contains an index with the given name + */ + hasIndex: function (indexName) { + return this.store.indexNames.contains(indexName); + }, + + /** + * Normalizes an object containing index data and assures that all + * properties are set. + * + * @param {Object} indexData The index data object to normalize + * @param {String} indexData.name The name of the index + * @param {String} [indexData.keyPath] The key path of the index + * @param {Boolean} [indexData.unique] Whether the index is unique + * @param {Boolean} [indexData.multiEntry] Whether the index is multi entry + */ + normalizeIndexData: function (indexData) { + indexData.keyPath = indexData.keyPath || indexData.name; + indexData.unique = !!indexData.unique; + indexData.multiEntry = !!indexData.multiEntry; + }, + + /** + * Checks if an actual index complies with an expected index. + * + * @param {Object} actual The actual index found in the store + * @param {Object} expected An Object describing an expected index + * @return {Boolean} Whether both index definitions are identical + */ + indexComplies: function (actual, expected) { + var complies = ['keyPath', 'unique', 'multiEntry'].every(function (key) { + // IE10 returns undefined for no multiEntry + if (key == 'multiEntry' && actual[key] === undefined && expected[key] === false) { + return true; + } + // Compound keys + if (key == 'keyPath' && Object.prototype.toString.call(expected[key]) == '[object Array]') { + var exp = expected.keyPath; + var act = actual.keyPath; + + // IE10 can't handle keyPath sequences and stores them as a string. + // The index will be unusable there, but let's still return true if + // the keyPath sequence matches. + if (typeof act == 'string') { + return exp.toString() == act; + } + + // Chrome/Opera stores keyPath squences as DOMStringList, Firefox + // as Array + if ( ! (typeof act.contains == 'function' || typeof act.indexOf == 'function') ) { + return false; + } + + if (act.length !== exp.length) { + return false; + } + + for (var i = 0, m = exp.length; i<m; i++) { + if ( ! ( (act.contains && act.contains(exp[i])) || act.indexOf(exp[i] !== -1) )) { + return false; + } + } + return true; + } + return expected[key] == actual[key]; + }); + return complies; + }, + + /********** + * cursor * + **********/ + + /** + * Iterates over the store using the given options and calling onItem + * for each entry matching the options. + * + * @param {Function} onItem A callback to be called for each match + * @param {Object} [options] An object defining specific options + * @param {Object} [options.index=null] An IDBIndex to operate on + * @param {String} [options.order=ASC] The order in which to provide the + * results, can be 'DESC' or 'ASC' + * @param {Boolean} [options.autoContinue=true] Whether to automatically + * iterate the cursor to the next result + * @param {Boolean} [options.filterDuplicates=false] Whether to exclude + * duplicate matches + * @param {Object} [options.keyRange=null] An IDBKeyRange to use + * @param {Boolean} [options.writeAccess=false] Whether grant write access + * to the store in the onItem callback + * @param {Function} [options.onEnd=null] A callback to be called after + * iteration has ended + * @param {Function} [options.onError=throw] A callback to be called + * if an error occurred during the operation. + * @returns {IDBTransaction} The transaction used for this operation. + */ + iterate: function (onItem, options) { + options = mixin({ + index: null, + order: 'ASC', + autoContinue: true, + filterDuplicates: false, + keyRange: null, + writeAccess: false, + onEnd: null, + onError: defaultErrorHandler + }, options || {}); + + var directionType = options.order.toLowerCase() == 'desc' ? 'PREV' : 'NEXT'; + if (options.filterDuplicates) { + directionType += '_NO_DUPLICATE'; + } + + var hasSuccess = false; + var cursorTransaction = this.db.transaction([this.storeName], this.consts[options.writeAccess ? 'READ_WRITE' : 'READ_ONLY']); + var cursorTarget = cursorTransaction.objectStore(this.storeName); + if (options.index) { + cursorTarget = cursorTarget.index(options.index); + } + + cursorTransaction.oncomplete = function () { + if (!hasSuccess) { + options.onError(null); + return; + } + if (options.onEnd) { + options.onEnd(); + } else { + onItem(null); + } + }; + cursorTransaction.onabort = options.onError; + cursorTransaction.onerror = options.onError; + + var cursorRequest = cursorTarget.openCursor(options.keyRange, this.consts[directionType]); + cursorRequest.onerror = options.onError; + cursorRequest.onsuccess = function (event) { + var cursor = event.target.result; + if (cursor) { + onItem(cursor.value, cursor, cursorTransaction); + if (options.autoContinue) { + cursor['continue'](); + } + } else { + hasSuccess = true; + } + }; + + return cursorTransaction; + }, + + /** + * Runs a query against the store and passes an array containing matched + * objects to the success handler. + * + * @param {Function} onSuccess A callback to be called when the operation + * was successful. + * @param {Object} [options] An object defining specific query options + * @param {Object} [options.index=null] An IDBIndex to operate on + * @param {String} [options.order=ASC] The order in which to provide the + * results, can be 'DESC' or 'ASC' + * @param {Boolean} [options.filterDuplicates=false] Whether to exclude + * duplicate matches + * @param {Object} [options.keyRange=null] An IDBKeyRange to use + * @param {Function} [options.onError=throw] A callback to be called if an error + * occurred during the operation. + * @returns {IDBTransaction} The transaction used for this operation. + */ + query: function (onSuccess, options) { + var result = []; + options = options || {}; + options.onEnd = function () { + onSuccess(result); + }; + return this.iterate(function (item) { + result.push(item); + }, options); + }, + + /** + * + * Runs a query against the store, but only returns the number of matches + * instead of the matches itself. + * + * @param {Function} onSuccess A callback to be called if the opration + * was successful. + * @param {Object} [options] An object defining specific options + * @param {Object} [options.index=null] An IDBIndex to operate on + * @param {Object} [options.keyRange=null] An IDBKeyRange to use + * @param {Function} [options.onError=throw] A callback to be called if an error + * occurred during the operation. + * @returns {IDBTransaction} The transaction used for this operation. + */ + count: function (onSuccess, options) { + + options = mixin({ + index: null, + keyRange: null + }, options || {}); + + var onError = options.onError || defaultErrorHandler; + + var hasSuccess = false, + result = null; + + var cursorTransaction = this.db.transaction([this.storeName], this.consts.READ_ONLY); + cursorTransaction.oncomplete = function () { + var callback = hasSuccess ? onSuccess : onError; + callback(result); + }; + cursorTransaction.onabort = onError; + cursorTransaction.onerror = onError; + + var cursorTarget = cursorTransaction.objectStore(this.storeName); + if (options.index) { + cursorTarget = cursorTarget.index(options.index); + } + var countRequest = cursorTarget.count(options.keyRange); + countRequest.onsuccess = function (evt) { + hasSuccess = true; + result = evt.target.result; + }; + countRequest.onError = onError; + + return cursorTransaction; + }, + + /**************/ + /* key ranges */ + /**************/ + + /** + * Creates a key range using specified options. This key range can be + * handed over to the count() and iterate() methods. + * + * Note: You must provide at least one or both of "lower" or "upper" value. + * + * @param {Object} options The options for the key range to create + * @param {*} [options.lower] The lower bound + * @param {Boolean} [options.excludeLower] Whether to exclude the lower + * bound passed in options.lower from the key range + * @param {*} [options.upper] The upper bound + * @param {Boolean} [options.excludeUpper] Whether to exclude the upper + * bound passed in options.upper from the key range + * @param {*} [options.only] A single key value. Use this if you need a key + * range that only includes one value for a key. Providing this + * property invalidates all other properties. + * @return {Object} The IDBKeyRange representing the specified options + */ + makeKeyRange: function(options){ + /*jshint onecase:true */ + var keyRange, + hasLower = typeof options.lower != 'undefined', + hasUpper = typeof options.upper != 'undefined', + isOnly = typeof options.only != 'undefined'; + + switch(true){ + case isOnly: + keyRange = this.keyRange.only(options.only); + break; + case hasLower && hasUpper: + keyRange = this.keyRange.bound(options.lower, options.upper, options.excludeLower, options.excludeUpper); + break; + case hasLower: + keyRange = this.keyRange.lowerBound(options.lower, options.excludeLower); + break; + case hasUpper: + keyRange = this.keyRange.upperBound(options.upper, options.excludeUpper); + break; + default: + throw new Error('Cannot create KeyRange. Provide one or both of "lower" or "upper" value, or an "only" value.'); + } + + return keyRange; + + } + + }; + + /** helpers **/ + + var noop = function () { + }; + var empty = {}; + var mixin = function (target, source) { + var name, s; + for (name in source) { + s = source[name]; + if (s !== empty[name] && s !== target[name]) { + target[name] = s; + } + } + return target; + }; + + IDBStore.version = IDBStore.prototype.version; + + return IDBStore; + +}, this); + +},{}],51:[function(_dereq_,module,exports){ +var Buffer = _dereq_('buffer').Buffer; + +module.exports = isBuffer; + +function isBuffer (o) { + return Buffer.isBuffer(o) + || /\[object (.+Array|Array.+)\]/.test(Object.prototype.toString.call(o)); +} + +},{"buffer":17}],52:[function(_dereq_,module,exports){ +(function (Buffer){ + +exports.compare = function (a, b) { + + if(Buffer.isBuffer(a)) { + var l = Math.min(a.length, b.length) + for(var i = 0; i < l; i++) { + var cmp = a[i] - b[i] + if(cmp) return cmp + } + return a.length - b.length + } + + return a < b ? -1 : a > b ? 1 : 0 +} + +function has(obj, key) { + return Object.hasOwnProperty.call(obj, key) +} + +// to be compatible with the current abstract-leveldown tests +// nullish or empty strings. +// I could use !!val but I want to permit numbers and booleans, +// if possible. + +function isDef (val) { + return val !== undefined && val !== '' +} + +function has (range, name) { + return Object.hasOwnProperty.call(range, name) +} + +function hasKey(range, name) { + return Object.hasOwnProperty.call(range, name) && name +} + +var lowerBoundKey = exports.lowerBoundKey = function (range) { + return ( + hasKey(range, 'gt') + || hasKey(range, 'gte') + || hasKey(range, 'min') + || (range.reverse ? hasKey(range, 'end') : hasKey(range, 'start')) + || undefined + ) +} + +var lowerBound = exports.lowerBound = function (range) { + var k = lowerBoundKey(range) + return k && range[k] + return ( + has(range, 'gt') ? range.gt + : has(range, 'gte') ? range.gte + : has(range, 'min') ? range.min + : has(range, 'start') && !range.reverse ? range.start + : has(range, 'end') && range.reverse ? range.end + : undefined + ) +} + +exports.lowerBoundInclusive = function (range) { + return has(range, 'gt') ? false : true +} + +exports.upperBoundInclusive = + function (range) { + return has(range, 'lt') || !range.minEx ? false : true + } + +var lowerBoundExclusive = exports.lowerBoundExclusive = + function (range) { + return has(range, 'gt') || range.minEx ? true : false + } + +var upperBoundExclusive = exports.upperBoundExclusive = + function (range) { + return has(range, 'lt') ? true : false + } + +var upperBoundKey = exports.upperBoundKey = function (range) { + return ( + hasKey(range, 'lt') + || hasKey(range, 'lte') + || hasKey(range, 'max') + || (range.reverse ? hasKey(range, 'start') : hasKey(range, 'end')) + || undefined + ) +} + +var upperBound = exports.upperBound = function (range) { + var k = upperBoundKey(range) + return k && range[k] +} + +function id (e) { return e } + +exports.toLtgt = function (range, _range, map, lower, upper) { + _range = _range || {} + map = map || id + var defaults = arguments.length > 3 + var lb = exports.lowerBoundKey(range) + var ub = exports.upperBoundKey(range) + if(lb) { + if(lb === 'gt') _range.gt = map(range.gt) + else _range.gte = map(range[lb]) + } + else if(defaults) + _range.gte = lower + + if(ub) { + if(ub === 'lt') _range.lt = map(range.lt) + else _range.lte = map(range[ub]) + } + else if(defaults) + _range.lte = upper + + _range.reverse = !!range.reverse + + return _range +} + +exports.contains = function (range, key, compare) { + compare = compare || exports.compare + + var lb = lowerBound(range) + if(isDef(lb)) { + var cmp = compare(key, lb) + if(cmp < 0 || (cmp === 0 && lowerBoundExclusive(range))) + return false + } + + var ub = upperBound(range) + if(isDef(ub)) { + var cmp = compare(key, ub) + if(cmp > 0 || (cmp === 0) && upperBoundExclusive(range)) + return false + } + + return true +} + +exports.filter = function (range, compare) { + return function (key) { + return exports.contains(range, key, compare) + } +} + +}).call(this,_dereq_("buffer").Buffer) +},{"buffer":17}],53:[function(_dereq_,module,exports){ +(function (Buffer){ +/** + * Convert a typed array to a Buffer without a copy + * + * Author: Feross Aboukhadijeh <feross@feross.org> <http://feross.org> + * License: MIT + * + * `npm install typedarray-to-buffer` + */ + +module.exports = function (arr) { + if (typeof Buffer._augment === 'function' && Buffer.TYPED_ARRAY_SUPPORT) { + // If `Buffer` is from the `buffer` module and this browser supports typed arrays, + // then augment it with all the `Buffer` methods. + return Buffer._augment(arr) + } else { + // Otherwise, fallback to creating a `Buffer` with a copy. + return new Buffer(arr) + } +} + +}).call(this,_dereq_("buffer").Buffer) +},{"buffer":17}],54:[function(_dereq_,module,exports){ +module.exports = hasKeys + +function hasKeys(source) { + return source !== null && + (typeof source === "object" || + typeof source === "function") +} + +},{}],55:[function(_dereq_,module,exports){ +var Keys = _dereq_("object-keys") +var hasKeys = _dereq_("./has-keys") + +module.exports = extend + +function extend() { + var target = {} + + for (var i = 0; i < arguments.length; i++) { + var source = arguments[i] + + if (!hasKeys(source)) { + continue + } + + var keys = Keys(source) + + for (var j = 0; j < keys.length; j++) { + var name = keys[j] + target[name] = source[name] + } + } + + return target +} + +},{"./has-keys":54,"object-keys":57}],56:[function(_dereq_,module,exports){ +var hasOwn = Object.prototype.hasOwnProperty; +var toString = Object.prototype.toString; + +var isFunction = function (fn) { + var isFunc = (typeof fn === 'function' && !(fn instanceof RegExp)) || toString.call(fn) === '[object Function]'; + if (!isFunc && typeof window !== 'undefined') { + isFunc = fn === window.setTimeout || fn === window.alert || fn === window.confirm || fn === window.prompt; + } + return isFunc; +}; + +module.exports = function forEach(obj, fn) { + if (!isFunction(fn)) { + throw new TypeError('iterator must be a function'); + } + var i, k, + isString = typeof obj === 'string', + l = obj.length, + context = arguments.length > 2 ? arguments[2] : null; + if (l === +l) { + for (i = 0; i < l; i++) { + if (context === null) { + fn(isString ? obj.charAt(i) : obj[i], i, obj); + } else { + fn.call(context, isString ? obj.charAt(i) : obj[i], i, obj); + } + } + } else { + for (k in obj) { + if (hasOwn.call(obj, k)) { + if (context === null) { + fn(obj[k], k, obj); + } else { + fn.call(context, obj[k], k, obj); + } + } + } + } +}; + + +},{}],57:[function(_dereq_,module,exports){ +module.exports = Object.keys || _dereq_('./shim'); + + +},{"./shim":59}],58:[function(_dereq_,module,exports){ +var toString = Object.prototype.toString; + +module.exports = function isArguments(value) { + var str = toString.call(value); + var isArguments = str === '[object Arguments]'; + if (!isArguments) { + isArguments = str !== '[object Array]' + && value !== null + && typeof value === 'object' + && typeof value.length === 'number' + && value.length >= 0 + && toString.call(value.callee) === '[object Function]'; + } + return isArguments; +}; + + +},{}],59:[function(_dereq_,module,exports){ +(function () { + "use strict"; + + // modified from https://github.com/kriskowal/es5-shim + var has = Object.prototype.hasOwnProperty, + toString = Object.prototype.toString, + forEach = _dereq_('./foreach'), + isArgs = _dereq_('./isArguments'), + hasDontEnumBug = !({'toString': null}).propertyIsEnumerable('toString'), + hasProtoEnumBug = (function () {}).propertyIsEnumerable('prototype'), + dontEnums = [ + "toString", + "toLocaleString", + "valueOf", + "hasOwnProperty", + "isPrototypeOf", + "propertyIsEnumerable", + "constructor" + ], + keysShim; + + keysShim = function keys(object) { + var isObject = object !== null && typeof object === 'object', + isFunction = toString.call(object) === '[object Function]', + isArguments = isArgs(object), + theKeys = []; + + if (!isObject && !isFunction && !isArguments) { + throw new TypeError("Object.keys called on a non-object"); + } + + if (isArguments) { + forEach(object, function (value) { + theKeys.push(value); + }); + } else { + var name, + skipProto = hasProtoEnumBug && isFunction; + + for (name in object) { + if (!(skipProto && name === 'prototype') && has.call(object, name)) { + theKeys.push(name); + } + } + } + + if (hasDontEnumBug) { + var ctor = object.constructor, + skipConstructor = ctor && ctor.prototype === object; + + forEach(dontEnums, function (dontEnum) { + if (!(skipConstructor && dontEnum === 'constructor') && has.call(object, dontEnum)) { + theKeys.push(dontEnum); + } + }); + } + return theKeys; + }; + + module.exports = keysShim; +}()); + + +},{"./foreach":56,"./isArguments":58}],60:[function(_dereq_,module,exports){ +function addOperation (type, key, value, options) { + var operation = { + type: type, + key: key, + value: value, + options: options + } + + if (options && options.prefix) { + operation.prefix = options.prefix + delete options.prefix + } + + this._operations.push(operation) + + return this +} + +function Batch(sdb) { + this._operations = [] + this._sdb = sdb + + this.put = addOperation.bind(this, 'put') + this.del = addOperation.bind(this, 'del') +} + +var B = Batch.prototype + + +B.clear = function () { + this._operations = [] +} + +B.write = function (cb) { + this._sdb.batch(this._operations, cb) +} + +module.exports = Batch + +},{}],61:[function(_dereq_,module,exports){ +(function (process){ +var EventEmitter = _dereq_('events').EventEmitter +var next = process.nextTick +var SubDb = _dereq_('./sub') +var Batch = _dereq_('./batch') +var fixRange = _dereq_('level-fix-range') + +var Hooks = _dereq_('level-hooks') + +module.exports = function (_db, options) { + function DB () {} + DB.prototype = _db + var db = new DB() + + if (db.sublevel) return db + + options = options || {} + + //use \xff (255) as the seperator, + //so that sections of the database will sort after the regular keys + var sep = options.sep = options.sep || '\xff' + db._options = options + + Hooks(db) + + db.sublevels = {} + + db.sublevel = function (prefix, options) { + if(db.sublevels[prefix]) + return db.sublevels[prefix] + return new SubDb(db, prefix, options || this._options) + } + + db.methods = {} + + db.prefix = function (key) { + return '' + (key || '') + } + + db.pre = function (range, hook) { + if(!hook) + hook = range, range = { + max : sep + } + return db.hooks.pre(range, hook) + } + + db.post = function (range, hook) { + if(!hook) + hook = range, range = { + max : sep + } + return db.hooks.post(range, hook) + } + + function safeRange(fun) { + return function (opts) { + opts = opts || {} + opts = fixRange(opts) + + if(opts.reverse) opts.start = opts.start || sep + else opts.end = opts.end || sep + + return fun.call(db, opts) + } + } + + db.readStream = + db.createReadStream = safeRange(db.createReadStream) + db.keyStream = + db.createKeyStream = safeRange(db.createKeyStream) + db.valuesStream = + db.createValueStream = safeRange(db.createValueStream) + + var batch = db.batch + db.batch = function (changes, opts, cb) { + if(!Array.isArray(changes)) + return new Batch(db) + changes.forEach(function (e) { + if(e.prefix) { + if('function' === typeof e.prefix.prefix) + e.key = e.prefix.prefix(e.key) + else if('string' === typeof e.prefix) + e.key = e.prefix + e.key + } + }) + batch.call(db, changes, opts, cb) + } + return db +} + + +}).call(this,_dereq_('_process')) +},{"./batch":60,"./sub":72,"_process":24,"events":21,"level-fix-range":62,"level-hooks":64}],62:[function(_dereq_,module,exports){ +var clone = _dereq_('clone') + +module.exports = +function fixRange(opts) { + opts = clone(opts) + + var reverse = opts.reverse + var end = opts.max || opts.end + var start = opts.min || opts.start + + var range = [start, end] + if(start != null && end != null) + range.sort() + if(reverse) + range = range.reverse() + + opts.start = range[0] + opts.end = range[1] + + delete opts.min + delete opts.max + + return opts +} + +},{"clone":63}],63:[function(_dereq_,module,exports){ +(function (Buffer){ +'use strict'; + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + +// shim for Node's 'util' package +// DO NOT REMOVE THIS! It is required for compatibility with EnderJS (http://enderjs.com/). +var util = { + isArray: function (ar) { + return Array.isArray(ar) || (typeof ar === 'object' && objectToString(ar) === '[object Array]'); + }, + isDate: function (d) { + return typeof d === 'object' && objectToString(d) === '[object Date]'; + }, + isRegExp: function (re) { + return typeof re === 'object' && objectToString(re) === '[object RegExp]'; + }, + getRegExpFlags: function (re) { + var flags = ''; + re.global && (flags += 'g'); + re.ignoreCase && (flags += 'i'); + re.multiline && (flags += 'm'); + return flags; + } +}; + + +if (typeof module === 'object') + module.exports = clone; + +/** + * Clones (copies) an Object using deep copying. + * + * This function supports circular references by default, but if you are certain + * there are no circular references in your object, you can save some CPU time + * by calling clone(obj, false). + * + * Caution: if `circular` is false and `parent` contains circular references, + * your program may enter an infinite loop and crash. + * + * @param `parent` - the object to be cloned + * @param `circular` - set to true if the object to be cloned may contain + * circular references. (optional - true by default) + * @param `depth` - set to a number if the object is only to be cloned to + * a particular depth. (optional - defaults to Infinity) + * @param `prototype` - sets the prototype to be used when cloning an object. + * (optional - defaults to parent prototype). +*/ + +function clone(parent, circular, depth, prototype) { + // maintain two arrays for circular references, where corresponding parents + // and children have the same index + var allParents = []; + var allChildren = []; + + var useBuffer = typeof Buffer != 'undefined'; + + if (typeof circular == 'undefined') + circular = true; + + if (typeof depth == 'undefined') + depth = Infinity; + + // recurse this function so we don't reset allParents and allChildren + function _clone(parent, depth) { + // cloning null always returns null + if (parent === null) + return null; + + if (depth == 0) + return parent; + + var child; + var proto; + if (typeof parent != 'object') { + return parent; + } + + if (util.isArray(parent)) { + child = []; + } else if (util.isRegExp(parent)) { + child = new RegExp(parent.source, util.getRegExpFlags(parent)); + if (parent.lastIndex) child.lastIndex = parent.lastIndex; + } else if (util.isDate(parent)) { + child = new Date(parent.getTime()); + } else if (useBuffer && Buffer.isBuffer(parent)) { + child = new Buffer(parent.length); + parent.copy(child); + return child; + } else { + if (typeof prototype == 'undefined') { + proto = Object.getPrototypeOf(parent); + child = Object.create(proto); + } + else { + child = Object.create(prototype); + proto = prototype; + } + } + + if (circular) { + var index = allParents.indexOf(parent); + + if (index != -1) { + return allChildren[index]; + } + allParents.push(parent); + allChildren.push(child); + } + + for (var i in parent) { + var attrs; + if (proto) { + attrs = Object.getOwnPropertyDescriptor(proto, i); + } + + if (attrs && attrs.set == null) { + continue; + } + child[i] = _clone(parent[i], depth - 1); + } + + return child; + } + + return _clone(parent, depth); +} + +/** + * Simple flat clone using prototype, accepts only objects, usefull for property + * override on FLAT configuration object (no nested props). + * + * USE WITH CAUTION! This may not behave as you wish if you do not know how this + * works. + */ +clone.clonePrototype = function(parent) { + if (parent === null) + return null; + + var c = function () {}; + c.prototype = parent; + return new c(); +}; + +}).call(this,_dereq_("buffer").Buffer) +},{"buffer":17}],64:[function(_dereq_,module,exports){ +var ranges = _dereq_('string-range') + +module.exports = function (db) { + + if(db.hooks) { + return + } + + var posthooks = [] + var prehooks = [] + + function getPrefix (p) { + return p && ( + 'string' === typeof p ? p + : 'string' === typeof p.prefix ? p.prefix + : 'function' === typeof p.prefix ? p.prefix() + : '' + ) + } + + function getKeyEncoding (db) { + if(db && db._getKeyEncoding) + return db._getKeyEncoding(db) + } + + function getValueEncoding (db) { + if(db && db._getValueEncoding) + return db._getValueEncoding(db) + } + + function remover (array, item) { + return function () { + var i = array.indexOf(item) + if(!~i) return false + array.splice(i, 1) + return true + } + } + + db.hooks = { + post: function (prefix, hook) { + if(!hook) hook = prefix, prefix = '' + var h = {test: ranges.checker(prefix), hook: hook} + posthooks.push(h) + return remover(posthooks, h) + }, + pre: function (prefix, hook) { + if(!hook) hook = prefix, prefix = '' + var h = { + test: ranges.checker(prefix), + hook: hook, + safe: false !== prefix.safe + } + prehooks.push(h) + return remover(prehooks, h) + }, + posthooks: posthooks, + prehooks: prehooks + } + + //POST HOOKS + + function each (e) { + if(e && e.type) { + posthooks.forEach(function (h) { + if(h.test(e.key)) h.hook(e) + }) + } + } + + db.on('put', function (key, val) { + each({type: 'put', key: key, value: val}) + }) + db.on('del', function (key, val) { + each({type: 'del', key: key, value: val}) + }) + db.on('batch', function onBatch (ary) { + ary.forEach(each) + }) + + //PRE HOOKS + + var put = db.put + var del = db.del + var batch = db.batch + + function callHooks (isBatch, b, opts, cb) { + try { + b.forEach(function hook(e, i) { + prehooks.forEach(function (h) { + if(h.test(String(e.key))) { + //optimize this? + //maybe faster to not create a new object each time? + //have one object and expose scope to it? + var context = { + add: function (ch, db) { + if(typeof ch === 'undefined') { + return this + } + if(ch === false) + return delete b[i] + var prefix = ( + getPrefix(ch.prefix) || + getPrefix(db) || + h.prefix || '' + ) + //don't leave a circular json object there incase using multilevel. + if(prefix) ch.prefix = prefix + ch.key = prefix + ch.key + if(h.safe && h.test(String(ch.key))) { + //this usually means a stack overflow. + throw new Error('prehook cannot insert into own range') + } + var ke = ch.keyEncoding || getKeyEncoding(ch.prefix) + var ve = ch.valueEncoding || getValueEncoding(ch.prefix) + if(ke) ch.keyEncoding = ke + if(ve) ch.valueEncoding = ve + + b.push(ch) + hook(ch, b.length - 1) + return this + }, + put: function (ch, db) { + if('object' === typeof ch) ch.type = 'put' + return this.add(ch, db) + }, + del: function (ch, db) { + if('object' === typeof ch) ch.type = 'del' + return this.add(ch, db) + }, + veto: function () { + return this.add(false) + } + } + h.hook.call(context, e, context.add, b) + } + }) + }) + } catch (err) { + return (cb || opts)(err) + } + b = b.filter(function (e) { + return e && e.type //filter out empty items + }) + + if(b.length == 1 && !isBatch) { + var change = b[0] + return change.type == 'put' + ? put.call(db, change.key, change.value, opts, cb) + : del.call(db, change.key, opts, cb) + } + return batch.call(db, b, opts, cb) + } + + db.put = function (key, value, opts, cb ) { + var batch = [{key: key, value: value, type: 'put'}] + return callHooks(false, batch, opts, cb) + } + + db.del = function (key, opts, cb) { + var batch = [{key: key, type: 'del'}] + return callHooks(false, batch, opts, cb) + } + + db.batch = function (batch, opts, cb) { + return callHooks(true, batch, opts, cb) + } +} + +},{"string-range":65}],65:[function(_dereq_,module,exports){ + +//force to a valid range +var range = exports.range = function (obj) { + return null == obj ? {} : 'string' === typeof range ? { + min: range, max: range + '\xff' + } : obj +} + +//turn into a sub range. +var prefix = exports.prefix = function (range, within, term) { + range = exports.range(range) + var _range = {} + term = term || '\xff' + if(range instanceof RegExp || 'function' == typeof range) { + _range.min = within + _range.max = within + term, + _range.inner = function (k) { + var j = k.substring(within.length) + if(range.test) + return range.test(j) + return range(j) + } + } + else if('object' === typeof range) { + _range.min = within + (range.min || range.start || '') + _range.max = within + (range.max || range.end || (term || '~')) + _range.reverse = !!range.reverse + } + return _range +} + +//return a function that checks a range +var checker = exports.checker = function (range) { + if(!range) range = {} + + if ('string' === typeof range) + return function (key) { + return key.indexOf(range) == 0 + } + else if(range instanceof RegExp) + return function (key) { + return range.test(key) + } + else if('object' === typeof range) + return function (key) { + var min = range.min || range.start + var max = range.max || range.end + + // fixes keys passed as ints from sublevels + key = String(key) + + return ( + !min || key >= min + ) && ( + !max || key <= max + ) && ( + !range.inner || ( + range.inner.test + ? range.inner.test(key) + : range.inner(key) + ) + ) + } + else if('function' === typeof range) + return range +} +//check if a key is within a range. +var satifies = exports.satisfies = function (key, range) { + return checker(range)(key) +} + + + +},{}],66:[function(_dereq_,module,exports){ +module.exports=_dereq_(54) +},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/has-keys.js":54}],67:[function(_dereq_,module,exports){ +arguments[4][55][0].apply(exports,arguments) +},{"./has-keys":66,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/index.js":55,"object-keys":68}],68:[function(_dereq_,module,exports){ +arguments[4][57][0].apply(exports,arguments) +},{"./shim":71,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/index.js":57}],69:[function(_dereq_,module,exports){ + +var hasOwn = Object.prototype.hasOwnProperty; +var toString = Object.prototype.toString; + +module.exports = function forEach (obj, fn, ctx) { + if (toString.call(fn) !== '[object Function]') { + throw new TypeError('iterator must be a function'); + } + var l = obj.length; + if (l === +l) { + for (var i = 0; i < l; i++) { + fn.call(ctx, obj[i], i, obj); + } + } else { + for (var k in obj) { + if (hasOwn.call(obj, k)) { + fn.call(ctx, obj[k], k, obj); + } + } + } +}; + + +},{}],70:[function(_dereq_,module,exports){ + +/**! + * is + * the definitive JavaScript type testing library + * + * @copyright 2013 Enrico Marino + * @license MIT + */ + +var objProto = Object.prototype; +var owns = objProto.hasOwnProperty; +var toString = objProto.toString; +var isActualNaN = function (value) { + return value !== value; +}; +var NON_HOST_TYPES = { + "boolean": 1, + "number": 1, + "string": 1, + "undefined": 1 +}; + +/** + * Expose `is` + */ + +var is = module.exports = {}; + +/** + * Test general. + */ + +/** + * is.type + * Test if `value` is a type of `type`. + * + * @param {Mixed} value value to test + * @param {String} type type + * @return {Boolean} true if `value` is a type of `type`, false otherwise + * @api public + */ + +is.a = +is.type = function (value, type) { + return typeof value === type; +}; + +/** + * is.defined + * Test if `value` is defined. + * + * @param {Mixed} value value to test + * @return {Boolean} true if 'value' is defined, false otherwise + * @api public + */ + +is.defined = function (value) { + return value !== undefined; +}; + +/** + * is.empty + * Test if `value` is empty. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is empty, false otherwise + * @api public + */ + +is.empty = function (value) { + var type = toString.call(value); + var key; + + if ('[object Array]' === type || '[object Arguments]' === type) { + return value.length === 0; + } + + if ('[object Object]' === type) { + for (key in value) if (owns.call(value, key)) return false; + return true; + } + + if ('[object String]' === type) { + return '' === value; + } + + return false; +}; + +/** + * is.equal + * Test if `value` is equal to `other`. + * + * @param {Mixed} value value to test + * @param {Mixed} other value to compare with + * @return {Boolean} true if `value` is equal to `other`, false otherwise + */ + +is.equal = function (value, other) { + var type = toString.call(value) + var key; + + if (type !== toString.call(other)) { + return false; + } + + if ('[object Object]' === type) { + for (key in value) { + if (!is.equal(value[key], other[key])) { + return false; + } + } + return true; + } + + if ('[object Array]' === type) { + key = value.length; + if (key !== other.length) { + return false; + } + while (--key) { + if (!is.equal(value[key], other[key])) { + return false; + } + } + return true; + } + + if ('[object Function]' === type) { + return value.prototype === other.prototype; + } + + if ('[object Date]' === type) { + return value.getTime() === other.getTime(); + } + + return value === other; +}; + +/** + * is.hosted + * Test if `value` is hosted by `host`. + * + * @param {Mixed} value to test + * @param {Mixed} host host to test with + * @return {Boolean} true if `value` is hosted by `host`, false otherwise + * @api public + */ + +is.hosted = function (value, host) { + var type = typeof host[value]; + return type === 'object' ? !!host[value] : !NON_HOST_TYPES[type]; +}; + +/** + * is.instance + * Test if `value` is an instance of `constructor`. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is an instance of `constructor` + * @api public + */ + +is.instance = is['instanceof'] = function (value, constructor) { + return value instanceof constructor; +}; + +/** + * is.null + * Test if `value` is null. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is null, false otherwise + * @api public + */ + +is['null'] = function (value) { + return value === null; +}; + +/** + * is.undefined + * Test if `value` is undefined. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is undefined, false otherwise + * @api public + */ + +is.undefined = function (value) { + return value === undefined; +}; + +/** + * Test arguments. + */ + +/** + * is.arguments + * Test if `value` is an arguments object. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is an arguments object, false otherwise + * @api public + */ + +is.arguments = function (value) { + var isStandardArguments = '[object Arguments]' === toString.call(value); + var isOldArguments = !is.array(value) && is.arraylike(value) && is.object(value) && is.fn(value.callee); + return isStandardArguments || isOldArguments; +}; + +/** + * Test array. + */ + +/** + * is.array + * Test if 'value' is an array. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is an array, false otherwise + * @api public + */ + +is.array = function (value) { + return '[object Array]' === toString.call(value); +}; + +/** + * is.arguments.empty + * Test if `value` is an empty arguments object. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is an empty arguments object, false otherwise + * @api public + */ +is.arguments.empty = function (value) { + return is.arguments(value) && value.length === 0; +}; + +/** + * is.array.empty + * Test if `value` is an empty array. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is an empty array, false otherwise + * @api public + */ +is.array.empty = function (value) { + return is.array(value) && value.length === 0; +}; + +/** + * is.arraylike + * Test if `value` is an arraylike object. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is an arguments object, false otherwise + * @api public + */ + +is.arraylike = function (value) { + return !!value && !is.boolean(value) + && owns.call(value, 'length') + && isFinite(value.length) + && is.number(value.length) + && value.length >= 0; +}; + +/** + * Test boolean. + */ + +/** + * is.boolean + * Test if `value` is a boolean. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is a boolean, false otherwise + * @api public + */ + +is.boolean = function (value) { + return '[object Boolean]' === toString.call(value); +}; + +/** + * is.false + * Test if `value` is false. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is false, false otherwise + * @api public + */ + +is['false'] = function (value) { + return is.boolean(value) && (value === false || value.valueOf() === false); +}; + +/** + * is.true + * Test if `value` is true. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is true, false otherwise + * @api public + */ + +is['true'] = function (value) { + return is.boolean(value) && (value === true || value.valueOf() === true); +}; + +/** + * Test date. + */ + +/** + * is.date + * Test if `value` is a date. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is a date, false otherwise + * @api public + */ + +is.date = function (value) { + return '[object Date]' === toString.call(value); +}; + +/** + * Test element. + */ + +/** + * is.element + * Test if `value` is an html element. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is an HTML Element, false otherwise + * @api public + */ + +is.element = function (value) { + return value !== undefined + && typeof HTMLElement !== 'undefined' + && value instanceof HTMLElement + && value.nodeType === 1; +}; + +/** + * Test error. + */ + +/** + * is.error + * Test if `value` is an error object. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is an error object, false otherwise + * @api public + */ + +is.error = function (value) { + return '[object Error]' === toString.call(value); +}; + +/** + * Test function. + */ + +/** + * is.fn / is.function (deprecated) + * Test if `value` is a function. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is a function, false otherwise + * @api public + */ + +is.fn = is['function'] = function (value) { + var isAlert = typeof window !== 'undefined' && value === window.alert; + return isAlert || '[object Function]' === toString.call(value); +}; + +/** + * Test number. + */ + +/** + * is.number + * Test if `value` is a number. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is a number, false otherwise + * @api public + */ + +is.number = function (value) { + return '[object Number]' === toString.call(value); +}; + +/** + * is.infinite + * Test if `value` is positive or negative infinity. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is positive or negative Infinity, false otherwise + * @api public + */ +is.infinite = function (value) { + return value === Infinity || value === -Infinity; +}; + +/** + * is.decimal + * Test if `value` is a decimal number. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is a decimal number, false otherwise + * @api public + */ + +is.decimal = function (value) { + return is.number(value) && !isActualNaN(value) && !is.infinite(value) && value % 1 !== 0; +}; + +/** + * is.divisibleBy + * Test if `value` is divisible by `n`. + * + * @param {Number} value value to test + * @param {Number} n dividend + * @return {Boolean} true if `value` is divisible by `n`, false otherwise + * @api public + */ + +is.divisibleBy = function (value, n) { + var isDividendInfinite = is.infinite(value); + var isDivisorInfinite = is.infinite(n); + var isNonZeroNumber = is.number(value) && !isActualNaN(value) && is.number(n) && !isActualNaN(n) && n !== 0; + return isDividendInfinite || isDivisorInfinite || (isNonZeroNumber && value % n === 0); +}; + +/** + * is.int + * Test if `value` is an integer. + * + * @param value to test + * @return {Boolean} true if `value` is an integer, false otherwise + * @api public + */ + +is.int = function (value) { + return is.number(value) && !isActualNaN(value) && value % 1 === 0; +}; + +/** + * is.maximum + * Test if `value` is greater than 'others' values. + * + * @param {Number} value value to test + * @param {Array} others values to compare with + * @return {Boolean} true if `value` is greater than `others` values + * @api public + */ + +is.maximum = function (value, others) { + if (isActualNaN(value)) { + throw new TypeError('NaN is not a valid value'); + } else if (!is.arraylike(others)) { + throw new TypeError('second argument must be array-like'); + } + var len = others.length; + + while (--len >= 0) { + if (value < others[len]) { + return false; + } + } + + return true; +}; + +/** + * is.minimum + * Test if `value` is less than `others` values. + * + * @param {Number} value value to test + * @param {Array} others values to compare with + * @return {Boolean} true if `value` is less than `others` values + * @api public + */ + +is.minimum = function (value, others) { + if (isActualNaN(value)) { + throw new TypeError('NaN is not a valid value'); + } else if (!is.arraylike(others)) { + throw new TypeError('second argument must be array-like'); + } + var len = others.length; + + while (--len >= 0) { + if (value > others[len]) { + return false; + } + } + + return true; +}; + +/** + * is.nan + * Test if `value` is not a number. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is not a number, false otherwise + * @api public + */ + +is.nan = function (value) { + return !is.number(value) || value !== value; +}; + +/** + * is.even + * Test if `value` is an even number. + * + * @param {Number} value value to test + * @return {Boolean} true if `value` is an even number, false otherwise + * @api public + */ + +is.even = function (value) { + return is.infinite(value) || (is.number(value) && value === value && value % 2 === 0); +}; + +/** + * is.odd + * Test if `value` is an odd number. + * + * @param {Number} value value to test + * @return {Boolean} true if `value` is an odd number, false otherwise + * @api public + */ + +is.odd = function (value) { + return is.infinite(value) || (is.number(value) && value === value && value % 2 !== 0); +}; + +/** + * is.ge + * Test if `value` is greater than or equal to `other`. + * + * @param {Number} value value to test + * @param {Number} other value to compare with + * @return {Boolean} + * @api public + */ + +is.ge = function (value, other) { + if (isActualNaN(value) || isActualNaN(other)) { + throw new TypeError('NaN is not a valid value'); + } + return !is.infinite(value) && !is.infinite(other) && value >= other; +}; + +/** + * is.gt + * Test if `value` is greater than `other`. + * + * @param {Number} value value to test + * @param {Number} other value to compare with + * @return {Boolean} + * @api public + */ + +is.gt = function (value, other) { + if (isActualNaN(value) || isActualNaN(other)) { + throw new TypeError('NaN is not a valid value'); + } + return !is.infinite(value) && !is.infinite(other) && value > other; +}; + +/** + * is.le + * Test if `value` is less than or equal to `other`. + * + * @param {Number} value value to test + * @param {Number} other value to compare with + * @return {Boolean} if 'value' is less than or equal to 'other' + * @api public + */ + +is.le = function (value, other) { + if (isActualNaN(value) || isActualNaN(other)) { + throw new TypeError('NaN is not a valid value'); + } + return !is.infinite(value) && !is.infinite(other) && value <= other; +}; + +/** + * is.lt + * Test if `value` is less than `other`. + * + * @param {Number} value value to test + * @param {Number} other value to compare with + * @return {Boolean} if `value` is less than `other` + * @api public + */ + +is.lt = function (value, other) { + if (isActualNaN(value) || isActualNaN(other)) { + throw new TypeError('NaN is not a valid value'); + } + return !is.infinite(value) && !is.infinite(other) && value < other; +}; + +/** + * is.within + * Test if `value` is within `start` and `finish`. + * + * @param {Number} value value to test + * @param {Number} start lower bound + * @param {Number} finish upper bound + * @return {Boolean} true if 'value' is is within 'start' and 'finish' + * @api public + */ +is.within = function (value, start, finish) { + if (isActualNaN(value) || isActualNaN(start) || isActualNaN(finish)) { + throw new TypeError('NaN is not a valid value'); + } else if (!is.number(value) || !is.number(start) || !is.number(finish)) { + throw new TypeError('all arguments must be numbers'); + } + var isAnyInfinite = is.infinite(value) || is.infinite(start) || is.infinite(finish); + return isAnyInfinite || (value >= start && value <= finish); +}; + +/** + * Test object. + */ + +/** + * is.object + * Test if `value` is an object. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is an object, false otherwise + * @api public + */ + +is.object = function (value) { + return value && '[object Object]' === toString.call(value); +}; + +/** + * is.hash + * Test if `value` is a hash - a plain object literal. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is a hash, false otherwise + * @api public + */ + +is.hash = function (value) { + return is.object(value) && value.constructor === Object && !value.nodeType && !value.setInterval; +}; + +/** + * Test regexp. + */ + +/** + * is.regexp + * Test if `value` is a regular expression. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is a regexp, false otherwise + * @api public + */ + +is.regexp = function (value) { + return '[object RegExp]' === toString.call(value); +}; + +/** + * Test string. + */ + +/** + * is.string + * Test if `value` is a string. + * + * @param {Mixed} value value to test + * @return {Boolean} true if 'value' is a string, false otherwise + * @api public + */ + +is.string = function (value) { + return '[object String]' === toString.call(value); +}; + + +},{}],71:[function(_dereq_,module,exports){ +(function () { + "use strict"; + + // modified from https://github.com/kriskowal/es5-shim + var has = Object.prototype.hasOwnProperty, + is = _dereq_('is'), + forEach = _dereq_('foreach'), + hasDontEnumBug = !({'toString': null}).propertyIsEnumerable('toString'), + dontEnums = [ + "toString", + "toLocaleString", + "valueOf", + "hasOwnProperty", + "isPrototypeOf", + "propertyIsEnumerable", + "constructor" + ], + keysShim; + + keysShim = function keys(object) { + if (!is.object(object) && !is.array(object)) { + throw new TypeError("Object.keys called on a non-object"); + } + + var name, theKeys = []; + for (name in object) { + if (has.call(object, name)) { + theKeys.push(name); + } + } + + if (hasDontEnumBug) { + forEach(dontEnums, function (dontEnum) { + if (has.call(object, dontEnum)) { + theKeys.push(dontEnum); + } + }); + } + return theKeys; + }; + + module.exports = keysShim; +}()); + + +},{"foreach":69,"is":70}],72:[function(_dereq_,module,exports){ +var EventEmitter = _dereq_('events').EventEmitter +var inherits = _dereq_('util').inherits +var ranges = _dereq_('string-range') +var fixRange = _dereq_('level-fix-range') +var xtend = _dereq_('xtend') +var Batch = _dereq_('./batch') + +inherits(SubDB, EventEmitter) + +function SubDB (db, prefix, options) { + if('string' === typeof options) { + console.error('db.sublevel(name, seperator<string>) is depreciated') + console.error('use db.sublevel(name, {sep: separator})) if you must') + options = {sep: options} + } + if(!(this instanceof SubDB)) return new SubDB(db, prefix, options) + if(!db) throw new Error('must provide db') + if(!prefix) throw new Error('must provide prefix') + + options = options || {} + options.sep = options.sep || '\xff' + + this._parent = db + this._options = options + this.options = options + this._prefix = prefix + this._root = root(this) + db.sublevels[prefix] = this + this.sublevels = {} + this.methods = {} + var self = this + this.hooks = { + pre: function () { + return self.pre.apply(self, arguments) + }, + post: function () { + return self.post.apply(self, arguments) + } + } +} + +var SDB = SubDB.prototype + +SDB._key = function (key) { + var sep = this._options.sep + return sep + + this._prefix + + sep + + key +} + +SDB._getOptsAndCb = function (opts, cb) { + if (typeof opts == 'function') { + cb = opts + opts = {} + } + return { opts: xtend(opts, this._options), cb: cb } +} + +SDB.sublevel = function (prefix, options) { + if(this.sublevels[prefix]) + return this.sublevels[prefix] + return new SubDB(this, prefix, options || this._options) +} + +SDB.put = function (key, value, opts, cb) { + var res = this._getOptsAndCb(opts, cb) + this._root.put(this.prefix(key), value, res.opts, res.cb) +} + +SDB.get = function (key, opts, cb) { + var res = this._getOptsAndCb(opts, cb) + this._root.get(this.prefix(key), res.opts, res.cb) +} + +SDB.del = function (key, opts, cb) { + var res = this._getOptsAndCb(opts, cb) + this._root.del(this.prefix(key), res.opts, res.cb) +} + +SDB.batch = function (changes, opts, cb) { + if(!Array.isArray(changes)) + return new Batch(this) + var self = this, + res = this._getOptsAndCb(opts, cb) + changes.forEach(function (ch) { + + //OH YEAH, WE NEED TO VALIDATE THAT UPDATING THIS KEY/PREFIX IS ALLOWED + if('string' === typeof ch.prefix) + ch.key = ch.prefix + ch.key + else + ch.key = (ch.prefix || self).prefix(ch.key) + + if(ch.prefix) ch.prefix = null + }) + this._root.batch(changes, res.opts, res.cb) +} + +SDB._getKeyEncoding = function () { + if(this.options.keyEncoding) + return this.options.keyEncoding + if(this._parent && this._parent._getKeyEncoding) + return this._parent._getKeyEncoding() +} + +SDB._getValueEncoding = function () { + if(this.options.valueEncoding) + return this.options.valueEncoding + if(this._parent && this._parent._getValueEncoding) + return this._parent._getValueEncoding() +} + +SDB.prefix = function (key) { + var sep = this._options.sep + return this._parent.prefix() + sep + this._prefix + sep + (key || '') +} + +SDB.keyStream = +SDB.createKeyStream = function (opts) { + opts = opts || {} + opts.keys = true + opts.values = false + return this.createReadStream(opts) +} + +SDB.valueStream = +SDB.createValueStream = function (opts) { + opts = opts || {} + opts.keys = false + opts.values = true + opts.keys = false + return this.createReadStream(opts) +} + +function selectivelyMerge(_opts, opts) { + [ 'valueEncoding' + , 'encoding' + , 'keyEncoding' + , 'reverse' + , 'values' + , 'keys' + , 'limit' + , 'fillCache' + ] + .forEach(function (k) { + if (opts.hasOwnProperty(k)) _opts[k] = opts[k] + }) +} + +SDB.readStream = +SDB.createReadStream = function (opts) { + opts = opts || {} + var r = root(this) + var p = this.prefix() + + var _opts = ranges.prefix(opts, p) + selectivelyMerge(_opts, xtend(opts, this._options)) + + var s = r.createReadStream(_opts) + + if(_opts.values === false) { + var read = s.read + if (read) { + s.read = function (size) { + var val = read.call(this, size) + if (val) val = val.substring(p.length) + return val + } + } else { + var emit = s.emit + s.emit = function (event, val) { + if(event === 'data') { + emit.call(this, 'data', val.substring(p.length)) + } else + emit.call(this, event, val) + } + } + return s + } else if(_opts.keys === false) + return s + else { + var read = s.read + if (read) { + s.read = function (size) { + var d = read.call(this, size) + if (d) d.key = d.key.substring(p.length) + return d + } + } else { + s.on('data', function (d) { + //mutate the prefix! + //this doesn't work for createKeyStream admittedly. + d.key = d.key.substring(p.length) + }) + } + return s + } +} + + +SDB.writeStream = +SDB.createWriteStream = function () { + var r = root(this) + var p = this.prefix() + var ws = r.createWriteStream.apply(r, arguments) + var write = ws.write + + var encoding = this._options.encoding + var valueEncoding = this._options.valueEncoding + var keyEncoding = this._options.keyEncoding + + // slight optimization, if no encoding was specified at all, + // which will be the case most times, make write not check at all + var nocheck = !encoding && !valueEncoding && !keyEncoding + + ws.write = nocheck + ? function (data) { + data.key = p + data.key + return write.call(ws, data) + } + : function (data) { + data.key = p + data.key + + // not merging all options here since this happens on every write and things could get slowed down + // at this point we only consider encoding important to propagate + if (encoding && typeof data.encoding === 'undefined') + data.encoding = encoding + if (valueEncoding && typeof data.valueEncoding === 'undefined') + data.valueEncoding = valueEncoding + if (keyEncoding && typeof data.keyEncoding === 'undefined') + data.keyEncoding = keyEncoding + + return write.call(ws, data) + } + return ws +} + +SDB.approximateSize = function () { + var r = root(db) + return r.approximateSize.apply(r, arguments) +} + +function root(db) { + if(!db._parent) return db + return root(db._parent) +} + +SDB.pre = function (range, hook) { + if(!hook) hook = range, range = null + range = ranges.prefix(range, this.prefix(), this._options.sep) + var r = root(this._parent) + var p = this.prefix() + return r.hooks.pre(fixRange(range), function (ch, add, batch) { + hook({ + key: ch.key.substring(p.length), + value: ch.value, + type: ch.type + }, function (ch, _p) { + //maybe remove the second add arg now + //that op can have prefix? + add(ch, ch.prefix ? _p : (_p || p)) + }, batch) + }) +} + +SDB.post = function (range, hook) { + if(!hook) hook = range, range = null + var r = root(this._parent) + var p = this.prefix() + range = ranges.prefix(range, p, this._options.sep) + return r.hooks.post(fixRange(range), function (data) { + hook({key: data.key.substring(p.length), value: data.value, type: data.type}) + }) +} + +var exports = module.exports = SubDB + + +},{"./batch":60,"events":21,"level-fix-range":62,"string-range":65,"util":39,"xtend":67}],73:[function(_dereq_,module,exports){ +/* Copyright (c) 2012-2014 LevelUP contributors + * See list at <https://github.com/rvagg/node-levelup#contributing> + * MIT License + * <https://github.com/rvagg/node-levelup/blob/master/LICENSE.md> + */ + +var util = _dereq_('./util') + , WriteError = _dereq_('./errors').WriteError + + , getOptions = util.getOptions + , dispatchError = util.dispatchError + +function Batch (levelup) { + this._levelup = levelup + this.batch = levelup.db.batch() + this.ops = [] +} + +Batch.prototype.put = function (key_, value_, options) { + options = getOptions(this._levelup, options) + + var key = util.encodeKey(key_, options) + , value = util.encodeValue(value_, options) + + try { + this.batch.put(key, value) + } catch (e) { + throw new WriteError(e) + } + this.ops.push({ type : 'put', key : key, value : value }) + + return this +} + +Batch.prototype.del = function (key_, options) { + options = getOptions(this._levelup, options) + + var key = util.encodeKey(key_, options) + + try { + this.batch.del(key) + } catch (err) { + throw new WriteError(err) + } + this.ops.push({ type : 'del', key : key }) + + return this +} + +Batch.prototype.clear = function () { + try { + this.batch.clear() + } catch (err) { + throw new WriteError(err) + } + + this.ops = [] + return this +} + +Batch.prototype.write = function (callback) { + var levelup = this._levelup + , ops = this.ops + + try { + this.batch.write(function (err) { + if (err) + return dispatchError(levelup, new WriteError(err), callback) + levelup.emit('batch', ops) + if (callback) + callback() + }) + } catch (err) { + throw new WriteError(err) + } +} + +module.exports = Batch + +},{"./errors":74,"./util":77}],74:[function(_dereq_,module,exports){ +/* Copyright (c) 2012-2014 LevelUP contributors + * See list at <https://github.com/rvagg/node-levelup#contributing> + * MIT License + * <https://github.com/rvagg/node-levelup/blob/master/LICENSE.md> + */ + +var createError = _dereq_('errno').create + , LevelUPError = createError('LevelUPError') + , NotFoundError = createError('NotFoundError', LevelUPError) + +NotFoundError.prototype.notFound = true +NotFoundError.prototype.status = 404 + +module.exports = { + LevelUPError : LevelUPError + , InitializationError : createError('InitializationError', LevelUPError) + , OpenError : createError('OpenError', LevelUPError) + , ReadError : createError('ReadError', LevelUPError) + , WriteError : createError('WriteError', LevelUPError) + , NotFoundError : NotFoundError + , EncodingError : createError('EncodingError', LevelUPError) +} + +},{"errno":85}],75:[function(_dereq_,module,exports){ +(function (process){ +/* Copyright (c) 2012-2014 LevelUP contributors + * See list at <https://github.com/rvagg/node-levelup#contributing> + * MIT License + * <https://github.com/rvagg/node-levelup/blob/master/LICENSE.md> + */ + +var EventEmitter = _dereq_('events').EventEmitter + , inherits = _dereq_('util').inherits + , extend = _dereq_('xtend') + , prr = _dereq_('prr') + , DeferredLevelDOWN = _dereq_('deferred-leveldown') + + , WriteError = _dereq_('./errors').WriteError + , ReadError = _dereq_('./errors').ReadError + , NotFoundError = _dereq_('./errors').NotFoundError + , OpenError = _dereq_('./errors').OpenError + , EncodingError = _dereq_('./errors').EncodingError + , InitializationError = _dereq_('./errors').InitializationError + + , ReadStream = _dereq_('./read-stream') + , WriteStream = _dereq_('./write-stream') + , util = _dereq_('./util') + , Batch = _dereq_('./batch') + + , getOptions = util.getOptions + , defaultOptions = util.defaultOptions + , getLevelDOWN = util.getLevelDOWN + , dispatchError = util.dispatchError + +function getCallback (options, callback) { + return typeof options == 'function' ? options : callback +} + +// Possible LevelUP#_status values: +// - 'new' - newly created, not opened or closed +// - 'opening' - waiting for the database to be opened, post open() +// - 'open' - successfully opened the database, available for use +// - 'closing' - waiting for the database to be closed, post close() +// - 'closed' - database has been successfully closed, should not be +// used except for another open() operation + +function LevelUP (location, options, callback) { + if (!(this instanceof LevelUP)) + return new LevelUP(location, options, callback) + + var error + + EventEmitter.call(this) + this.setMaxListeners(Infinity) + + if (typeof location == 'function') { + options = typeof options == 'object' ? options : {} + options.db = location + location = null + } else if (typeof location == 'object' && typeof location.db == 'function') { + options = location + location = null + } + + if (typeof options == 'function') { + callback = options + options = {} + } + + if ((!options || typeof options.db != 'function') && typeof location != 'string') { + error = new InitializationError( + 'Must provide a location for the database') + if (callback) { + return process.nextTick(function () { + callback(error) + }) + } + throw error + } + + options = getOptions(this, options) + this.options = extend(defaultOptions, options) + this._status = 'new' + // set this.location as enumerable but not configurable or writable + prr(this, 'location', location, 'e') + + this.open(callback) +} + +inherits(LevelUP, EventEmitter) + +LevelUP.prototype.open = function (callback) { + var self = this + , dbFactory + , db + + if (this.isOpen()) { + if (callback) + process.nextTick(function () { callback(null, self) }) + return this + } + + if (this._isOpening()) { + return callback && this.once( + 'open' + , function () { callback(null, self) } + ) + } + + this.emit('opening') + + this._status = 'opening' + this.db = new DeferredLevelDOWN(this.location) + dbFactory = this.options.db || getLevelDOWN() + db = dbFactory(this.location) + + db.open(this.options, function (err) { + if (err) { + return dispatchError(self, new OpenError(err), callback) + } else { + self.db.setDb(db) + self.db = db + self._status = 'open' + if (callback) + callback(null, self) + self.emit('open') + self.emit('ready') + } + }) +} + +LevelUP.prototype.close = function (callback) { + var self = this + + if (this.isOpen()) { + this._status = 'closing' + this.db.close(function () { + self._status = 'closed' + self.emit('closed') + if (callback) + callback.apply(null, arguments) + }) + this.emit('closing') + this.db = null + } else if (this._status == 'closed' && callback) { + return process.nextTick(callback) + } else if (this._status == 'closing' && callback) { + this.once('closed', callback) + } else if (this._isOpening()) { + this.once('open', function () { + self.close(callback) + }) + } +} + +LevelUP.prototype.isOpen = function () { + return this._status == 'open' +} + +LevelUP.prototype._isOpening = function () { + return this._status == 'opening' +} + +LevelUP.prototype.isClosed = function () { + return (/^clos/).test(this._status) +} + +LevelUP.prototype.get = function (key_, options, callback) { + var self = this + , key + + callback = getCallback(options, callback) + + if (typeof callback != 'function') { + return dispatchError( + this + , new ReadError('get() requires key and callback arguments') + ) + } + + if (!this._isOpening() && !this.isOpen()) { + return dispatchError( + this + , new ReadError('Database is not open') + , callback + ) + } + + options = util.getOptions(this, options) + key = util.encodeKey(key_, options) + + options.asBuffer = util.isValueAsBuffer(options) + + this.db.get(key, options, function (err, value) { + if (err) { + if ((/notfound/i).test(err)) { + err = new NotFoundError( + 'Key not found in database [' + key_ + ']', err) + } else { + err = new ReadError(err) + } + return dispatchError(self, err, callback) + } + if (callback) { + try { + value = util.decodeValue(value, options) + } catch (e) { + return callback(new EncodingError(e)) + } + callback(null, value) + } + }) +} + +LevelUP.prototype.put = function (key_, value_, options, callback) { + var self = this + , key + , value + + callback = getCallback(options, callback) + + if (key_ === null || key_ === undefined + || value_ === null || value_ === undefined) { + return dispatchError( + this + , new WriteError('put() requires key and value arguments') + , callback + ) + } + + if (!this._isOpening() && !this.isOpen()) { + return dispatchError( + this + , new WriteError('Database is not open') + , callback + ) + } + + options = getOptions(this, options) + key = util.encodeKey(key_, options) + value = util.encodeValue(value_, options) + + this.db.put(key, value, options, function (err) { + if (err) { + return dispatchError(self, new WriteError(err), callback) + } else { + self.emit('put', key_, value_) + if (callback) + callback() + } + }) +} + +LevelUP.prototype.del = function (key_, options, callback) { + var self = this + , key + + callback = getCallback(options, callback) + + if (key_ === null || key_ === undefined) { + return dispatchError( + this + , new WriteError('del() requires a key argument') + , callback + ) + } + + if (!this._isOpening() && !this.isOpen()) { + return dispatchError( + this + , new WriteError('Database is not open') + , callback + ) + } + + options = getOptions(this, options) + key = util.encodeKey(key_, options) + + this.db.del(key, options, function (err) { + if (err) { + return dispatchError(self, new WriteError(err), callback) + } else { + self.emit('del', key_) + if (callback) + callback() + } + }) +} + +LevelUP.prototype.batch = function (arr_, options, callback) { + var self = this + , keyEnc + , valueEnc + , arr + + if (!arguments.length) + return new Batch(this) + + callback = getCallback(options, callback) + + if (!Array.isArray(arr_)) { + return dispatchError( + this + , new WriteError('batch() requires an array argument') + , callback + ) + } + + if (!this._isOpening() && !this.isOpen()) { + return dispatchError( + this + , new WriteError('Database is not open') + , callback + ) + } + + options = getOptions(this, options) + keyEnc = options.keyEncoding + valueEnc = options.valueEncoding + + arr = arr_.map(function (e) { + if (e.type === undefined || e.key === undefined) + return {} + + // inherit encoding + var kEnc = e.keyEncoding || keyEnc + , vEnc = e.valueEncoding || e.encoding || valueEnc + , o + + // If we're not dealing with plain utf8 strings or plain + // Buffers then we have to do some work on the array to + // encode the keys and/or values. This includes JSON types. + + if (kEnc != 'utf8' && kEnc != 'binary' + || vEnc != 'utf8' && vEnc != 'binary') { + o = { + type: e.type + , key: util.encodeKey(e.key, options, e) + } + + if (e.value !== undefined) + o.value = util.encodeValue(e.value, options, e) + + return o + } else { + return e + } + }) + + this.db.batch(arr, options, function (err) { + if (err) { + return dispatchError(self, new WriteError(err), callback) + } else { + self.emit('batch', arr_) + if (callback) + callback() + } + }) +} + +// DEPRECATED: prefer accessing LevelDOWN for this: db.db.approximateSize() +LevelUP.prototype.approximateSize = function (start_, end_, callback) { + var self = this + , start + , end + + if (start_ === null || start_ === undefined + || end_ === null || end_ === undefined + || typeof callback != 'function') { + return dispatchError( + this + , new ReadError('approximateSize() requires start, end and callback arguments') + , callback + ) + } + + start = util.encodeKey(start_, this.options) + end = util.encodeKey(end_, this.options) + + if (!this._isOpening() && !this.isOpen()) { + return dispatchError( + this + , new WriteError('Database is not open') + , callback + ) + } + + this.db.approximateSize(start, end, function (err, size) { + if (err) { + return dispatchError(self, new OpenError(err), callback) + } else if (callback) { + callback(null, size) + } + }) +} + +LevelUP.prototype.readStream = +LevelUP.prototype.createReadStream = function (options) { + var self = this + options = extend(this.options, options) + return new ReadStream( + options + , this + , function (options) { + return self.db.iterator(options) + } + ) +} + +LevelUP.prototype.keyStream = +LevelUP.prototype.createKeyStream = function (options) { + return this.createReadStream(extend(options, { keys: true, values: false })) +} + +LevelUP.prototype.valueStream = +LevelUP.prototype.createValueStream = function (options) { + return this.createReadStream(extend(options, { keys: false, values: true })) +} + +LevelUP.prototype.writeStream = +LevelUP.prototype.createWriteStream = function (options) { + return new WriteStream(extend(options), this) +} + +LevelUP.prototype.toString = function () { + return 'LevelUP' +} + +function utilStatic (name) { + return function (location, callback) { + getLevelDOWN()[name](location, callback || function () {}) + } +} + +module.exports = LevelUP +module.exports.copy = util.copy +// DEPRECATED: prefer accessing LevelDOWN for this: require('leveldown').destroy() +module.exports.destroy = utilStatic('destroy') +// DEPRECATED: prefer accessing LevelDOWN for this: require('leveldown').repair() +module.exports.repair = utilStatic('repair') + +}).call(this,_dereq_('_process')) +},{"./batch":73,"./errors":74,"./read-stream":76,"./util":77,"./write-stream":78,"_process":24,"deferred-leveldown":80,"events":21,"prr":86,"util":39,"xtend":96}],76:[function(_dereq_,module,exports){ +/* Copyright (c) 2012-2014 LevelUP contributors + * See list at <https://github.com/rvagg/node-levelup#contributing> + * MIT License <https://github.com/rvagg/node-levelup/blob/master/LICENSE.md> + */ + +// NOTE: we are fixed to readable-stream@1.0.x for now +// for pure Streams2 across Node versions +var Readable = _dereq_('readable-stream').Readable + , inherits = _dereq_('util').inherits + , extend = _dereq_('xtend') + , EncodingError = _dereq_('./errors').EncodingError + , util = _dereq_('./util') + + , defaultOptions = { keys: true, values: true } + + , makeKeyValueData = function (key, value) { + return { + key: util.decodeKey(key, this._options) + , value: util.decodeValue(value, this._options) + } + } + , makeKeyData = function (key) { + return util.decodeKey(key, this._options) + } + , makeValueData = function (_, value) { + return util.decodeValue(value, this._options) + } + , makeNoData = function () { return null } + +function ReadStream (options, db, iteratorFactory) { + if (!(this instanceof ReadStream)) + return new ReadStream(options, db, iteratorFactory) + + Readable.call(this, { objectMode: true, highWaterMark: options.highWaterMark }) + + // purely to keep `db` around until we're done so it's not GCed if the user doesn't keep a ref + this._db = db + + options = this._options = extend(defaultOptions, options) + + this._keyEncoding = options.keyEncoding || options.encoding + this._valueEncoding = options.valueEncoding || options.encoding + + if (typeof this._options.start != 'undefined') + this._options.start = util.encodeKey(this._options.start, this._options) + if (typeof this._options.end != 'undefined') + this._options.end = util.encodeKey(this._options.end, this._options) + if (typeof this._options.limit != 'number') + this._options.limit = -1 + + this._options.keyAsBuffer = util.isKeyAsBuffer(this._options) + + this._options.valueAsBuffer = util.isValueAsBuffer(this._options) + + this._makeData = this._options.keys && this._options.values + ? makeKeyValueData : this._options.keys + ? makeKeyData : this._options.values + ? makeValueData : makeNoData + + var self = this + if (!this._db.isOpen()) { + this._db.once('ready', function () { + if (!self._destroyed) { + self._iterator = iteratorFactory(self._options) + } + }) + } else + this._iterator = iteratorFactory(this._options) +} + +inherits(ReadStream, Readable) + +ReadStream.prototype._read = function read () { + var self = this + if (!self._db.isOpen()) { + return self._db.once('ready', function () { read.call(self) }) + } + if (self._destroyed) + return + + self._iterator.next(function(err, key, value) { + if (err || (key === undefined && value === undefined)) { + if (!err && !self._destroyed) + self.push(null) + return self._cleanup(err) + } + + try { + value = self._makeData(key, value) + } catch (e) { + return self._cleanup(new EncodingError(e)) + } + if (!self._destroyed) + self.push(value) + }) +} + +ReadStream.prototype._cleanup = function (err) { + if (this._destroyed) + return + + this._destroyed = true + + var self = this + if (err) + self.emit('error', err) + + if (self._iterator) { + self._iterator.end(function () { + self._iterator = null + self.emit('close') + }) + } else { + self.emit('close') + } +} + +ReadStream.prototype.destroy = function () { + this._cleanup() +} + +ReadStream.prototype.toString = function () { + return 'LevelUP.ReadStream' +} + +module.exports = ReadStream + +},{"./errors":74,"./util":77,"readable-stream":95,"util":39,"xtend":96}],77:[function(_dereq_,module,exports){ +(function (process,Buffer){ +/* Copyright (c) 2012-2014 LevelUP contributors + * See list at <https://github.com/rvagg/node-levelup#contributing> + * MIT License + * <https://github.com/rvagg/node-levelup/blob/master/LICENSE.md> + */ + +var extend = _dereq_('xtend') + , LevelUPError = _dereq_('./errors').LevelUPError + + , encodingNames = [ + 'hex' + , 'utf8' + , 'utf-8' + , 'ascii' + , 'binary' + , 'base64' + , 'ucs2' + , 'ucs-2' + , 'utf16le' + , 'utf-16le' + ] + + , defaultOptions = { + createIfMissing : true + , errorIfExists : false + , keyEncoding : 'utf8' + , valueEncoding : 'utf8' + , compression : true + } + + , leveldown + + , encodings = (function () { + function isBinary (data) { + return data === undefined || data === null || Buffer.isBuffer(data) + } + + var encodings = {} + encodings.utf8 = encodings['utf-8'] = { + encode : function (data) { + return isBinary(data) ? data : String(data) + } + , decode : function (data) { + return data + } + , buffer : false + , type : 'utf8' + } + encodings.json = { + encode : JSON.stringify + , decode : JSON.parse + , buffer : false + , type : 'json' + } + encodingNames.forEach(function (type) { + if (encodings[type]) + return + encodings[type] = { + encode : function (data) { + return isBinary(data) ? data : new Buffer(data, type) + } + , decode : function (buffer) { + return process.browser ? buffer.toString(type) : buffer; + } + , buffer : true + , type : type // useful for debugging purposes + } + }) + return encodings + })() + + , encodingOpts = (function () { + var eo = {} + encodingNames.forEach(function (e) { + eo[e] = { valueEncoding : e } + }) + return eo + }()) + +function copy (srcdb, dstdb, callback) { + srcdb.readStream() + .pipe(dstdb.writeStream()) + .on('close', callback ? callback : function () {}) + .on('error', callback ? callback : function (err) { throw err }) +} + +function getOptions (levelup, options) { + var s = typeof options == 'string' // just an encoding + if (!s && options && options.encoding && !options.valueEncoding) + options.valueEncoding = options.encoding + return extend( + (levelup && levelup.options) || {} + , s ? encodingOpts[options] || encodingOpts[defaultOptions.valueEncoding] + : options + ) +} + +function getLevelDOWN () { + if (leveldown) + return leveldown + + var requiredVersion = _dereq_('../package.json').devDependencies.leveldown + , missingLevelDOWNError = 'Could not locate LevelDOWN, try `npm install leveldown`' + , leveldownVersion + + try { + leveldownVersion = _dereq_('leveldown/package').version + } catch (e) { + throw new LevelUPError(missingLevelDOWNError) + } + + if (!_dereq_('semver').satisfies(leveldownVersion, requiredVersion)) { + throw new LevelUPError( + 'Installed version of LevelDOWN (' + + leveldownVersion + + ') does not match required version (' + + requiredVersion + + ')' + ) + } + + try { + return leveldown = _dereq_('leveldown') + } catch (e) { + throw new LevelUPError(missingLevelDOWNError) + } +} + +function dispatchError (levelup, error, callback) { + return typeof callback == 'function' + ? callback(error) + : levelup.emit('error', error) +} + +function getKeyEncoder (options, op) { + var type = ((op && op.keyEncoding) || options.keyEncoding) || 'utf8' + return encodings[type] || type +} + +function getValueEncoder (options, op) { + var type = (((op && (op.valueEncoding || op.encoding)) + || options.valueEncoding || options.encoding)) || 'utf8' + return encodings[type] || type +} + +function encodeKey (key, options, op) { + return getKeyEncoder(options, op).encode(key) +} + +function encodeValue (value, options, op) { + return getValueEncoder(options, op).encode(value) +} + +function decodeKey (key, options) { + return getKeyEncoder(options).decode(key) +} + +function decodeValue (value, options) { + return getValueEncoder(options).decode(value) +} + +function isValueAsBuffer (options, op) { + return getValueEncoder(options, op).buffer +} + +function isKeyAsBuffer (options, op) { + return getKeyEncoder(options, op).buffer +} + +module.exports = { + defaultOptions : defaultOptions + , copy : copy + , getOptions : getOptions + , getLevelDOWN : getLevelDOWN + , dispatchError : dispatchError + , encodeKey : encodeKey + , encodeValue : encodeValue + , isValueAsBuffer : isValueAsBuffer + , isKeyAsBuffer : isKeyAsBuffer + , decodeValue : decodeValue + , decodeKey : decodeKey +} + +}).call(this,_dereq_('_process'),_dereq_("buffer").Buffer) +},{"../package.json":97,"./errors":74,"_process":24,"buffer":17,"leveldown":"leveldown","leveldown/package":16,"semver":16,"xtend":96}],78:[function(_dereq_,module,exports){ +(function (process,global){ +/* Copyright (c) 2012-2014 LevelUP contributors + * See list at <https://github.com/rvagg/node-levelup#contributing> + * MIT License + * <https://github.com/rvagg/node-levelup/blob/master/LICENSE.md> + */ + +var Stream = _dereq_('stream').Stream + , inherits = _dereq_('util').inherits + , extend = _dereq_('xtend') + , bl = _dereq_('bl') + + , setImmediate = global.setImmediate || process.nextTick + + , getOptions = _dereq_('./util').getOptions + + , defaultOptions = { type: 'put' } + +function WriteStream (options, db) { + if (!(this instanceof WriteStream)) + return new WriteStream(options, db) + + Stream.call(this) + this._options = extend(defaultOptions, getOptions(db, options)) + this._db = db + this._buffer = [] + this._status = 'init' + this._end = false + this.writable = true + this.readable = false + + var self = this + , ready = function () { + if (!self.writable) + return + self._status = 'ready' + self.emit('ready') + self._process() + } + + if (db.isOpen()) + setImmediate(ready) + else + db.once('ready', ready) +} + +inherits(WriteStream, Stream) + +WriteStream.prototype.write = function (data) { + if (!this.writable) + return false + this._buffer.push(data) + if (this._status != 'init') + this._processDelayed() + if (this._options.maxBufferLength && + this._buffer.length > this._options.maxBufferLength) { + this._writeBlock = true + return false + } + return true +} + +WriteStream.prototype.end = function (data) { + var self = this + if (data) + this.write(data) + setImmediate(function () { + self._end = true + self._process() + }) +} + +WriteStream.prototype.destroy = function () { + this.writable = false + this.end() +} + +WriteStream.prototype.destroySoon = function () { + this.end() +} + +WriteStream.prototype.add = function (entry) { + if (!entry.props) + return + if (entry.props.Directory) + entry.pipe(this._db.writeStream(this._options)) + else if (entry.props.File || entry.File || entry.type == 'File') + this._write(entry) + return true +} + +WriteStream.prototype._processDelayed = function () { + var self = this + setImmediate(function () { + self._process() + }) +} + +WriteStream.prototype._process = function () { + var buffer + , self = this + + , cb = function (err) { + if (!self.writable) + return + if (self._status != 'closed') + self._status = 'ready' + if (err) { + self.writable = false + return self.emit('error', err) + } + self._process() + } + + if (self._status != 'ready' && self.writable) { + if (self._buffer.length && self._status != 'closed') + self._processDelayed() + return + } + + if (self._buffer.length && self.writable) { + self._status = 'writing' + buffer = self._buffer + self._buffer = [] + + self._db.batch(buffer.map(function (d) { + return { + type : d.type || self._options.type + , key : d.key + , value : d.value + , keyEncoding : d.keyEncoding || self._options.keyEncoding + , valueEncoding : d.valueEncoding + || d.encoding + || self._options.valueEncoding + } + }), cb) + + if (self._writeBlock) { + self._writeBlock = false + self.emit('drain') + } + + // don't allow close until callback has returned + return + } + + if (self._end && self._status != 'closed') { + self._status = 'closed' + self.writable = false + self.emit('close') + } +} + +WriteStream.prototype._write = function (entry) { + var key = entry.path || entry.props.path + , self = this + + if (!key) + return + + entry.pipe(bl(function (err, data) { + if (err) { + self.writable = false + return self.emit('error', err) + } + + if (self._options.fstreamRoot && + key.indexOf(self._options.fstreamRoot) > -1) + key = key.substr(self._options.fstreamRoot.length + 1) + + self.write({ key: key, value: data.slice(0) }) + })) +} + +WriteStream.prototype.toString = function () { + return 'LevelUP.WriteStream' +} + +module.exports = WriteStream + +}).call(this,_dereq_('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./util":77,"_process":24,"bl":79,"stream":36,"util":39,"xtend":96}],79:[function(_dereq_,module,exports){ +(function (Buffer){ +var DuplexStream = _dereq_('readable-stream').Duplex + , util = _dereq_('util') + +function BufferList (callback) { + if (!(this instanceof BufferList)) + return new BufferList(callback) + + this._bufs = [] + this.length = 0 + + if (typeof callback == 'function') { + this._callback = callback + + var piper = function (err) { + if (this._callback) { + this._callback(err) + this._callback = null + } + }.bind(this) + + this.on('pipe', function (src) { + src.on('error', piper) + }) + this.on('unpipe', function (src) { + src.removeListener('error', piper) + }) + } + else if (Buffer.isBuffer(callback)) + this.append(callback) + else if (Array.isArray(callback)) { + callback.forEach(function (b) { + Buffer.isBuffer(b) && this.append(b) + }.bind(this)) + } + + DuplexStream.call(this) +} + +util.inherits(BufferList, DuplexStream) + +BufferList.prototype._offset = function (offset) { + var tot = 0, i = 0, _t + for (; i < this._bufs.length; i++) { + _t = tot + this._bufs[i].length + if (offset < _t) + return [ i, offset - tot ] + tot = _t + } +} + +BufferList.prototype.append = function (buf) { + this._bufs.push(Buffer.isBuffer(buf) ? buf : new Buffer(buf)) + this.length += buf.length + return this +} + +BufferList.prototype._write = function (buf, encoding, callback) { + this.append(buf) + if (callback) + callback() +} + +BufferList.prototype._read = function (size) { + if (!this.length) + return this.push(null) + size = Math.min(size, this.length) + this.push(this.slice(0, size)) + this.consume(size) +} + +BufferList.prototype.end = function (chunk) { + DuplexStream.prototype.end.call(this, chunk) + + if (this._callback) { + this._callback(null, this.slice()) + this._callback = null + } +} + +BufferList.prototype.get = function (index) { + return this.slice(index, index + 1)[0] +} + +BufferList.prototype.slice = function (start, end) { + return this.copy(null, 0, start, end) +} + +BufferList.prototype.copy = function (dst, dstStart, srcStart, srcEnd) { + if (typeof srcStart != 'number' || srcStart < 0) + srcStart = 0 + if (typeof srcEnd != 'number' || srcEnd > this.length) + srcEnd = this.length + if (srcStart >= this.length) + return dst || new Buffer(0) + if (srcEnd <= 0) + return dst || new Buffer(0) + + var copy = !!dst + , off = this._offset(srcStart) + , len = srcEnd - srcStart + , bytes = len + , bufoff = (copy && dstStart) || 0 + , start = off[1] + , l + , i + + // copy/slice everything + if (srcStart === 0 && srcEnd == this.length) { + if (!copy) // slice, just return a full concat + return Buffer.concat(this._bufs) + + // copy, need to copy individual buffers + for (i = 0; i < this._bufs.length; i++) { + this._bufs[i].copy(dst, bufoff) + bufoff += this._bufs[i].length + } + + return dst + } + + // easy, cheap case where it's a subset of one of the buffers + if (bytes <= this._bufs[off[0]].length - start) { + return copy + ? this._bufs[off[0]].copy(dst, dstStart, start, start + bytes) + : this._bufs[off[0]].slice(start, start + bytes) + } + + if (!copy) // a slice, we need something to copy in to + dst = new Buffer(len) + + for (i = off[0]; i < this._bufs.length; i++) { + l = this._bufs[i].length - start + + if (bytes > l) { + this._bufs[i].copy(dst, bufoff, start) + } else { + this._bufs[i].copy(dst, bufoff, start, start + bytes) + break + } + + bufoff += l + bytes -= l + + if (start) + start = 0 + } + + return dst +} + +BufferList.prototype.toString = function (encoding, start, end) { + return this.slice(start, end).toString(encoding) +} + +BufferList.prototype.consume = function (bytes) { + while (this._bufs.length) { + if (bytes > this._bufs[0].length) { + bytes -= this._bufs[0].length + this.length -= this._bufs[0].length + this._bufs.shift() + } else { + this._bufs[0] = this._bufs[0].slice(bytes) + this.length -= bytes + break + } + } + return this +} + +BufferList.prototype.duplicate = function () { + var i = 0 + , copy = new BufferList() + + for (; i < this._bufs.length; i++) + copy.append(this._bufs[i]) + + return copy +} + +BufferList.prototype.destroy = function () { + this._bufs.length = 0; + this.length = 0; + this.push(null); +} + +;(function () { + var methods = { + 'readDoubleBE' : 8 + , 'readDoubleLE' : 8 + , 'readFloatBE' : 4 + , 'readFloatLE' : 4 + , 'readInt32BE' : 4 + , 'readInt32LE' : 4 + , 'readUInt32BE' : 4 + , 'readUInt32LE' : 4 + , 'readInt16BE' : 2 + , 'readInt16LE' : 2 + , 'readUInt16BE' : 2 + , 'readUInt16LE' : 2 + , 'readInt8' : 1 + , 'readUInt8' : 1 + } + + for (var m in methods) { + (function (m) { + BufferList.prototype[m] = function (offset) { + return this.slice(offset, offset + methods[m])[m](0) + } + }(m)) + } +}()) + +module.exports = BufferList + +}).call(this,_dereq_("buffer").Buffer) +},{"buffer":17,"readable-stream":95,"util":39}],80:[function(_dereq_,module,exports){ +(function (process,Buffer){ +var util = _dereq_('util') + , AbstractLevelDOWN = _dereq_('abstract-leveldown').AbstractLevelDOWN + +function DeferredLevelDOWN (location) { + AbstractLevelDOWN.call(this, typeof location == 'string' ? location : '') // optional location, who cares? + this._db = undefined + this._operations = [] +} + +util.inherits(DeferredLevelDOWN, AbstractLevelDOWN) + +// called by LevelUP when we have a real DB to take its place +DeferredLevelDOWN.prototype.setDb = function (db) { + this._db = db + this._operations.forEach(function (op) { + db[op.method].apply(db, op.args) + }) +} + +DeferredLevelDOWN.prototype._open = function (options, callback) { + return process.nextTick(callback) +} + +// queue a new deferred operation +DeferredLevelDOWN.prototype._operation = function (method, args) { + if (this._db) + return this._db[method].apply(this._db, args) + this._operations.push({ method: method, args: args }) +} + +// deferrables +'put get del batch approximateSize'.split(' ').forEach(function (m) { + DeferredLevelDOWN.prototype['_' + m] = function () { + this._operation(m, arguments) + } +}) + +DeferredLevelDOWN.prototype._isBuffer = function (obj) { + return Buffer.isBuffer(obj) +} + +// don't need to implement this as LevelUP's ReadStream checks for 'ready' state +DeferredLevelDOWN.prototype._iterator = function () { + throw new TypeError('not implemented') +} + +module.exports = DeferredLevelDOWN + +}).call(this,_dereq_('_process'),_dereq_("buffer").Buffer) +},{"_process":24,"abstract-leveldown":83,"buffer":17,"util":39}],81:[function(_dereq_,module,exports){ +module.exports=_dereq_(46) +},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/abstract-leveldown/abstract-chained-batch.js":46,"_process":24}],82:[function(_dereq_,module,exports){ +module.exports=_dereq_(47) +},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/abstract-leveldown/abstract-iterator.js":47,"_process":24}],83:[function(_dereq_,module,exports){ +module.exports=_dereq_(48) +},{"./abstract-chained-batch":81,"./abstract-iterator":82,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/abstract-leveldown/abstract-leveldown.js":48,"_process":24,"buffer":17,"xtend":96}],84:[function(_dereq_,module,exports){ +var prr = _dereq_('prr') + +function init (type, message, cause) { + prr(this, { + type : type + , name : type + // can be passed just a 'cause' + , cause : typeof message != 'string' ? message : cause + , message : !!message && typeof message != 'string' ? message.message : message + + }, 'ewr') +} + +// generic prototype, not intended to be actually used - helpful for `instanceof` +function CustomError (message, cause) { + Error.call(this) + if (Error.captureStackTrace) + Error.captureStackTrace(this, arguments.callee) + init.call(this, 'CustomError', message, cause) +} + +CustomError.prototype = new Error() + +function createError (errno, type, proto) { + var err = function (message, cause) { + init.call(this, type, message, cause) + //TODO: the specificity here is stupid, errno should be available everywhere + if (type == 'FilesystemError') { + this.code = this.cause.code + this.path = this.cause.path + this.errno = this.cause.errno + this.message = + (errno.errno[this.cause.errno] + ? errno.errno[this.cause.errno].description + : this.cause.message) + + (this.cause.path ? ' [' + this.cause.path + ']' : '') + } + Error.call(this) + if (Error.captureStackTrace) + Error.captureStackTrace(this, arguments.callee) + } + err.prototype = !!proto ? new proto() : new CustomError() + return err +} + +module.exports = function (errno) { + var ce = function (type, proto) { + return createError(errno, type, proto) + } + return { + CustomError : CustomError + , FilesystemError : ce('FilesystemError') + , createError : ce + } +} + +},{"prr":86}],85:[function(_dereq_,module,exports){ +var all = module.exports.all = [ + { + "errno": -1, + "code": "UNKNOWN", + "description": "unknown error" + }, + { + "errno": 0, + "code": "OK", + "description": "success" + }, + { + "errno": 1, + "code": "EOF", + "description": "end of file" + }, + { + "errno": 2, + "code": "EADDRINFO", + "description": "getaddrinfo error" + }, + { + "errno": 3, + "code": "EACCES", + "description": "permission denied" + }, + { + "errno": 4, + "code": "EAGAIN", + "description": "resource temporarily unavailable" + }, + { + "errno": 5, + "code": "EADDRINUSE", + "description": "address already in use" + }, + { + "errno": 6, + "code": "EADDRNOTAVAIL", + "description": "address not available" + }, + { + "errno": 7, + "code": "EAFNOSUPPORT", + "description": "address family not supported" + }, + { + "errno": 8, + "code": "EALREADY", + "description": "connection already in progress" + }, + { + "errno": 9, + "code": "EBADF", + "description": "bad file descriptor" + }, + { + "errno": 10, + "code": "EBUSY", + "description": "resource busy or locked" + }, + { + "errno": 11, + "code": "ECONNABORTED", + "description": "software caused connection abort" + }, + { + "errno": 12, + "code": "ECONNREFUSED", + "description": "connection refused" + }, + { + "errno": 13, + "code": "ECONNRESET", + "description": "connection reset by peer" + }, + { + "errno": 14, + "code": "EDESTADDRREQ", + "description": "destination address required" + }, + { + "errno": 15, + "code": "EFAULT", + "description": "bad address in system call argument" + }, + { + "errno": 16, + "code": "EHOSTUNREACH", + "description": "host is unreachable" + }, + { + "errno": 17, + "code": "EINTR", + "description": "interrupted system call" + }, + { + "errno": 18, + "code": "EINVAL", + "description": "invalid argument" + }, + { + "errno": 19, + "code": "EISCONN", + "description": "socket is already connected" + }, + { + "errno": 20, + "code": "EMFILE", + "description": "too many open files" + }, + { + "errno": 21, + "code": "EMSGSIZE", + "description": "message too long" + }, + { + "errno": 22, + "code": "ENETDOWN", + "description": "network is down" + }, + { + "errno": 23, + "code": "ENETUNREACH", + "description": "network is unreachable" + }, + { + "errno": 24, + "code": "ENFILE", + "description": "file table overflow" + }, + { + "errno": 25, + "code": "ENOBUFS", + "description": "no buffer space available" + }, + { + "errno": 26, + "code": "ENOMEM", + "description": "not enough memory" + }, + { + "errno": 27, + "code": "ENOTDIR", + "description": "not a directory" + }, + { + "errno": 28, + "code": "EISDIR", + "description": "illegal operation on a directory" + }, + { + "errno": 29, + "code": "ENONET", + "description": "machine is not on the network" + }, + { + "errno": 31, + "code": "ENOTCONN", + "description": "socket is not connected" + }, + { + "errno": 32, + "code": "ENOTSOCK", + "description": "socket operation on non-socket" + }, + { + "errno": 33, + "code": "ENOTSUP", + "description": "operation not supported on socket" + }, + { + "errno": 34, + "code": "ENOENT", + "description": "no such file or directory" + }, + { + "errno": 35, + "code": "ENOSYS", + "description": "function not implemented" + }, + { + "errno": 36, + "code": "EPIPE", + "description": "broken pipe" + }, + { + "errno": 37, + "code": "EPROTO", + "description": "protocol error" + }, + { + "errno": 38, + "code": "EPROTONOSUPPORT", + "description": "protocol not supported" + }, + { + "errno": 39, + "code": "EPROTOTYPE", + "description": "protocol wrong type for socket" + }, + { + "errno": 40, + "code": "ETIMEDOUT", + "description": "connection timed out" + }, + { + "errno": 41, + "code": "ECHARSET", + "description": "invalid Unicode character" + }, + { + "errno": 42, + "code": "EAIFAMNOSUPPORT", + "description": "address family for hostname not supported" + }, + { + "errno": 44, + "code": "EAISERVICE", + "description": "servname not supported for ai_socktype" + }, + { + "errno": 45, + "code": "EAISOCKTYPE", + "description": "ai_socktype not supported" + }, + { + "errno": 46, + "code": "ESHUTDOWN", + "description": "cannot send after transport endpoint shutdown" + }, + { + "errno": 47, + "code": "EEXIST", + "description": "file already exists" + }, + { + "errno": 48, + "code": "ESRCH", + "description": "no such process" + }, + { + "errno": 49, + "code": "ENAMETOOLONG", + "description": "name too long" + }, + { + "errno": 50, + "code": "EPERM", + "description": "operation not permitted" + }, + { + "errno": 51, + "code": "ELOOP", + "description": "too many symbolic links encountered" + }, + { + "errno": 52, + "code": "EXDEV", + "description": "cross-device link not permitted" + }, + { + "errno": 53, + "code": "ENOTEMPTY", + "description": "directory not empty" + }, + { + "errno": 54, + "code": "ENOSPC", + "description": "no space left on device" + }, + { + "errno": 55, + "code": "EIO", + "description": "i/o error" + }, + { + "errno": 56, + "code": "EROFS", + "description": "read-only file system" + }, + { + "errno": 57, + "code": "ENODEV", + "description": "no such device" + }, + { + "errno": 58, + "code": "ESPIPE", + "description": "invalid seek" + }, + { + "errno": 59, + "code": "ECANCELED", + "description": "operation canceled" + } +] + + +module.exports.errno = { + '-1': all[0] + , '0': all[1] + , '1': all[2] + , '2': all[3] + , '3': all[4] + , '4': all[5] + , '5': all[6] + , '6': all[7] + , '7': all[8] + , '8': all[9] + , '9': all[10] + , '10': all[11] + , '11': all[12] + , '12': all[13] + , '13': all[14] + , '14': all[15] + , '15': all[16] + , '16': all[17] + , '17': all[18] + , '18': all[19] + , '19': all[20] + , '20': all[21] + , '21': all[22] + , '22': all[23] + , '23': all[24] + , '24': all[25] + , '25': all[26] + , '26': all[27] + , '27': all[28] + , '28': all[29] + , '29': all[30] + , '31': all[31] + , '32': all[32] + , '33': all[33] + , '34': all[34] + , '35': all[35] + , '36': all[36] + , '37': all[37] + , '38': all[38] + , '39': all[39] + , '40': all[40] + , '41': all[41] + , '42': all[42] + , '44': all[43] + , '45': all[44] + , '46': all[45] + , '47': all[46] + , '48': all[47] + , '49': all[48] + , '50': all[49] + , '51': all[50] + , '52': all[51] + , '53': all[52] + , '54': all[53] + , '55': all[54] + , '56': all[55] + , '57': all[56] + , '58': all[57] + , '59': all[58] +} + + +module.exports.code = { + 'UNKNOWN': all[0] + , 'OK': all[1] + , 'EOF': all[2] + , 'EADDRINFO': all[3] + , 'EACCES': all[4] + , 'EAGAIN': all[5] + , 'EADDRINUSE': all[6] + , 'EADDRNOTAVAIL': all[7] + , 'EAFNOSUPPORT': all[8] + , 'EALREADY': all[9] + , 'EBADF': all[10] + , 'EBUSY': all[11] + , 'ECONNABORTED': all[12] + , 'ECONNREFUSED': all[13] + , 'ECONNRESET': all[14] + , 'EDESTADDRREQ': all[15] + , 'EFAULT': all[16] + , 'EHOSTUNREACH': all[17] + , 'EINTR': all[18] + , 'EINVAL': all[19] + , 'EISCONN': all[20] + , 'EMFILE': all[21] + , 'EMSGSIZE': all[22] + , 'ENETDOWN': all[23] + , 'ENETUNREACH': all[24] + , 'ENFILE': all[25] + , 'ENOBUFS': all[26] + , 'ENOMEM': all[27] + , 'ENOTDIR': all[28] + , 'EISDIR': all[29] + , 'ENONET': all[30] + , 'ENOTCONN': all[31] + , 'ENOTSOCK': all[32] + , 'ENOTSUP': all[33] + , 'ENOENT': all[34] + , 'ENOSYS': all[35] + , 'EPIPE': all[36] + , 'EPROTO': all[37] + , 'EPROTONOSUPPORT': all[38] + , 'EPROTOTYPE': all[39] + , 'ETIMEDOUT': all[40] + , 'ECHARSET': all[41] + , 'EAIFAMNOSUPPORT': all[42] + , 'EAISERVICE': all[43] + , 'EAISOCKTYPE': all[44] + , 'ESHUTDOWN': all[45] + , 'EEXIST': all[46] + , 'ESRCH': all[47] + , 'ENAMETOOLONG': all[48] + , 'EPERM': all[49] + , 'ELOOP': all[50] + , 'EXDEV': all[51] + , 'ENOTEMPTY': all[52] + , 'ENOSPC': all[53] + , 'EIO': all[54] + , 'EROFS': all[55] + , 'ENODEV': all[56] + , 'ESPIPE': all[57] + , 'ECANCELED': all[58] +} + + +module.exports.custom = _dereq_("./custom")(module.exports) +module.exports.create = module.exports.custom.createError +},{"./custom":84}],86:[function(_dereq_,module,exports){ +/*! + * prr + * (c) 2013 Rod Vagg <rod@vagg.org> + * https://github.com/rvagg/prr + * License: MIT + */ + +(function (name, context, definition) { + if (typeof module != 'undefined' && module.exports) + module.exports = definition() + else + context[name] = definition() +})('prr', this, function() { + + var setProperty = typeof Object.defineProperty == 'function' + ? function (obj, key, options) { + Object.defineProperty(obj, key, options) + return obj + } + : function (obj, key, options) { // < es5 + obj[key] = options.value + return obj + } + + , makeOptions = function (value, options) { + var oo = typeof options == 'object' + , os = !oo && typeof options == 'string' + , op = function (p) { + return oo + ? !!options[p] + : os + ? options.indexOf(p[0]) > -1 + : false + } + + return { + enumerable : op('enumerable') + , configurable : op('configurable') + , writable : op('writable') + , value : value + } + } + + , prr = function (obj, key, value, options) { + var k + + options = makeOptions(value, options) + + if (typeof key == 'object') { + for (k in key) { + if (Object.hasOwnProperty.call(key, k)) { + options.value = key[k] + setProperty(obj, k, options) + } + } + return obj + } + + return setProperty(obj, key, options) + } + + return prr +}) +},{}],87:[function(_dereq_,module,exports){ +module.exports=_dereq_(26) +},{"./_stream_readable":89,"./_stream_writable":91,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_duplex.js":26,"_process":24,"core-util-is":92,"inherits":44}],88:[function(_dereq_,module,exports){ +module.exports=_dereq_(27) +},{"./_stream_transform":90,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_passthrough.js":27,"core-util-is":92,"inherits":44}],89:[function(_dereq_,module,exports){ +module.exports=_dereq_(28) +},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_readable.js":28,"_process":24,"buffer":17,"core-util-is":92,"events":21,"inherits":44,"isarray":93,"stream":36,"string_decoder/":94}],90:[function(_dereq_,module,exports){ +module.exports=_dereq_(29) +},{"./_stream_duplex":87,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_transform.js":29,"core-util-is":92,"inherits":44}],91:[function(_dereq_,module,exports){ +module.exports=_dereq_(30) +},{"./_stream_duplex":87,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_writable.js":30,"_process":24,"buffer":17,"core-util-is":92,"inherits":44,"stream":36}],92:[function(_dereq_,module,exports){ +module.exports=_dereq_(31) +},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/node_modules/core-util-is/lib/util.js":31,"buffer":17}],93:[function(_dereq_,module,exports){ +module.exports=_dereq_(22) +},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/isarray/index.js":22}],94:[function(_dereq_,module,exports){ +module.exports=_dereq_(37) +},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/string_decoder/index.js":37,"buffer":17}],95:[function(_dereq_,module,exports){ +module.exports=_dereq_(33) +},{"./lib/_stream_duplex.js":87,"./lib/_stream_passthrough.js":88,"./lib/_stream_readable.js":89,"./lib/_stream_transform.js":90,"./lib/_stream_writable.js":91,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/readable.js":33,"stream":36}],96:[function(_dereq_,module,exports){ +module.exports=_dereq_(49) +},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/abstract-leveldown/node_modules/xtend/index.js":49}],97:[function(_dereq_,module,exports){ +module.exports={ + "name": "levelup", + "description": "Fast & simple storage - a Node.js-style LevelDB wrapper", + "version": "0.18.6", + "contributors": [ + { + "name": "Rod Vagg", + "email": "r@va.gg", + "url": "https://github.com/rvagg" + }, + { + "name": "John Chesley", + "email": "john@chesl.es", + "url": "https://github.com/chesles/" + }, + { + "name": "Jake Verbaten", + "email": "raynos2@gmail.com", + "url": "https://github.com/raynos" + }, + { + "name": "Dominic Tarr", + "email": "dominic.tarr@gmail.com", + "url": "https://github.com/dominictarr" + }, + { + "name": "Max Ogden", + "email": "max@maxogden.com", + "url": "https://github.com/maxogden" + }, + { + "name": "Lars-Magnus Skog", + "email": "lars.magnus.skog@gmail.com", + "url": "https://github.com/ralphtheninja" + }, + { + "name": "David Björklund", + "email": "david.bjorklund@gmail.com", + "url": "https://github.com/kesla" + }, + { + "name": "Julian Gruber", + "email": "julian@juliangruber.com", + "url": "https://github.com/juliangruber" + }, + { + "name": "Paolo Fragomeni", + "email": "paolo@async.ly", + "url": "https://github.com/hij1nx" + }, + { + "name": "Anton Whalley", + "email": "anton.whalley@nearform.com", + "url": "https://github.com/No9" + }, + { + "name": "Matteo Collina", + "email": "matteo.collina@gmail.com", + "url": "https://github.com/mcollina" + }, + { + "name": "Pedro Teixeira", + "email": "pedro.teixeira@gmail.com", + "url": "https://github.com/pgte" + }, + { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "https://github.com/substack" + } + ], + "repository": { + "type": "git", + "url": "https://github.com/rvagg/node-levelup.git" + }, + "homepage": "https://github.com/rvagg/node-levelup", + "keywords": [ + "leveldb", + "stream", + "database", + "db", + "store", + "storage", + "json" + ], + "main": "lib/levelup.js", + "dependencies": { + "bl": "~0.8.1", + "deferred-leveldown": "~0.2.0", + "errno": "~0.1.1", + "prr": "~0.0.0", + "readable-stream": "~1.0.26", + "semver": "~2.3.1", + "xtend": "~3.0.0" + }, + "devDependencies": { + "leveldown": "~0.10.0", + "bustermove": "*", + "tap": "*", + "referee": "*", + "rimraf": "*", + "async": "*", + "fstream": "*", + "tar": "*", + "mkfiletree": "*", + "readfiletree": "*", + "slow-stream": ">=0.0.4", + "delayed": "*", + "boganipsum": "*", + "du": "*", + "memdown": "*", + "msgpack-js": "*" + }, + "browser": { + "leveldown": false, + "leveldown/package": false, + "semver": false + }, + "scripts": { + "test": "tap test/*-test.js --stderr", + "functionaltests": "node ./test/functional/fstream-test.js && node ./test/functional/binary-data-test.js && node ./test/functional/compat-test.js", + "alltests": "npm test && npm run-script functionaltests" + }, + "license": "MIT", + "gitHead": "213e989e2b75273e2b44c23f84f95e35bff7ea11", + "bugs": { + "url": "https://github.com/rvagg/node-levelup/issues" + }, + "_id": "levelup@0.18.6", + "_shasum": "e6a01cb089616c8ecc0291c2a9bd3f0c44e3e5eb", + "_from": "levelup@~0.18.4", + "_npmVersion": "1.4.14", + "_npmUser": { + "name": "rvagg", + "email": "rod@vagg.org" + }, + "maintainers": [ + { + "name": "rvagg", + "email": "rod@vagg.org" + } + ], + "dist": { + "shasum": "e6a01cb089616c8ecc0291c2a9bd3f0c44e3e5eb", + "tarball": "http://127.0.0.1:5080/tarballs/levelup/0.18.6.tgz" + }, + "_resolved": "http://127.0.0.1:5080/tarballs/levelup/0.18.6.tgz", + "readme": "ERROR: No README data found!" +} + +},{}],98:[function(_dereq_,module,exports){ +'use strict'; + +module.exports = INTERNAL; + +function INTERNAL() {} +},{}],99:[function(_dereq_,module,exports){ +'use strict'; +var Promise = _dereq_('./promise'); +var reject = _dereq_('./reject'); +var resolve = _dereq_('./resolve'); +var INTERNAL = _dereq_('./INTERNAL'); +var handlers = _dereq_('./handlers'); +module.exports = all; +function all(iterable) { + if (Object.prototype.toString.call(iterable) !== '[object Array]') { + return reject(new TypeError('must be an array')); + } + + var len = iterable.length; + var called = false; + if (!len) { + return resolve([]); + } + + var values = new Array(len); + var resolved = 0; + var i = -1; + var promise = new Promise(INTERNAL); + + while (++i < len) { + allResolver(iterable[i], i); + } + return promise; + function allResolver(value, i) { + resolve(value).then(resolveFromAll, function (error) { + if (!called) { + called = true; + handlers.reject(promise, error); + } + }); + function resolveFromAll(outValue) { + values[i] = outValue; + if (++resolved === len & !called) { + called = true; + handlers.resolve(promise, values); + } + } + } +} +},{"./INTERNAL":98,"./handlers":100,"./promise":102,"./reject":105,"./resolve":106}],100:[function(_dereq_,module,exports){ +'use strict'; +var tryCatch = _dereq_('./tryCatch'); +var resolveThenable = _dereq_('./resolveThenable'); +var states = _dereq_('./states'); + +exports.resolve = function (self, value) { + var result = tryCatch(getThen, value); + if (result.status === 'error') { + return exports.reject(self, result.value); + } + var thenable = result.value; + + if (thenable) { + resolveThenable.safely(self, thenable); + } else { + self.state = states.FULFILLED; + self.outcome = value; + var i = -1; + var len = self.queue.length; + while (++i < len) { + self.queue[i].callFulfilled(value); + } + } + return self; +}; +exports.reject = function (self, error) { + self.state = states.REJECTED; + self.outcome = error; + var i = -1; + var len = self.queue.length; + while (++i < len) { + self.queue[i].callRejected(error); + } + return self; +}; + +function getThen(obj) { + // Make sure we only access the accessor once as required by the spec + var then = obj && obj.then; + if (obj && typeof obj === 'object' && typeof then === 'function') { + return function appyThen() { + then.apply(obj, arguments); + }; + } +} +},{"./resolveThenable":107,"./states":108,"./tryCatch":109}],101:[function(_dereq_,module,exports){ +module.exports = exports = _dereq_('./promise'); + +exports.resolve = _dereq_('./resolve'); +exports.reject = _dereq_('./reject'); +exports.all = _dereq_('./all'); +exports.race = _dereq_('./race'); +},{"./all":99,"./promise":102,"./race":104,"./reject":105,"./resolve":106}],102:[function(_dereq_,module,exports){ +'use strict'; + +var unwrap = _dereq_('./unwrap'); +var INTERNAL = _dereq_('./INTERNAL'); +var resolveThenable = _dereq_('./resolveThenable'); +var states = _dereq_('./states'); +var QueueItem = _dereq_('./queueItem'); + +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); + } +} + +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)); + } + + return promise; +}; + +},{"./INTERNAL":98,"./queueItem":103,"./resolveThenable":107,"./states":108,"./unwrap":110}],103:[function(_dereq_,module,exports){ +'use strict'; +var handlers = _dereq_('./handlers'); +var unwrap = _dereq_('./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":100,"./unwrap":110}],104:[function(_dereq_,module,exports){ +'use strict'; +var Promise = _dereq_('./promise'); +var reject = _dereq_('./reject'); +var resolve = _dereq_('./resolve'); +var INTERNAL = _dereq_('./INTERNAL'); +var handlers = _dereq_('./handlers'); +module.exports = race; +function race(iterable) { + if (Object.prototype.toString.call(iterable) !== '[object Array]') { + return reject(new TypeError('must be an array')); + } + + var len = iterable.length; + var called = false; + if (!len) { + return resolve([]); + } + + var resolved = 0; + var i = -1; + var promise = new Promise(INTERNAL); + + while (++i < len) { + resolver(iterable[i]); + } + return promise; + function resolver(value) { + resolve(value).then(function (response) { + if (!called) { + called = true; + handlers.resolve(promise, response); + } + }, function (error) { + if (!called) { + called = true; + handlers.reject(promise, error); + } + }); + } +} +},{"./INTERNAL":98,"./handlers":100,"./promise":102,"./reject":105,"./resolve":106}],105:[function(_dereq_,module,exports){ +'use strict'; + +var Promise = _dereq_('./promise'); +var INTERNAL = _dereq_('./INTERNAL'); +var handlers = _dereq_('./handlers'); +module.exports = reject; + +function reject(reason) { + var promise = new Promise(INTERNAL); + return handlers.reject(promise, reason); +} +},{"./INTERNAL":98,"./handlers":100,"./promise":102}],106:[function(_dereq_,module,exports){ +'use strict'; + +var Promise = _dereq_('./promise'); +var INTERNAL = _dereq_('./INTERNAL'); +var handlers = _dereq_('./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":98,"./handlers":100,"./promise":102}],107:[function(_dereq_,module,exports){ +'use strict'; +var handlers = _dereq_('./handlers'); +var tryCatch = _dereq_('./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":100,"./tryCatch":109}],108:[function(_dereq_,module,exports){ +// Lazy man's symbols for states + +exports.REJECTED = ['REJECTED']; +exports.FULFILLED = ['FULFILLED']; +exports.PENDING = ['PENDING']; +},{}],109:[function(_dereq_,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; +} +},{}],110:[function(_dereq_,module,exports){ +'use strict'; + +var immediate = _dereq_('immediate'); +var handlers = _dereq_('./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":100,"immediate":111}],111:[function(_dereq_,module,exports){ +'use strict'; +var types = [ + _dereq_('./nextTick'), + _dereq_('./mutation.js'), + _dereq_('./messageChannel'), + _dereq_('./stateChange'), + _dereq_('./timeout') +]; +var draining; +var queue = []; +//named nextTick for less confusing stack traces +function nextTick() { + draining = true; + var i, oldQueue; + var len = queue.length; + while (len) { + oldQueue = queue; + queue = []; + i = -1; + while (++i < len) { + oldQueue[i](); + } + len = queue.length; + } + draining = false; +} +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; + } +} +module.exports = immediate; +function immediate(task) { + if (queue.push(task) === 1 && !draining) { + scheduleDrain(); + } +} +},{"./messageChannel":112,"./mutation.js":113,"./nextTick":16,"./stateChange":114,"./timeout":115}],112:[function(_dereq_,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 : {}) +},{}],113:[function(_dereq_,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 : {}) +},{}],114:[function(_dereq_,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 <script> 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 : {}) +},{}],115:[function(_dereq_,module,exports){ +'use strict'; +exports.test = function () { + return true; +}; + +exports.install = function (t) { + return function () { + setTimeout(t, 0); + }; +}; +},{}],116:[function(_dereq_,module,exports){ +"use strict"; + +// Extends method +// (taken from http://code.jquery.com/jquery-1.9.0.js) +// Populate the class2type map +var class2type = {}; + +var types = [ + "Boolean", "Number", "String", "Function", "Array", + "Date", "RegExp", "Object", "Error" +]; +for (var i = 0; i < types.length; i++) { + var typename = types[i]; + class2type["[object " + typename + "]"] = typename.toLowerCase(); +} + +var core_toString = class2type.toString; +var core_hasOwn = class2type.hasOwnProperty; + +function type(obj) { + if (obj === null) { + return String(obj); + } + return typeof obj === "object" || typeof obj === "function" ? + class2type[core_toString.call(obj)] || "object" : + typeof obj; +} + +function isWindow(obj) { + return obj !== null && obj === obj.window; +} + +function isPlainObject(obj) { + // Must be an Object. + // Because of IE, we also have to check the presence of + // the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if (!obj || type(obj) !== "object" || obj.nodeType || isWindow(obj)) { + return false; + } + + try { + // Not own constructor property must be Object + if (obj.constructor && + !core_hasOwn.call(obj, "constructor") && + !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + var key; + for (key in obj) {} + + return key === undefined || core_hasOwn.call(obj, key); +} + + +function isFunction(obj) { + return type(obj) === "function"; +} + +var isArray = Array.isArray || function (obj) { + return type(obj) === "array"; +}; + +function extend() { + // originally extend() was recursive, but this ended up giving us + // "call stack exceeded", so it's been unrolled to use a literal stack + // (see https://github.com/pouchdb/pouchdb/issues/2543) + var stack = []; + var i = -1; + var len = arguments.length; + var args = new Array(len); + while (++i < len) { + args[i] = arguments[i]; + } + var container = {}; + stack.push({args: args, result: {container: container, key: 'key'}}); + var next; + while ((next = stack.pop())) { + extendInner(stack, next.args, next.result); + } + return container.key; +} + +function extendInner(stack, args, result) { + var options, name, src, copy, copyIsArray, clone, + target = args[0] || {}, + i = 1, + length = args.length, + deep = false, + numericStringRegex = /\d+/, + optionsIsArray; + + // Handle a deep copy situation + if (typeof target === "boolean") { + deep = target; + target = args[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if (typeof target !== "object" && !isFunction(target)) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if (length === i) { + /* jshint validthis: true */ + target = this; + --i; + } + + for (; i < length; i++) { + // Only deal with non-null/undefined values + if ((options = args[i]) != null) { + optionsIsArray = isArray(options); + // Extend the base object + for (name in options) { + //if (options.hasOwnProperty(name)) { + if (!(name in Object.prototype)) { + if (optionsIsArray && !numericStringRegex.test(name)) { + continue; + } + + src = target[name]; + copy = options[name]; + + // Prevent never-ending loop + if (target === copy) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if (deep && copy && (isPlainObject(copy) || + (copyIsArray = isArray(copy)))) { + if (copyIsArray) { + copyIsArray = false; + clone = src && isArray(src) ? src : []; + + } else { + clone = src && isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + stack.push({ + args: [deep, clone, copy], + result: { + container: target, + key: name + } + }); + + // Don't bring in undefined values + } else if (copy !== undefined) { + if (!(isArray(options) && isFunction(copy))) { + target[name] = copy; + } + } + } + } + } + } + + // "Return" the modified object by setting the key + // on the given container + result.container[result.key] = target; +} + + +module.exports = extend; + + + +},{}],117:[function(_dereq_,module,exports){ +/*jshint bitwise:false*/ +/*global unescape*/ + +(function (factory) { + if (typeof exports === 'object') { + // Node/CommonJS + module.exports = factory(); + } else if (typeof define === 'function' && define.amd) { + // AMD + define(factory); + } else { + // Browser globals (with support for web workers) + var glob; + try { + glob = window; + } catch (e) { + glob = self; + } + + glob.SparkMD5 = factory(); + } +}(function (undefined) { + + 'use strict'; + + //////////////////////////////////////////////////////////////////////////// + + /* + * Fastest md5 implementation around (JKM md5) + * Credits: Joseph Myers + * + * @see http://www.myersdaily.org/joseph/javascript/md5-text.html + * @see http://jsperf.com/md5-shootout/7 + */ + + /* this function is much faster, + so if possible we use it. Some IEs + are the only ones I know of that + need the idiotic second function, + generated by an if clause. */ + var add32 = function (a, b) { + return (a + b) & 0xFFFFFFFF; + }, + + cmn = function (q, a, b, x, s, t) { + a = add32(add32(a, q), add32(x, t)); + return add32((a << s) | (a >>> (32 - s)), b); + }, + + ff = function (a, b, c, d, x, s, t) { + return cmn((b & c) | ((~b) & d), a, b, x, s, t); + }, + + gg = function (a, b, c, d, x, s, t) { + return cmn((b & d) | (c & (~d)), a, b, x, s, t); + }, + + hh = function (a, b, c, d, x, s, t) { + return cmn(b ^ c ^ d, a, b, x, s, t); + }, + + ii = function (a, b, c, d, x, s, t) { + return cmn(c ^ (b | (~d)), a, b, x, s, t); + }, + + md5cycle = function (x, k) { + var a = x[0], + b = x[1], + c = x[2], + d = x[3]; + + a = ff(a, b, c, d, k[0], 7, -680876936); + d = ff(d, a, b, c, k[1], 12, -389564586); + c = ff(c, d, a, b, k[2], 17, 606105819); + b = ff(b, c, d, a, k[3], 22, -1044525330); + a = ff(a, b, c, d, k[4], 7, -176418897); + d = ff(d, a, b, c, k[5], 12, 1200080426); + c = ff(c, d, a, b, k[6], 17, -1473231341); + b = ff(b, c, d, a, k[7], 22, -45705983); + a = ff(a, b, c, d, k[8], 7, 1770035416); + d = ff(d, a, b, c, k[9], 12, -1958414417); + c = ff(c, d, a, b, k[10], 17, -42063); + b = ff(b, c, d, a, k[11], 22, -1990404162); + a = ff(a, b, c, d, k[12], 7, 1804603682); + d = ff(d, a, b, c, k[13], 12, -40341101); + c = ff(c, d, a, b, k[14], 17, -1502002290); + b = ff(b, c, d, a, k[15], 22, 1236535329); + + a = gg(a, b, c, d, k[1], 5, -165796510); + d = gg(d, a, b, c, k[6], 9, -1069501632); + c = gg(c, d, a, b, k[11], 14, 643717713); + b = gg(b, c, d, a, k[0], 20, -373897302); + a = gg(a, b, c, d, k[5], 5, -701558691); + d = gg(d, a, b, c, k[10], 9, 38016083); + c = gg(c, d, a, b, k[15], 14, -660478335); + b = gg(b, c, d, a, k[4], 20, -405537848); + a = gg(a, b, c, d, k[9], 5, 568446438); + d = gg(d, a, b, c, k[14], 9, -1019803690); + c = gg(c, d, a, b, k[3], 14, -187363961); + b = gg(b, c, d, a, k[8], 20, 1163531501); + a = gg(a, b, c, d, k[13], 5, -1444681467); + d = gg(d, a, b, c, k[2], 9, -51403784); + c = gg(c, d, a, b, k[7], 14, 1735328473); + b = gg(b, c, d, a, k[12], 20, -1926607734); + + a = hh(a, b, c, d, k[5], 4, -378558); + d = hh(d, a, b, c, k[8], 11, -2022574463); + c = hh(c, d, a, b, k[11], 16, 1839030562); + b = hh(b, c, d, a, k[14], 23, -35309556); + a = hh(a, b, c, d, k[1], 4, -1530992060); + d = hh(d, a, b, c, k[4], 11, 1272893353); + c = hh(c, d, a, b, k[7], 16, -155497632); + b = hh(b, c, d, a, k[10], 23, -1094730640); + a = hh(a, b, c, d, k[13], 4, 681279174); + d = hh(d, a, b, c, k[0], 11, -358537222); + c = hh(c, d, a, b, k[3], 16, -722521979); + b = hh(b, c, d, a, k[6], 23, 76029189); + a = hh(a, b, c, d, k[9], 4, -640364487); + d = hh(d, a, b, c, k[12], 11, -421815835); + c = hh(c, d, a, b, k[15], 16, 530742520); + b = hh(b, c, d, a, k[2], 23, -995338651); + + a = ii(a, b, c, d, k[0], 6, -198630844); + d = ii(d, a, b, c, k[7], 10, 1126891415); + c = ii(c, d, a, b, k[14], 15, -1416354905); + b = ii(b, c, d, a, k[5], 21, -57434055); + a = ii(a, b, c, d, k[12], 6, 1700485571); + d = ii(d, a, b, c, k[3], 10, -1894986606); + c = ii(c, d, a, b, k[10], 15, -1051523); + b = ii(b, c, d, a, k[1], 21, -2054922799); + a = ii(a, b, c, d, k[8], 6, 1873313359); + d = ii(d, a, b, c, k[15], 10, -30611744); + c = ii(c, d, a, b, k[6], 15, -1560198380); + b = ii(b, c, d, a, k[13], 21, 1309151649); + a = ii(a, b, c, d, k[4], 6, -145523070); + d = ii(d, a, b, c, k[11], 10, -1120210379); + c = ii(c, d, a, b, k[2], 15, 718787259); + b = ii(b, c, d, a, k[9], 21, -343485551); + + x[0] = add32(a, x[0]); + x[1] = add32(b, x[1]); + x[2] = add32(c, x[2]); + x[3] = add32(d, x[3]); + }, + + /* there needs to be support for Unicode here, + * unless we pretend that we can redefine the MD-5 + * algorithm for multi-byte characters (perhaps + * by adding every four 16-bit characters and + * shortening the sum to 32 bits). Otherwise + * I suggest performing MD-5 as if every character + * was two bytes--e.g., 0040 0025 = @%--but then + * how will an ordinary MD-5 sum be matched? + * There is no way to standardize text to something + * like UTF-8 before transformation; speed cost is + * utterly prohibitive. The JavaScript standard + * itself needs to look at this: it should start + * providing access to strings as preformed UTF-8 + * 8-bit unsigned value arrays. + */ + md5blk = function (s) { + var md5blks = [], + i; /* Andy King said do it this way. */ + + for (i = 0; i < 64; i += 4) { + md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); + } + return md5blks; + }, + + md5blk_array = function (a) { + var md5blks = [], + i; /* Andy King said do it this way. */ + + for (i = 0; i < 64; i += 4) { + md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24); + } + return md5blks; + }, + + md51 = function (s) { + var n = s.length, + state = [1732584193, -271733879, -1732584194, 271733878], + i, + length, + tail, + tmp, + lo, + hi; + + for (i = 64; i <= n; i += 64) { + md5cycle(state, md5blk(s.substring(i - 64, i))); + } + s = s.substring(i - 64); + length = s.length; + tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3); + } + tail[i >> 2] |= 0x80 << ((i % 4) << 3); + if (i > 55) { + md5cycle(state, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + + // Beware that the final length might not fit in 32 bits so we take care of that + tmp = n * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + + tail[14] = lo; + tail[15] = hi; + + md5cycle(state, tail); + return state; + }, + + md51_array = function (a) { + var n = a.length, + state = [1732584193, -271733879, -1732584194, 271733878], + i, + length, + tail, + tmp, + lo, + hi; + + for (i = 64; i <= n; i += 64) { + md5cycle(state, md5blk_array(a.subarray(i - 64, i))); + } + + // Not sure if it is a bug, however IE10 will always produce a sub array of length 1 + // containing the last element of the parent array if the sub array specified starts + // beyond the length of the parent array - weird. + // https://connect.microsoft.com/IE/feedback/details/771452/typed-array-subarray-issue + a = (i - 64) < n ? a.subarray(i - 64) : new Uint8Array(0); + + length = a.length; + tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= a[i] << ((i % 4) << 3); + } + + tail[i >> 2] |= 0x80 << ((i % 4) << 3); + if (i > 55) { + md5cycle(state, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + + // Beware that the final length might not fit in 32 bits so we take care of that + tmp = n * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + + tail[14] = lo; + tail[15] = hi; + + md5cycle(state, tail); + + return state; + }, + + hex_chr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'], + + rhex = function (n) { + var s = '', + j; + for (j = 0; j < 4; j += 1) { + s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]; + } + return s; + }, + + hex = function (x) { + var i; + for (i = 0; i < x.length; i += 1) { + x[i] = rhex(x[i]); + } + return x.join(''); + }, + + md5 = function (s) { + return hex(md51(s)); + }, + + + + //////////////////////////////////////////////////////////////////////////// + + /** + * SparkMD5 OOP implementation. + * + * Use this class to perform an incremental md5, otherwise use the + * static methods instead. + */ + SparkMD5 = function () { + // call reset to init the instance + this.reset(); + }; + + + // In some cases the fast add32 function cannot be used.. + if (md5('hello') !== '5d41402abc4b2a76b9719d911017c592') { + add32 = function (x, y) { + var lsw = (x & 0xFFFF) + (y & 0xFFFF), + msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xFFFF); + }; + } + + + /** + * Appends a string. + * A conversion will be applied if an utf8 string is detected. + * + * @param {String} str The string to be appended + * + * @return {SparkMD5} The instance itself + */ + SparkMD5.prototype.append = function (str) { + // converts the string to utf8 bytes if necessary + if (/[\u0080-\uFFFF]/.test(str)) { + str = unescape(encodeURIComponent(str)); + } + + // then append as binary + this.appendBinary(str); + + return this; + }; + + /** + * Appends a binary string. + * + * @param {String} contents The binary string to be appended + * + * @return {SparkMD5} The instance itself + */ + SparkMD5.prototype.appendBinary = function (contents) { + this._buff += contents; + this._length += contents.length; + + var length = this._buff.length, + i; + + for (i = 64; i <= length; i += 64) { + md5cycle(this._state, md5blk(this._buff.substring(i - 64, i))); + } + + this._buff = this._buff.substr(i - 64); + + return this; + }; + + /** + * Finishes the incremental computation, reseting the internal state and + * returning the result. + * Use the raw parameter to obtain the raw result instead of the hex one. + * + * @param {Boolean} raw True to get the raw result, false to get the hex result + * + * @return {String|Array} The result + */ + SparkMD5.prototype.end = function (raw) { + var buff = this._buff, + length = buff.length, + i, + tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + ret; + + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= buff.charCodeAt(i) << ((i % 4) << 3); + } + + this._finish(tail, length); + ret = !!raw ? this._state : hex(this._state); + + this.reset(); + + return ret; + }; + + /** + * Finish the final calculation based on the tail. + * + * @param {Array} tail The tail (will be modified) + * @param {Number} length The length of the remaining buffer + */ + SparkMD5.prototype._finish = function (tail, length) { + var i = length, + tmp, + lo, + hi; + + tail[i >> 2] |= 0x80 << ((i % 4) << 3); + if (i > 55) { + md5cycle(this._state, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + + // Do the final computation based on the tail and length + // Beware that the final length may not fit in 32 bits so we take care of that + tmp = this._length * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + + tail[14] = lo; + tail[15] = hi; + md5cycle(this._state, tail); + }; + + /** + * Resets the internal state of the computation. + * + * @return {SparkMD5} The instance itself + */ + SparkMD5.prototype.reset = function () { + this._buff = ""; + this._length = 0; + this._state = [1732584193, -271733879, -1732584194, 271733878]; + + return this; + }; + + /** + * Releases memory used by the incremental buffer and other aditional + * resources. If you plan to use the instance again, use reset instead. + */ + SparkMD5.prototype.destroy = function () { + delete this._state; + delete this._buff; + delete this._length; + }; + + + /** + * Performs the md5 hash on a string. + * A conversion will be applied if utf8 string is detected. + * + * @param {String} str The string + * @param {Boolean} raw True to get the raw result, false to get the hex result + * + * @return {String|Array} The result + */ + SparkMD5.hash = function (str, raw) { + // converts the string to utf8 bytes if necessary + if (/[\u0080-\uFFFF]/.test(str)) { + str = unescape(encodeURIComponent(str)); + } + + var hash = md51(str); + + return !!raw ? hash : hex(hash); + }; + + /** + * Performs the md5 hash on a binary string. + * + * @param {String} content The binary string + * @param {Boolean} raw True to get the raw result, false to get the hex result + * + * @return {String|Array} The result + */ + SparkMD5.hashBinary = function (content, raw) { + var hash = md51(content); + + return !!raw ? hash : hex(hash); + }; + + /** + * SparkMD5 OOP implementation for array buffers. + * + * Use this class to perform an incremental md5 ONLY for array buffers. + */ + SparkMD5.ArrayBuffer = function () { + // call reset to init the instance + this.reset(); + }; + + //////////////////////////////////////////////////////////////////////////// + + /** + * Appends an array buffer. + * + * @param {ArrayBuffer} arr The array to be appended + * + * @return {SparkMD5.ArrayBuffer} The instance itself + */ + SparkMD5.ArrayBuffer.prototype.append = function (arr) { + // TODO: we could avoid the concatenation here but the algorithm would be more complex + // if you find yourself needing extra performance, please make a PR. + var buff = this._concatArrayBuffer(this._buff, arr), + length = buff.length, + i; + + this._length += arr.byteLength; + + for (i = 64; i <= length; i += 64) { + md5cycle(this._state, md5blk_array(buff.subarray(i - 64, i))); + } + + // Avoids IE10 weirdness (documented above) + this._buff = (i - 64) < length ? buff.subarray(i - 64) : new Uint8Array(0); + + return this; + }; + + /** + * Finishes the incremental computation, reseting the internal state and + * returning the result. + * Use the raw parameter to obtain the raw result instead of the hex one. + * + * @param {Boolean} raw True to get the raw result, false to get the hex result + * + * @return {String|Array} The result + */ + SparkMD5.ArrayBuffer.prototype.end = function (raw) { + var buff = this._buff, + length = buff.length, + tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + i, + ret; + + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= buff[i] << ((i % 4) << 3); + } + + this._finish(tail, length); + ret = !!raw ? this._state : hex(this._state); + + this.reset(); + + return ret; + }; + + SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish; + + /** + * Resets the internal state of the computation. + * + * @return {SparkMD5.ArrayBuffer} The instance itself + */ + SparkMD5.ArrayBuffer.prototype.reset = function () { + this._buff = new Uint8Array(0); + this._length = 0; + this._state = [1732584193, -271733879, -1732584194, 271733878]; + + return this; + }; + + /** + * Releases memory used by the incremental buffer and other aditional + * resources. If you plan to use the instance again, use reset instead. + */ + SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy; + + /** + * Concats two array buffers, returning a new one. + * + * @param {ArrayBuffer} first The first array buffer + * @param {ArrayBuffer} second The second array buffer + * + * @return {ArrayBuffer} The new array buffer + */ + SparkMD5.ArrayBuffer.prototype._concatArrayBuffer = function (first, second) { + var firstLength = first.length, + result = new Uint8Array(firstLength + second.byteLength); + + result.set(first); + result.set(new Uint8Array(second), firstLength); + + return result; + }; + + /** + * Performs the md5 hash on an array buffer. + * + * @param {ArrayBuffer} arr The array buffer + * @param {Boolean} raw True to get the raw result, false to get the hex result + * + * @return {String|Array} The result + */ + SparkMD5.ArrayBuffer.hash = function (arr, raw) { + var hash = md51_array(new Uint8Array(arr)); + + return !!raw ? hash : hex(hash); + }; + + return SparkMD5; +})); + +},{}],118:[function(_dereq_,module,exports){ +module.exports=_dereq_(26) +},{"./_stream_readable":119,"./_stream_writable":121,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_duplex.js":26,"_process":24,"core-util-is":122,"inherits":44}],119:[function(_dereq_,module,exports){ +module.exports=_dereq_(28) +},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_readable.js":28,"_process":24,"buffer":17,"core-util-is":122,"events":21,"inherits":44,"isarray":123,"stream":36,"string_decoder/":124}],120:[function(_dereq_,module,exports){ +module.exports=_dereq_(29) +},{"./_stream_duplex":118,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_transform.js":29,"core-util-is":122,"inherits":44}],121:[function(_dereq_,module,exports){ +module.exports=_dereq_(30) +},{"./_stream_duplex":118,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_writable.js":30,"_process":24,"buffer":17,"core-util-is":122,"inherits":44,"stream":36}],122:[function(_dereq_,module,exports){ +module.exports=_dereq_(31) +},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/node_modules/core-util-is/lib/util.js":31,"buffer":17}],123:[function(_dereq_,module,exports){ +module.exports=_dereq_(22) +},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/isarray/index.js":22}],124:[function(_dereq_,module,exports){ +module.exports=_dereq_(37) +},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/string_decoder/index.js":37,"buffer":17}],125:[function(_dereq_,module,exports){ +module.exports=_dereq_(34) +},{"./lib/_stream_transform.js":120,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/transform.js":34}],126:[function(_dereq_,module,exports){ +module.exports=_dereq_(54) +},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/has-keys.js":54}],127:[function(_dereq_,module,exports){ +module.exports=_dereq_(55) +},{"./has-keys":126,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/index.js":55,"object-keys":129}],128:[function(_dereq_,module,exports){ +module.exports=_dereq_(56) +},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/foreach.js":56}],129:[function(_dereq_,module,exports){ +module.exports=_dereq_(57) +},{"./shim":131,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/index.js":57}],130:[function(_dereq_,module,exports){ +module.exports=_dereq_(58) +},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/isArguments.js":58}],131:[function(_dereq_,module,exports){ +module.exports=_dereq_(59) +},{"./foreach":128,"./isArguments":130,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/shim.js":59}],132:[function(_dereq_,module,exports){ +var Transform = _dereq_('readable-stream/transform') + , inherits = _dereq_('util').inherits + , xtend = _dereq_('xtend') + + +// a noop _transform function +function noop (chunk, enc, callback) { + callback(null, chunk) +} + + +// create a new export function, used by both the main export and +// the .ctor export, contains common logic for dealing with arguments +function through2 (construct) { + return function (options, transform, flush) { + if (typeof options == 'function') { + flush = transform + transform = options + options = {} + } + + if (typeof transform != 'function') + transform = noop + + if (typeof flush != 'function') + flush = null + + return construct(options, transform, flush) + } +} + + +// main export, just make me a transform stream! +module.exports = through2(function (options, transform, flush) { + var t2 = new Transform(options) + + t2._transform = transform + + if (flush) + t2._flush = flush + + return t2 +}) + + +// make me a reusable prototype that I can `new`, or implicitly `new` +// with a constructor call +module.exports.ctor = through2(function (options, transform, flush) { + function Through2 (override) { + if (!(this instanceof Through2)) + return new Through2(override) + + this.options = xtend(options, override) + + Transform.call(this, this.options) + } + + inherits(Through2, Transform) + + Through2.prototype._transform = transform + + if (flush) + Through2.prototype._flush = flush + + return Through2 +}) + + +module.exports.obj = through2(function (options, transform, flush) { + var t2 = new Transform(xtend({ objectMode: true }, options)) + + t2._transform = transform + + if (flush) + t2._flush = flush + + return t2 +}) + +},{"readable-stream/transform":125,"util":39,"xtend":127}],133:[function(_dereq_,module,exports){ +'use strict'; + +/** + * Stringify/parse functions that don't operate + * recursively, so they avoid call stack exceeded + * errors. + */ +exports.stringify = function stringify(input) { + var queue = []; + queue.push({obj: input}); + + var res = ''; + var next, obj, prefix, val, i, arrayPrefix, keys, k, key, value, objPrefix; + while ((next = queue.pop())) { + obj = next.obj; + prefix = next.prefix || ''; + val = next.val || ''; + res += prefix; + if (val) { + res += val; + } else if (typeof obj !== 'object') { + res += typeof obj === 'undefined' ? null : JSON.stringify(obj); + } else if (obj === null) { + res += 'null'; + } else if (Array.isArray(obj)) { + queue.push({val: ']'}); + for (i = obj.length - 1; i >= 0; i--) { + arrayPrefix = i === 0 ? '' : ','; + queue.push({obj: obj[i], prefix: arrayPrefix}); + } + queue.push({val: '['}); + } else { // object + keys = []; + for (k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + queue.push({val: '}'}); + for (i = keys.length - 1; i >= 0; i--) { + key = keys[i]; + value = obj[key]; + objPrefix = (i > 0 ? ',' : ''); + objPrefix += JSON.stringify(key) + ':'; + queue.push({obj: value, prefix: objPrefix}); + } + queue.push({val: '{'}); + } + } + return res; +}; + +// Convenience function for the parse function. +// This pop function is basically copied from +// pouchCollate.parseIndexableString +function pop(obj, stack, metaStack) { + var lastMetaElement = metaStack[metaStack.length - 1]; + if (obj === lastMetaElement.element) { + // popping a meta-element, e.g. an object whose value is another object + metaStack.pop(); + lastMetaElement = metaStack[metaStack.length - 1]; + } + var element = lastMetaElement.element; + var lastElementIndex = lastMetaElement.index; + if (Array.isArray(element)) { + element.push(obj); + } else if (lastElementIndex === stack.length - 2) { // obj with key+value + var key = stack.pop(); + element[key] = obj; + } else { + stack.push(obj); // obj with key only + } +} + +exports.parse = function (str) { + var stack = []; + var metaStack = []; // stack for arrays and objects + var i = 0; + var collationIndex,parsedNum,numChar; + var parsedString,lastCh,numConsecutiveSlashes,ch; + var arrayElement, objElement; + while (true) { + collationIndex = str[i++]; + if (collationIndex === '}' || + collationIndex === ']' || + typeof collationIndex === 'undefined') { + if (stack.length === 1) { + return stack.pop(); + } else { + pop(stack.pop(), stack, metaStack); + continue; + } + } + switch (collationIndex) { + case ' ': + case '\t': + case '\n': + case ':': + case ',': + break; + case 'n': + i += 3; // 'ull' + pop(null, stack, metaStack); + break; + case 't': + i += 3; // 'rue' + pop(true, stack, metaStack); + break; + case 'f': + i += 4; // 'alse' + pop(false, stack, metaStack); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + parsedNum = ''; + i--; + while (true) { + numChar = str[i++]; + if (/[\d\.\-e\+]/.test(numChar)) { + parsedNum += numChar; + } else { + i--; + break; + } + } + pop(parseFloat(parsedNum), stack, metaStack); + break; + case '"': + parsedString = ''; + lastCh = void 0; + numConsecutiveSlashes = 0; + while (true) { + ch = str[i++]; + if (ch !== '"' || (lastCh === '\\' && + numConsecutiveSlashes % 2 === 1)) { + parsedString += ch; + lastCh = ch; + if (lastCh === '\\') { + numConsecutiveSlashes++; + } else { + numConsecutiveSlashes = 0; + } + } else { + break; + } + } + pop(JSON.parse('"' + parsedString + '"'), stack, metaStack); + break; + case '[': + arrayElement = { element: [], index: stack.length }; + stack.push(arrayElement.element); + metaStack.push(arrayElement); + break; + case '{': + objElement = { element: {}, index: stack.length }; + stack.push(objElement.element); + metaStack.push(objElement); + break; + default: + throw new Error( + 'unexpectedly reached end of input: ' + collationIndex); + } + } +}; + +},{}],"adapter-config":[function(_dereq_,module,exports){ +(function (global){ +'use strict'; + +module.exports = { + name: 'idb-alt', + valid: function () { + var PouchDB = global.PouchDB || _dereq_('pouchdb'); + return 'idb' in PouchDB.adapters && + PouchDB.adapters.idb.valid(); + }, + use_prefix: true +}; +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"pouchdb":"pouchdb"}],"leveldown":[function(_dereq_,module,exports){ +(function (Buffer){ +module.exports = Level + +var IDB = _dereq_('idb-wrapper') +var AbstractLevelDOWN = _dereq_('abstract-leveldown').AbstractLevelDOWN +var util = _dereq_('util') +var Iterator = _dereq_('./iterator') +var isBuffer = _dereq_('isbuffer') +var xtend = _dereq_('xtend') +var toBuffer = _dereq_('typedarray-to-buffer') + +function Level(location) { + if (!(this instanceof Level)) return new Level(location) + if (!location) throw new Error("constructor requires at least a location argument") + this.IDBOptions = {} + this.location = location +} + +util.inherits(Level, AbstractLevelDOWN) + +Level.prototype._open = function(options, callback) { + var self = this + + var idbOpts = { + storeName: this.location, + autoIncrement: false, + keyPath: null, + onStoreReady: function () { + callback && callback(null, self.idb) + }, + onError: function(err) { + callback && callback(err) + } + } + + xtend(idbOpts, options) + this.IDBOptions = idbOpts + this.idb = new IDB(idbOpts) +} + +Level.prototype._get = function (key, options, callback) { + this.idb.get(key, function (value) { + if (value === undefined) { + // 'NotFound' error, consistent with LevelDOWN API + return callback(new Error('NotFound')) + } + // by default return buffers, unless explicitly told not to + var asBuffer = true + if (options.asBuffer === false) asBuffer = false + if (options.raw) asBuffer = false + if (asBuffer) { + if (value instanceof Uint8Array) value = toBuffer(value) + else value = new Buffer(String(value)) + } + return callback(null, value, key) + }, callback) +} + +Level.prototype._del = function(id, options, callback) { + this.idb.remove(id, callback, callback) +} + +Level.prototype._put = function (key, value, options, callback) { + if (value instanceof ArrayBuffer) { + value = toBuffer(new Uint8Array(value)) + } + var obj = this.convertEncoding(key, value, options) + if (Buffer.isBuffer(obj.value)) { + obj.value = new Uint8Array(value.toArrayBuffer()) + } + this.idb.put(obj.key, obj.value, function() { callback() }, callback) +} + +Level.prototype.convertEncoding = function(key, value, options) { + if (options.raw) return {key: key, value: value} + if (value) { + var stringed = value.toString() + if (stringed === 'NaN') value = 'NaN' + } + var valEnc = options.valueEncoding + var obj = {key: key, value: value} + if (value && (!valEnc || valEnc !== 'binary')) { + if (typeof obj.value !== 'object') { + obj.value = stringed + } + } + return obj +} + +Level.prototype.iterator = function (options) { + if (typeof options !== 'object') options = {} + return new Iterator(this.idb, options) +} + +Level.prototype._batch = function (array, options, callback) { + var op + var i + var k + var copiedOp + var currentOp + var modified = [] + + if (array.length === 0) return setTimeout(callback, 0) + + for (i = 0; i < array.length; i++) { + copiedOp = {} + currentOp = array[i] + modified[i] = copiedOp + + var converted = this.convertEncoding(currentOp.key, currentOp.value, options) + currentOp.key = converted.key + currentOp.value = converted.value + + for (k in currentOp) { + if (k === 'type' && currentOp[k] == 'del') { + copiedOp[k] = 'remove' + } else { + copiedOp[k] = currentOp[k] + } + } + } + + return this.idb.batch(modified, function(){ callback() }, callback) +} + +Level.prototype._close = function (callback) { + this.idb.db.close() + callback() +} + +Level.prototype._approximateSize = function (start, end, callback) { + var err = new Error('Not implemented') + if (callback) + return callback(err) + + throw err +} + +Level.prototype._isBuffer = function (obj) { + return Buffer.isBuffer(obj) +} + +Level.destroy = function (db, callback) { + if (typeof db === 'object') { + var prefix = db.IDBOptions.storePrefix || 'IDBWrapper-' + var dbname = db.location + } else { + var prefix = 'IDBWrapper-' + var dbname = db + } + var request = indexedDB.deleteDatabase(prefix + dbname) + request.onsuccess = function() { + callback() + } + request.onerror = function(err) { + callback(err) + } +} + +var checkKeyValue = Level.prototype._checkKeyValue = function (obj, type) { + if (obj === null || obj === undefined) + return new Error(type + ' cannot be `null` or `undefined`') + if (obj === null || obj === undefined) + return new Error(type + ' cannot be `null` or `undefined`') + if (isBuffer(obj) && obj.byteLength === 0) + return new Error(type + ' cannot be an empty ArrayBuffer') + if (String(obj) === '') + return new Error(type + ' cannot be an empty String') + if (obj.length === 0) + return new Error(type + ' cannot be an empty Array') +} + +}).call(this,_dereq_("buffer").Buffer) +},{"./iterator":45,"abstract-leveldown":48,"buffer":17,"idb-wrapper":50,"isbuffer":51,"typedarray-to-buffer":53,"util":39,"xtend":55}]},{},[11]); +
diff --git a/dist/pouchdb.idb-alt.min.js b/dist/pouchdb.idb-alt.min.js new file mode 100644 index 0000000..30b5412 --- /dev/null +++ b/dist/pouchdb.idb-alt.min.js
@@ -0,0 +1,13 @@ +// PouchDB alternative IndexedDB plugin 3.2.0 +// Based on level.js: https://github.com/maxogden/level.js +// +// (c) 2012-2014 Dale Harvey and the PouchDB team +// PouchDB may be freely distributed under the Apache license, version 2.0. +// For all details and documentation: +// http://pouchdb.com +require=function e(t,r,n){function o(s,a){if(!r[s]){if(!t[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(i)return i(s,!0);var c=new Error("Cannot find module '"+s+"'");throw c.code="MODULE_NOT_FOUND",c}var f=r[s]={exports:{}};t[s][0].call(f.exports,function(e){var r=t[s][1][e];return o(r?r:e)},f,f.exports,e,t,r,n)}return r[s].exports}for(var i="function"==typeof require&&require,s=0;s<n.length;s++)o(n[s]);return o}({"./lib/deps/migrate":[function(e,t,r){(function(e){"use strict";r.toSublevel=function(t,r,n){e.nextTick(function(){n()})},r.localAndMetaStores=function(t,r,n){e.nextTick(function(){n()})}}).call(this,e("_process"))},{_process:24}],1:[function(e,t){(function(r,n){"use strict";function o(e,t){return h.Promise.all(e.map(function(e){if(e.doc&&e.doc._attachments){var r=Object.keys(e.doc._attachments);return h.Promise.all(r.map(function(r){var n=e.doc._attachments[r];if(!("data"in n))return new h.Promise(function(o,i){t.binaryStore.get(n.digest,function(t,s){var a="";return t&&"NotFoundError"!==t.name?i(t):(t||(a=h.btoa(s)),e.doc._attachments[r]=h.extend(h.pick(n,["digest","content_type"]),{data:a}),void o())})})}))}}))}function i(e){var t=h.filterChange(e),r=e.doc_ids&&new h.Set(e.doc_ids);return function(e){return r&&!r.has(e.id)?!1:t(e)}}function s(e,t){function v(){q.docStore=U.sublevel(g,{valueEncoding:R}),q.bySeqStore=U.sublevel(m,{valueEncoding:"json"}),q.attachmentStore=U.sublevel(b,{valueEncoding:"json"}),q.binaryStore=U.sublevel(_,{valueEncoding:"binary"}),q.localStore=U.sublevel(w,{valueEncoding:"json"}),q.metaStore=U.sublevel(E,{valueEncoding:"json"}),p.localAndMetaStores(U,q,function(){q.metaStore.get(S,function(e,n){"undefined"==typeof U._updateSeq&&(U._updateSeq=n||0),q.metaStore.get(A,function(e,n){U._docCountQueue.docCount=e?0:n,I(function(e){e&&M.emit("error",e),q.metaStore.get(j,function(e,n){P=e?h.uuid():n,q.metaStore.put(j,P,function(){r.nextTick(function(){t(null,M)})})})})})})})}function I(e){return U._docCountQueue.running||!U._docCountQueue.queue.length||-1===U._docCountQueue.docCount?T(0,e):U._docCountQueue.docCount}function N(){if(!U._docCountQueue.running&&U._docCountQueue.queue.length&&-1!==U._docCountQueue.docCount){U._docCountQueue.running=!0;var e=U._docCountQueue.queue.shift();return U.isClosed()?e.callback(new Error("database is closed")):void q.metaStore.get(A,function(t,r){function n(t){U._docCountQueue.docCount=r,e.callback(t,r),U._docCountQueue.running=!1,N()}r=t?0:r,0===e.delta?n():q.metaStore.put(A,r+e.delta,n)})}}function T(e,t){U._docCountQueue.queue.push({delta:e,callback:t}),N()}function L(e){return h.getArguments(function(t){var n=t[t.length-1];t[t.length-1]=h.getArguments(function(e){n.apply(null,e),r.nextTick(function(){U._writeQueue.shift(),U._writeQueue.length&&U._writeQueue.peekFront()()})}),U._writeQueue.push(function(){e.apply(null,t)}),1===U._writeQueue.length&&U._writeQueue.peekFront()()})}function D(e){return("0000000000000000"+e).slice(-16)}function B(e){return parseInt(e,10)}function C(e,t){var r=e.data;if(r._id=e.metadata.id,"_rev"in r){if(r._rev!==e.metadata.rev)return t(new Error("wrong doc returned"))}else r._rev=e.metadata.rev;t(null,{doc:r,metadata:e.metadata})}e=h.clone(e);var P,U,M=this,q={},F=e.name;"undefined"==typeof e.createIfMissing&&(e.createIfMissing=!0);var V=e.db||u;"function"!=typeof V.destroy&&(V.destroy=function(e,t){t()});var W;k.has(V.name)?W=k.get(V.name):(W=new h.Map,k.set(V.name,W)),W.has(F)?(U=W.get(F),v()):W.set(F,c(a(F,e,function(r){return r?(W["delete"](F),t(r)):(U=W.get(F),U._docCountQueue={queue:[],running:!1,docCount:-1},U._writeQueue=new y,void(e.db||e.noMigrate?v():p.toSublevel(F,U,v)))}))),M.type=function(){return"leveldb"},M._id=function(e){e(null,P)},M._info=function(e){I(function(t,r){return t?e(t):void q.metaStore.get(S,function(t,n){return t&&(n=U._updateSeq),e(null,{doc_count:r,update_seq:n})})})},M._get=function(e,t,r){function n(e){o.push(e)}t=h.clone(t);var o=[];U.on("pouchdb-id-"+e,n),q.docStore.get(e,function(i,s){function a(e){u=e}if(U.removeListener("pouchdb-id-"+e,n),i||!s)return r(l.MISSING_DOC);if(h.isDeleted(s)&&!t.rev)return r(l.error(l.MISSING_DOC,"deleted"));var u,c=d.winningRev(s);c=t.rev?t.rev:c;var f=s.rev_map[c],p=o.filter(function(e){return e.metadata.seq===f});return p.length?C(p.pop(),r):(U.on("pouchdb-"+f,a),void q.bySeqStore.get(D(f),function(e,t){if(U.removeListener("pouchdb-"+f,a),u)return C(u,r);if(!t)return r(l.MISSING_DOC);if("_id"in t&&t._id!==s.id)return r(new Error("wrong doc returned"));if(t._id=s.id,"_rev"in t){if(t._rev!==c)return r(new Error("wrong doc returned"))}else t._rev=c;return r(null,{doc:t,metadata:s})}))})},M._getAttachment=function(e,t,o){var i=e.digest;q.binaryStore.get(i,function(i,s){var a;return i&&"NotFoundError"===i.name?(a=t.encode?"":r.browser?h.createBlob([""],{type:e.content_type}):new n(""),o(null,a)):i?o(i):(a=r.browser?t.encode?h.btoa(s):h.createBlob([h.fixBinary(s)],{type:e.content_type}):t.encode?h.btoa(s):s,void o(null,a))})},M._bulkDocs=L(function(e,t,n){function o(e,t){q.attachmentStore.get(e,function(r){if(r){var n=new Error("unknown stub attachment with digest "+e);n.status=412,t(n)}else t()})}function i(e){function t(){++i===r.length&&e(n)}var r=[];if(_.forEach(function(e){e&&e._attachments&&Object.keys(e._attachments).forEach(function(t){var n=e._attachments[t];n.stub&&r.push(n.digest)})}),!r.length)return e();var n,i=0;r.forEach(function(e){o(e,function(e){e&&!n&&(n=e),t()})})}function a(){var e=E;if(!(A>x)){if(e>=w.length)return 0===A?y():void 0;var t=w[e];if(E++,A++,t._id&&h.isLocalId(t._id))return void M[t._deleted?"_removeLocalNoLock":"_putLocalNoLock"](t,function(t){m[e]=t?t:{},A--,a()});if(b.has(t.metadata.id))return m[e]=l.REV_CONFLICT,A--,a();b.add(t.metadata.id),q.docStore.get(t.metadata.id,function(r,n){r?"NotFoundError"===r.name?u(t,e,function(){b["delete"](t.metadata.id),A--,a()}):(r.error=!0,m[e]=r,b["delete"](t.metadata.id),A--,a()):c(n,t,e,function(){b["delete"](t.metadata.id),A--,a()})}),g&&a()}}function u(e,r,n){return"was_delete"in t&&h.isDeleted(e.metadata)?(m[r]=l.MISSING_DOC,n()):void f(e,r,function(t){return t?n(t):h.isDeleted(e.metadata)?n():void T(1,n)})}function c(e,t,r,n){if(h.revExists(e,t.metadata.rev))return m[r]=t,void n();var o=h.isDeleted(e),i=h.isDeleted(t.metadata),s=/^1-/.test(t.metadata.rev);if(o&&!i&&g&&s){var a=t.data;a._rev=e.rev,a._id=t.metadata.id,t=h.parseDoc(a,g)}var u=d.merge(e.rev_tree,t.metadata.rev_tree[0],1e3),c=g&&(o&&i||!o&&g&&"new_leaf"!==u.conflicts||o&&!i&&"new_branch"===u.conflicts);if(c)return m[r]=l.REV_CONFLICT,n();var p=t.metadata.rev;t.metadata.rev_tree=u.tree,t.metadata.rev_map=e.rev_map;var v=0;(g||d.winningRev(t.metadata)===p)&&(v=o===i?0:i>o?-1:1),T(v,function(e){return e?n(e):void f(t,r,n)})}function f(e,t,o){function i(e){f||(e?(f=e,o(f)):d===y.length&&c())}function s(e){d++,i(e)}function a(e,t,r,n){return function(o){v(e,O+o,t,r,n)}}function u(e,t,r){return function(n){h.MD5(n).then(a(e,t,n,r))}}function c(){var r=e.metadata.rev_map[e.metadata.rev];r||(r=++U._updateSeq),e.metadata.rev_map[e.metadata.rev]=e.metadata.seq=r;var n=D(r);U.emit("pouchdb-id-"+e.metadata.id,e),U.emit("pouchdb-"+n,e),U.batch([{key:n,value:e.data,prefix:q.bySeqStore,type:"put",valueEncoding:"json"},{key:e.metadata.id,value:e.metadata,prefix:q.docStore,type:"put",valueEncoding:R}],function(r){return r||(U.emit("pouchdb-id-"+e.metadata.id,e),U.emit("pouchdb-"+n,e)),q.metaStore.put(S,U._updateSeq,function(r){return m[t]=r?r:e,o()})})}var f=null,d=0;e.data._id=e.metadata.id,e.data._rev=e.metadata.rev,h.isDeleted(e.metadata)&&(e.data._deleted=!0);for(var y=e.data._attachments?Object.keys(e.data._attachments):[],g=0;g<y.length;g++){var b=y[g],_=e.data._attachments[b];if(_.stub){var w=e.data._id,E=e.data._rev;p(w,E,_.digest,s)}else{var x;if("string"==typeof _.data)try{x=h.atob(_.data)}catch(k){return void n(h.extend({},l.BAD_ARG,{reason:"Attachments need to be base64 encoded"}))}else{if(r.browser){h.readAsBinaryString(_.data,u(e,b,s));continue}x=_.data}h.MD5(x).then(a(e,b,x,s))}}y.length||c()}function p(e,t,r,n){function o(){return new h.Promise(function(e,t){q.attachmentStore.get(r,function(r,n){return r&&"NotFoundError"!==r.name?t(r):void e(n)})})}function i(n){var o=[e,t].join("@"),i={};return n?n.refs&&(i.refs=n.refs,i.refs[o]=!0):(i.refs={},i.refs[o]=!0),new h.Promise(function(e,t){q.attachmentStore.put(r,i,function(r){return r?t(r):void e(!n)})})}var s=j[r]||h.Promise.resolve();j[r]=s.then(function(){return o().then(i).then(function(e){n(null,e)},n)})}function v(e,t,r,n,o){var i=e.data._attachments[r];delete i.data,i.digest=t,i.length=n.length;var s=e.metadata.id,a=e.metadata.rev;p(s,a,t,function(e,r){return e?o(e):0===n.length?o(e):r?void q.binaryStore.put(t,n,function(e){o(e)}):o(e)})}function y(){var e=m.map(function(e){if(!Object.keys(e).length)return{ok:!0};if(e.error)return e;var t=e.metadata,r=d.winningRev(t);return{ok:!0,id:t.id,rev:r}});s.Changes.notify(F),r.nextTick(function(){n(null,e)})}var g=t.new_edits,m=new Array(e.docs.length),b=new h.Set,_=e.docs,w=_.map(function(e){if(e._id&&h.isLocalId(e._id))return e;var t=h.parseDoc(e,g);return t.metadata&&!t.metadata.rev_map&&(t.metadata.rev_map={}),t}),E=0,k=w.filter(function(e){return e.error});if(k.length)return n(k[0]);var A=0,j={};i(function(e){return e?n(e):void a()})}),M._allDocs=function(e,t){e=h.clone(e),I(function(r,n){if(r)return t(r);var i={},s=e.skip||0;if(e.startkey&&(i.start=e.startkey),e.endkey&&(i.end=e.endkey),e.key&&(i.start=i.end=e.key),e.descending){i.reverse=!0;var a=i.start;i.start=i.end,i.end=a}var u;if(u="number"==typeof e.limit?e.limit:-1,0===u||"start"in i&&"end"in i&&i.start>i.end)return t(null,{total_rows:n,offset:e.skip,rows:[]});var c=[],l=q.docStore.readStream(i),p=f(function(t,r,n){function o(t,r){var o={id:t.id,key:t.id,value:{rev:d.winningRev(t)}};if(e.include_docs){o.doc=r,o.doc._rev=o.value.rev,e.conflicts&&(o.doc._conflicts=d.collectConflicts(t));for(var i in o.doc._attachments)o.doc._attachments.hasOwnProperty(i)&&(o.doc._attachments[i].stub=!0)}if(e.inclusive_end===!1&&t.id===e.endkey)return n();if(h.isDeleted(t)){if("ok"!==e.deleted)return n();o.value.deleted=!0,o.doc=null}c.push(o),n()}if(h.isDeleted(t.value)){if("ok"!==e.deleted)return void n()}else{if(s-->0)return void n();if(0===u--)return l.unpipe(),l.destroy(),void n()}var i=t.value;if(e.include_docs){var a=i.rev_map[d.winningRev(i)];q.bySeqStore.get(D(a),function(e,t){o(i,t)})}else o(i)},function(r){h.Promise.resolve().then(function(){return e.attachments&&o(c,q)}).then(function(){t(null,{total_rows:n,offset:e.skip,rows:c})},t),r()}).on("unpipe",function(){p.end()});l.on("error",t),l.pipe(p)})},M._changes=function(e){function t(){e.done=!0,v&&e.limit&&e.limit<u.length&&(u.length=e.limit),g.unpipe(m),g.destroy(),e.continuous||e.cancelled||h.Promise.resolve().then(function(){return e.include_docs&&e.attachments?o(u,q):void 0}).then(function(){e.complete(null,{results:u,last_seq:c})})}if(e=h.clone(e),e.continuous){var r=F+":"+h.uuid();return s.Changes.addListener(F,r,M,e),s.Changes.notify(F),{cancel:function(){s.Changes.removeListener(F,r)}}}var n,a=e.descending,u=[],c=0,l=0,p={reverse:a};"limit"in e&&e.limit>0&&(n=e.limit),p.reverse||(p.start=D(e.since?e.since+1:0));var v,y=i(e);v="returnDocs"in e?e.returnDocs:!0;var g=q.bySeqStore.readStream(p),m=f(function(r,i,s){return n&&l>=n?(t(),s()):e.cancelled||e.done?s():void q.docStore.get(r.value._id,function(t,n){if(e.cancelled||e.done||U.isClosed()||h.isLocalId(n.id))return s();var i=r.value;i._rev=d.winningRev(n);var a=e.processChange(i,n,e);a.seq=n.seq,c<n.seq&&(c=n.seq),B(r.key)===n.rev_map[a.doc._rev]&&y(a)&&(l++,e.attachments&&e.include_docs?o([a],q).then(function(){e.onChange(a)}):e.onChange(a),v&&u.push(a)),s()})},function(t){return e.cancelled?t():(v&&e.limit&&e.limit<u.length&&(u.length=e.limit),void t())}).on("unpipe",function(){m.end(),t()});return g.pipe(m),{cancel:function(){e.cancelled=!0,t()}}},M._close=function(e){return U.isClosed()?e(l.NOT_OPEN):void U.close(function(t){t?e(t):(W["delete"](F),e())})},M._getRevisionTree=function(e,t){q.docStore.get(e,function(e,r){e?t(l.MISSING_DOC):t(null,r.rev_tree)})},M._doCompaction=L(function(e,t,r){return t.length?void q.docStore.get(e,function(n,o){function i(e){if(e&&(f=e),++p===t.length){if(f)return r(e);a()}}function s(e){return e?r(e):void U.batch(c,r)}function a(){function r(e){e&&(o=e),++i===n.length&&s(o)}var n=Object.keys(l);if(!n.length)return s();var o,i=0,a=new h.Map;t.forEach(function(t){a.set(e+"@"+t,!0)}),n.forEach(function(e){q.attachmentStore.get(e,function(t,n){if(t)return"NotFoundError"===t.name?r():r(t);var o=Object.keys(n.refs||{}).filter(function(e){return!a.has(e)}),i={};o.forEach(function(e){i[e]=!0}),o.length?c.push({key:e,type:"put",valueEncoding:"json",value:{refs:i},prefix:q.attachmentStore}):c=c.concat([{key:e,type:"del",prefix:q.attachmentStore},{key:e,type:"del",prefix:q.binaryStore}]),r()})})}if(n)return r(n);var u=o.rev_map;d.traverseRevTree(o.rev_tree,function(e,r,n,o,i){var s=r+"-"+n;-1!==t.indexOf(s)&&(i.status="missing")});var c=[];c.push({key:o.id,value:o,type:"put",valueEncoding:R,prefix:q.docStore});var f,l={},p=0;t.forEach(function(e){var t=u[e];t&&(c.push({key:D(t),type:"del",prefix:q.bySeqStore}),q.bySeqStore.get(D(t),function(e,t){if(e)return"NotFoundError"===e.name?i():i(e);var r=Object.keys(t._attachments||{});r.forEach(function(e){var r=t._attachments[e].digest;l[r]=!0}),i()}))})}):r()}),M._getLocal=function(e,t){q.localStore.get(e,function(e,r){e?t(l.MISSING_DOC):t(null,r)})},M._putLocal=L(function(e,t){M._putLocalNoLock(e,t)}),M._putLocalNoLock=function(e,t){delete e._revisions;var r=e._rev,n=e._id;q.localStore.get(n,function(o,i){return o&&r?t(l.REV_CONFLICT):i&&i._rev!==r?t(l.REV_CONFLICT):(e._rev=r?"0-"+(parseInt(r.split("-")[1],10)+1):"0-1",void q.localStore.put(n,e,function(r){if(r)return t(r);var n={ok:!0,id:e._id,rev:e._rev};t(null,n)}))})},M._removeLocal=L(function(e,t){M._removeLocalNoLock(e,t)}),M._removeLocalNoLock=function(e,t){q.localStore.get(e._id,function(r,n){return r?t(r):n._rev!==e._rev?t(l.REV_CONFLICT):void q.localStore.del(e._id,function(r){if(r)return t(r);var n={ok:!0,id:e._id,rev:"0-0"};t(null,n)})})}}var a=e("levelup"),u=e("leveldown"),c=e("level-sublevel"),f=e("through2").obj,l=e("../deps/errors"),d=e("../merge"),h=e("../utils"),p=e("../deps/migrate"),v=e("vuvuzela"),y=e("double-ended-queue"),g="document-store",m="by-sequence",b="attach-store",_="attach-binary-store",w="local-store",E="meta-store",x=50,k=new h.Map,S="_local_last_update_seq",A="_local_doc_count",j="_local_uuid",O="md5-",R={encode:v.stringify,decode:v.parse,buffer:!1,type:"cheap-json"};s.valid=function(){return r&&!r.browser},s.destroy=h.toPromise(function(e,t,n){function o(e,t){"function"==typeof a.destroy?a.destroy(e,t):r.nextTick(n)}t=h.clone(t);var i,a=t.db||u;return k.has(a.name)?(i=k.get(a.name),void(i.has(e)?(s.Changes.removeAllListeners(e),i.get(e).close(function(){i["delete"](e),o(e,n)})):o(e,n))):o(e,n)}),s.use_prefix=!1,s.Changes=new h.Changes,t.exports=s}).call(this,e("_process"),e("buffer").Buffer)},{"../deps/errors":5,"../deps/migrate":7,"../merge":10,"../utils":13,_process:24,buffer:17,"double-ended-queue":43,"level-sublevel":61,leveldown:"leveldown",levelup:75,through2:132,vuvuzela:133}],2:[function(e,t){"use strict";function r(e,t){function r(t,r,n){if(e.binary||e.json||!e.processData||"string"==typeof t){if(!e.binary&&e.json&&"string"==typeof t)try{t=JSON.parse(t)}catch(o){return n(o)}}else t=JSON.stringify(t);Array.isArray(t)&&(t=t.map(function(e){var t;return e.ok?e:e.error&&"conflict"===e.error?(t=i.REV_CONFLICT,t.id=e.id,t):e.error&&"forbidden"===e.error?(t=i.FORBIDDEN,t.id=e.id,t.reason=e.reason,t):e.missing?(t=i.MISSING_DOC,t.missing=e.missing,t):e})),n(null,t,r)}function a(e,t){var r,n,o,s;try{r=JSON.parse(e.responseText);for(s in i)if(i.hasOwnProperty(s)&&i[s].name===r.error){o=i[s];break}o||(o=i.UNKNOWN_ERROR,e.status&&(o.status=e.status),e.statusText&&(e.name=e.statusText)),n=i.error(o,r.reason)}catch(a){for(var s in i)if(i.hasOwnProperty(s)&&i[s].status===e.status){o=i[s];break}o||(o=i.UNKNOWN_ERROR,e.status&&(o.status=e.status),e.statusText&&(e.name=e.statusText)),n=i.error(o)}e.withCredentials&&0===e.status&&(n.status=405,n.statusText="Method Not Allowed"),t(n)}var u=!1,c=s.getArguments(function(e){u||(t.apply(this,e),u=!0)});"function"==typeof e&&(c=e,e={}),e=s.clone(e);var f={method:"GET",headers:{},json:!0,processData:!0,timeout:1e4,cache:!1};if(e=s.extend(!0,f,e),"GET"===e.method&&!e.cache){var l=-1!==e.url.indexOf("?");e.url+=(l?"&":"?")+"_nonce="+s.uuid(16)}var d,h;h=e.xhr?new e.xhr:new XMLHttpRequest,h.open(e.method,e.url),h.withCredentials=!0,e.json&&(e.headers.Accept="application/json",e.headers["Content-Type"]=e.headers["Content-Type"]||"application/json",e.body&&e.processData&&"string"!=typeof e.body&&(e.body=JSON.stringify(e.body))),e.binary&&(h.responseType="arraybuffer");var p=function(e,t,r){var n="";if(r){var o=new Date;o.setTime(o.getTime()+24*r*60*60*1e3),n="; expires="+o.toGMTString()}document.cookie=e+"="+t+n+"; path=/"};for(var v in e.headers)if("Cookie"===v){var y=e.headers[v].split("=");p(y[0],y[1],10)}else h.setRequestHeader(v,e.headers[v]);"body"in e||(e.body=null);var g=function(){u||(h.abort(),a(h,c))};return h.onreadystatechange=function(){if(4===h.readyState&&!u)if(clearTimeout(d),h.status>=200&&h.status<300){var t;t=e.binary?o([h.response||""],{type:h.getResponseHeader("Content-Type")}):h.responseText,r(t,h,c)}else a(h,c)},e.timeout>0&&(d=setTimeout(g,e.timeout),h.onprogress=function(){clearTimeout(d),d=setTimeout(g,e.timeout)},"undefined"==typeof n&&(n=-1!==Object.keys(h).indexOf("upload")),n&&(h.upload.onprogress=h.onprogress)),e.body&&e.body instanceof Blob?s.readAsBinaryString(e.body,function(e){h.send(s.fixBinary(e))}):h.send(e.body),{abort:g}}var n,o=e("./blob.js"),i=e("./errors"),s=e("../utils");t.exports=r},{"../utils":13,"./blob.js":3,"./errors":5}],3:[function(e,t){(function(e){"use strict";function r(t,r){t=t||[],r=r||{};try{return new Blob(t,r)}catch(n){if("TypeError"!==n.name)throw n;for(var o=e.BlobBuilder||e.MSBlobBuilder||e.MozBlobBuilder||e.WebKitBlobBuilder,i=new o,s=0;s<t.length;s+=1)i.append(t[s]);return i.getBlob(r.type)}}t.exports=r}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],4:[function(e,t,r){"use strict";function n(){this.store={}}function o(e){if(this.store=new n,e&&Array.isArray(e))for(var t=0,r=e.length;r>t;t++)this.add(e[t])}r.Map=n,r.Set=o,n.prototype.mangle=function(e){if("string"!=typeof e)throw new TypeError("key must be a string but Got "+e);return"$"+e},n.prototype.unmangle=function(e){return e.substring(1)},n.prototype.get=function(e){var t=this.mangle(e);return t in this.store?this.store[t]:void 0},n.prototype.set=function(e,t){var r=this.mangle(e);return this.store[r]=t,!0},n.prototype.has=function(e){var t=this.mangle(e);return t in this.store},n.prototype["delete"]=function(e){var t=this.mangle(e);return t in this.store?(delete this.store[t],!0):!1},n.prototype.forEach=function(e){var t=this,r=Object.keys(t.store);r.forEach(function(r){var n=t.store[r];r=t.unmangle(r),e(n,r)})},o.prototype.add=function(e){return this.store.set(e,!0)},o.prototype.has=function(e){return this.store.has(e)},o.prototype["delete"]=function(e){return this.store["delete"](e)}},{}],5:[function(e,t,r){"use strict";function n(e){this.status=e.status,this.name=e.error,this.message=e.reason,this.error=!0}n.prototype__proto__=Error.prototype,n.prototype.toString=function(){return JSON.stringify({status:this.status,name:this.name,message:this.message})},r.UNAUTHORIZED=new n({status:401,error:"unauthorized",reason:"Name or password is incorrect."}),r.MISSING_BULK_DOCS=new n({status:400,error:"bad_request",reason:"Missing JSON list of 'docs'"}),r.MISSING_DOC=new n({status:404,error:"not_found",reason:"missing"}),r.REV_CONFLICT=new n({status:409,error:"conflict",reason:"Document update conflict"}),r.INVALID_ID=new n({status:400,error:"invalid_id",reason:"_id field must contain a string"}),r.MISSING_ID=new n({status:412,error:"missing_id",reason:"_id is required for puts"}),r.RESERVED_ID=new n({status:400,error:"bad_request",reason:"Only reserved document ids may start with underscore."}),r.NOT_OPEN=new n({status:412,error:"precondition_failed",reason:"Database not open"}),r.UNKNOWN_ERROR=new n({status:500,error:"unknown_error",reason:"Database encountered an unknown error"}),r.BAD_ARG=new n({status:500,error:"badarg",reason:"Some query argument is invalid"}),r.INVALID_REQUEST=new n({status:400,error:"invalid_request",reason:"Request was invalid"}),r.QUERY_PARSE_ERROR=new n({status:400,error:"query_parse_error",reason:"Some query parameter is invalid"}),r.DOC_VALIDATION=new n({status:500,error:"doc_validation",reason:"Bad special document member"}),r.BAD_REQUEST=new n({status:400,error:"bad_request",reason:"Something wrong with the request"}),r.NOT_AN_OBJECT=new n({status:400,error:"bad_request",reason:"Document must be a JSON object"}),r.DB_MISSING=new n({status:404,error:"not_found",reason:"Database not found"}),r.IDB_ERROR=new n({status:500,error:"indexed_db_went_bad",reason:"unknown"}),r.WSQ_ERROR=new n({status:500,error:"web_sql_went_bad",reason:"unknown"}),r.LDB_ERROR=new n({status:500,error:"levelDB_went_went_bad",reason:"unknown"}),r.FORBIDDEN=new n({status:403,error:"forbidden",reason:"Forbidden by design doc validate_doc_update function"}),r.error=function(e,t,r){function n(){this.message=t,r&&(this.name=r)}return n.prototype=e,new n(t)}},{}],6:[function(e,t){(function(r,n){"use strict";function o(e,t,r){if("function"==typeof e.slice)return t?r?e.slice(t,r):e.slice(t):e.slice();t=Math.floor(t||0),r=Math.floor(r||0);var n=e.byteLength;if(t=0>t?Math.max(t+n,0):Math.min(n,t),r=0>r?Math.max(r+n,0):Math.min(n,r),0>=r-t)return new ArrayBuffer(0);var o=new ArrayBuffer(r-t),i=new Uint8Array(o),s=new Uint8Array(e,t,r-t);return i.set(s),o}function i(e){var t=[255&e,e>>>8&255,e>>>16&255,e>>>24&255];return t.map(function(e){return String.fromCharCode(e)}).join("")}function s(e){for(var t="",r=0;r<e.length;r++)t+=i(e[r]);return n.btoa(t)}var a=e("crypto"),u=e("spark-md5"),c=n.setImmediate||n.setTimeout,f=32768;t.exports=function(e,t){function n(e,t,r,n){d?e.appendBinary(t.substring(r,n)):e.append(o(t,r,n))}function i(){var r=y*p,o=r+p;if(r+p>=e.size&&(o=e.size),y++,v>y)n(g,e,r,o),c(i);else{n(g,e,r,o);var a=g.end(!0),u=s(a);t(null,u),g.destroy()}}if(!r.browser){var l=a.createHash("md5").update(e).digest("base64");return void t(null,l)}var d="string"==typeof e,h=d?e.length:e.byteLength,p=Math.min(f,h),v=Math.ceil(h/p),y=0,g=d?new u:new u.ArrayBuffer;i()}}).call(this,e("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{_process:24,crypto:16,"spark-md5":117}],7:[function(e,t,r){"use strict";function n(e){return("0000000000000000"+e).slice(-16)}var o=e("fs"),i=e("path"),s=e("../utils"),a=e("../merge"),u=e("levelup"),c=e("through2").obj,f=e("leveldown"),l=["document-store","by-sequence","attach-store","attach-binary-store"],d="_local_last_update_seq",h="_local_doc_count",p="_local_uuid";r.toSublevel=function(e,t,r){function n(e,r,n){var o,a=i.join(s,e);o=3===r?{valueEncoding:"binary"}:{valueEncoding:"json"};var c=t.sublevel(e,o),f=u(a,o),l=f.createReadStream(),d=c.createWriteStream();l.on("end",function(){f.close(function(e){n(e,a)})}),l.pipe(d)}var s=i.resolve(e);o.unlink(s+".uuid",function(e){if(e)return r();var t=4,i=[];l.forEach(function(e,a){n(e,a,function(e,n){return e?r(e):(i.push(n),void(--t||i.forEach(function(e){f.destroy(e,function(){++t===i.length&&o.rmdir(s,r)})})))})})})},r.localAndMetaStores=function(e,t,r){var o=[];t.bySeqStore.get(p,function(i,u){return i?r():(o.push({key:p,value:u,prefix:t.metaStore,type:"put",valueEncoding:"json"}),o.push({key:p,prefix:t.bySeqStore,type:"del"}),void t.bySeqStore.get(h,function(i,u){u&&(o.push({key:h,value:u,prefix:t.metaStore,type:"put",valueEncoding:"json"}),o.push({key:h,prefix:t.bySeqStore,type:"del"})),t.bySeqStore.get(d,function(i,u){u&&(o.push({key:d,value:u,prefix:t.metaStore,type:"put",valueEncoding:"json"}),o.push({key:d,prefix:t.bySeqStore,type:"del"}));var f={};t.docStore.createReadStream({startKey:"_",endKey:"_ÿ"}).pipe(c(function(e,r,i){if(!s.isLocalId(e.key))return i();o.push({key:e.key,prefix:t.docStore,type:"del"});var u=a.winningRev(e.value);Object.keys(e.value.rev_map).forEach(function(t){"winner"!==t&&this.push(n(e.value.rev_map[t]))},this);var c=e.value.rev_map[u];t.bySeqStore.get(n(c),function(r,n){r||o.push({key:e.key,value:n,prefix:t.localStore,type:"put",valueEncoding:"json"}),i()})})).pipe(c(function(e,r,n){return f[e]?n():(f[e]=!0,void t.bySeqStore.get(e,function(r,i){return r||!s.isLocalId(i._id)?n():(o.push({key:e,prefix:t.bySeqStore,type:"del"}),void n())}))},function(){e.batch(o,r)}))})}))})}},{"../merge":10,"../utils":13,fs:15,leveldown:"leveldown",levelup:75,path:23,through2:132}],8:[function(e,t){"use strict";function r(e){for(var t=n,r=t.parser[t.strictMode?"strict":"loose"].exec(e),o={},i=14;i--;){var s=t.key[i],a=r[i]||"",u=-1!==["user","password"].indexOf(s);o[s]=u?decodeURIComponent(a):a}return o[t.q.name]={},o[t.key[12]].replace(t.q.parser,function(e,r,n){r&&(o[t.q.name][r]=n)}),o}var n={strictMode:!1,key:["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],q:{name:"queryKey",parser:/(?:^|&)([^&=]*)=?([^&]*)/g},parser:{strict:/^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,loose:/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/}};t.exports=r},{}],9:[function(e,t){"use strict";function r(e){return 0|Math.random()*e}function n(e,t){t=t||o.length;var n="",i=-1;if(e){for(;++i<e;)n+=o[r(t)];return n}for(;++i<36;)switch(i){case 8:case 13:case 18:case 23:n+="-";break;case 19:n+=o[3&r(16)|8];break;default:n+=o[r(16)]}return n}var o="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split("");t.exports=n},{}],10:[function(e,t){"use strict";function r(e){for(var t,r=e.shift(),n=[r.id,r.opts,[]],o=n;e.length;)r=e.shift(),t=[r.id,r.opts,[]],o[2].push(t),o=t;return n}function n(e,t){for(var r=[{tree1:e,tree2:t}],n=!1;r.length>0;){var o=r.pop(),i=o.tree1,s=o.tree2;(i[1].status||s[1].status)&&(i[1].status="available"===i[1].status||"available"===s[1].status?"available":"missing");for(var a=0;a<s[2].length;a++)if(i[2][0]){for(var u=!1,c=0;c<i[2].length;c++)i[2][c][0]===s[2][a][0]&&(r.push({tree1:i[2][c],tree2:s[2][a]}),u=!0);u||(n="new_branch",i[2].push(s[2][a]),i[2].sort())}else n="new_leaf",i[2][0]=s[2][a]}return{conflicts:n,tree:e}}function o(e,t,r){var o,i=[],s=!1,a=!1;return e.length?(e.forEach(function(e){if(e.pos===t.pos&&e.ids[0]===t.ids[0])o=n(e.ids,t.ids),i.push({pos:e.pos,ids:o.tree}),s=s||o.conflicts,a=!0;else if(r!==!0){var u=e.pos<t.pos?e:t,c=e.pos<t.pos?t:e,f=c.pos-u.pos,l=[],d=[];for(d.push({ids:u.ids,diff:f,parent:null,parentIdx:null});d.length>0;){var h=d.pop();0!==h.diff?h.ids&&h.ids[2].forEach(function(e,t){d.push({ids:e,diff:h.diff-1,parent:h.ids,parentIdx:t})}):h.ids[0]===c.ids[0]&&l.push(h)}var p=l[0];p?(o=n(p.ids,c.ids),p.parent[2][p.parentIdx]=o.tree,i.push({pos:u.pos,ids:u.ids}),s=s||o.conflicts,a=!0):i.push(e)}else i.push(e)}),a||i.push(t),i.sort(function(e,t){return e.pos-t.pos}),{tree:i,conflicts:s||"internal_node"}):{tree:[t],conflicts:"new_leaf"}}function i(e,t){var n=a.rootToLeaf(e).map(function(e){var n=e.ids.slice(-t);return{pos:e.pos+(e.ids.length-n.length),ids:r(n)}});return n.reduce(function(e,t){return o(e,t,!0).tree},[n.shift()])}var s=e("pouchdb-extend"),a={};a.merge=function(e,t,r){e=s(!0,[],e),t=s(!0,{},t);var n=o(e,t);return{tree:i(n.tree,r),conflicts:n.conflicts}},a.winningRev=function(e){var t=[];return a.traverseRevTree(e.rev_tree,function(e,r,n,o,i){e&&t.push({pos:r,id:n,deleted:!!i.deleted})}),t.sort(function(e,t){return e.deleted!==t.deleted?e.deleted>t.deleted?1:-1:e.pos!==t.pos?t.pos-e.pos:e.id<t.id?1:-1}),t[0].pos+"-"+t[0].id},a.traverseRevTree=function(e,t){for(var r,n=e.slice();r=n.pop();)for(var o=r.pos,i=r.ids,s=i[2],a=t(0===s.length,o,i[0],r.ctx,i[1]),u=0,c=s.length;c>u;u++)n.push({pos:o+1,ids:s[u],ctx:a})},a.collectLeaves=function(e){var t=[];return a.traverseRevTree(e,function(e,r,n,o,i){e&&t.unshift({rev:r+"-"+n,pos:r,opts:i})}),t.sort(function(e,t){return t.pos-e.pos}),t.map(function(e){delete e.pos}),t},a.collectConflicts=function(e){var t=a.winningRev(e),r=a.collectLeaves(e.rev_tree),n=[];return r.forEach(function(e){e.rev===t||e.opts.deleted||n.push(e.rev)}),n},a.rootToLeaf=function(e){var t=[];return a.traverseRevTree(e,function(e,r,n,o,i){if(o=o?o.slice(0):[],o.push({id:n,opts:i}),e){var s=r+1-o.length;t.unshift({pos:s,ids:o})}return o}),t},t.exports=a},{"pouchdb-extend":116}],11:[function(e){(function(t){"use strict";var r=e("adapter-config"),n=r.name,o=e("./levelalt")(r),i=t.PouchDB||e("pouchdb");i.adapter(n,o),i.preferredAdapters.push(n)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./levelalt":12,"adapter-config":"adapter-config",pouchdb:"pouchdb"}],12:[function(e,t){"use strict";function r(e){function t(e,t){var r=i.extend({db:o},e);n.call(this,r,t)}return t.valid=function(){return e.valid()},t.use_prefix=e.use_prefix,t.destroy=i.toPromise(function(e,t,r){"function"==typeof t&&(r=t,t={});var s=i.extend({db:o},t);return n.destroy(e,s,r)}),t}var n=e("../adapters/leveldb"),o=e("leveldown"),i=e("../utils");t.exports=r},{"../adapters/leveldb":1,"../utils":13,leveldown:"leveldown"}],13:[function(e,t,r){(function(t,n){function o(e){var t={};return e.forEach(function(e){t[e]=!0}),t}function i(){return"undefined"!=typeof chrome&&"undefined"!=typeof chrome.storage&&"undefined"!=typeof chrome.storage.local}function s(){if(!(this instanceof s))return new s;var e=this;f.call(this),this.isChrome=i(),this.listeners={},this.hasLocal=!1,this.isChrome||(this.hasLocal=r.hasLocalStorage()),this.isChrome?chrome.storage.onChanged.addListener(function(t){null!=t.db_name&&e.emit(t.dbName.newValue)}):this.hasLocal&&(n.addEventListener?n.addEventListener("storage",function(t){e.emit(t.key)}):n.attachEvent("storage",function(t){e.emit(t.key)}))}var a=e("./merge");r.extend=e("pouchdb-extend"),r.ajax=e("./deps/ajax"),r.createBlob=e("./deps/blob"),r.uuid=e("./deps/uuid"),r.getArguments=e("argsarray");var u=e("./deps/buffer"),c=e("./deps/errors"),f=e("events").EventEmitter,l=e("./deps/collections");r.Map=l.Map,r.Set=l.Set,r.Promise="function"==typeof n.Promise?n.Promise:e("bluebird");var d=r.Promise,h=o(["_id","_rev","_attachments","_deleted","_revisions","_revs_info","_conflicts","_deleted_conflicts","_local_seq","_rev_tree","_replication_id","_replication_state","_replication_state_time","_replication_state_reason","_replication_stats"]),p=o(["_attachments","_replication_id","_replication_state","_replication_state_time","_replication_state_reason","_replication_stats"]);r.lastIndexOf=function(e,t){for(var r=e.length-1;r>=0;r--)if(e.charAt(r)===t)return r;return-1},r.clone=function(e){return r.extend(!0,{},e)},r.pick=function(e,t){for(var r={},n=0,o=t.length;o>n;n++){var i=t[n];r[i]=e[i]}return r},r.inherits=e("inherits"),r.invalidIdError=function(e){var t;if(e?"string"!=typeof e?(t=new TypeError(c.INVALID_ID.message),t.status=400):/^_/.test(e)&&!/^_(design|local)/.test(e)&&(t=new TypeError(c.RESERVED_ID.message),t.status=400):(t=new TypeError(c.MISSING_ID.message),t.status=412),t)throw t},r.call=r.getArguments(function(e){if(e.length){var t=e.shift();"function"==typeof t&&t.apply(this,e)}}),r.isLocalId=function(e){return/^_local/.test(e)},r.isDeleted=function(e,t){t||(t=a.winningRev(e)); +var r=t.indexOf("-");-1!==r&&(t=t.substring(r+1));var n=!1;return a.traverseRevTree(e.rev_tree,function(e,r,o,i,s){o===t&&(n=!!s.deleted)}),n},r.revExists=function(e,t){var r=!1;return a.traverseRevTree(e.rev_tree,function(e,n,o){n+"-"+o===t&&(r=!0)}),r},r.filterChange=function(e){var t={},r=e.filter&&"function"==typeof e.filter;return t.query=e.query_params,function(n){if(e.filter&&r&&!e.filter.call(this,n.doc,t))return!1;if(e.include_docs){if(!e.attachments)for(var o in n.doc._attachments)n.doc._attachments.hasOwnProperty(o)&&(n.doc._attachments[o].stub=!0)}else delete n.doc;return!0}},r.parseDoc=function(e,t){var n,o,i,s,a={status:"available"};if(e._deleted&&(a.deleted=!0),t)if(e._id||(e._id=r.uuid()),o=r.uuid(32,16).toLowerCase(),e._rev){if(i=/^(\d+)-(.+)$/.exec(e._rev),!i)return s=new Error("bad_request"),s.message="Invalid rev format",s.error=!0,s;e._rev_tree=[{pos:parseInt(i[1],10),ids:[i[2],{status:"missing"},[[o,a,[]]]]}],n=parseInt(i[1],10)+1}else e._rev_tree=[{pos:1,ids:[o,a,[]]}],n=1;else if(e._revisions&&(e._rev_tree=[{pos:e._revisions.start-e._revisions.ids.length+1,ids:e._revisions.ids.reduce(function(e,t){return null===e?[t,a,[]]:[t,{status:"missing"},[e]]},null)}],n=e._revisions.start,o=e._revisions.ids[0]),!e._rev_tree){if(i=/^(\d+)-(.+)$/.exec(e._rev),!i)return s=new Error("bad_request"),s.message="Invalid rev format",s.error=!0,s;n=parseInt(i[1],10),o=i[2],e._rev_tree=[{pos:parseInt(i[1],10),ids:[i[2],a,[]]}]}r.invalidIdError(e._id),e._rev=[n,o].join("-");var u={metadata:{},data:{}};for(var f in e)if(e.hasOwnProperty(f)){var l="_"===f[0];if(l&&!h[f])throw s=new Error(c.DOC_VALIDATION.message+": "+f),s.status=c.DOC_VALIDATION.status,s;l&&!p[f]?u.metadata[f.slice(1)]=e[f]:u.data[f]=e[f]}return u},r.isCordova=function(){return"undefined"!=typeof cordova||"undefined"!=typeof PhoneGap||"undefined"!=typeof phonegap},r.hasLocalStorage=function(){if(i())return!1;try{return n.localStorage}catch(e){return!1}},r.Changes=s,r.inherits(s,f),s.prototype.addListener=function(e,t,n,o){function i(){n.changes({include_docs:o.include_docs,attachments:o.attachments,conflicts:o.conflicts,continuous:!1,descending:!1,filter:o.filter,doc_ids:o.doc_ids,view:o.view,since:o.since,query_params:o.query_params,onChange:function(e){e.seq>o.since&&!o.cancelled&&(o.since=e.seq,r.call(o.onChange,e))}})}this.listeners[t]||(this.listeners[t]=i,this.on(e,i))},s.prototype.removeListener=function(e,t){t in this.listeners&&f.prototype.removeListener.call(this,e,this.listeners[t])},s.prototype.notifyLocalWindows=function(e){this.isChrome?chrome.storage.local.set({dbName:e}):this.hasLocal&&(localStorage[e]="a"===localStorage[e]?"b":"a")},s.prototype.notify=function(e){this.emit(e),this.notifyLocalWindows(e)},r.atob=t.browser&&"atob"in n?function(e){return atob(e)}:function(e){var t=new u(e,"base64");if(t.toString("base64")!==e)throw"Cannot base64 encode full string";return t.toString("binary")},r.btoa=t.browser&&"btoa"in n?function(e){return btoa(e)}:function(e){return new u(e,"binary").toString("base64")},r.fixBinary=function(e){if(!t.browser)return e;for(var r=e.length,n=new ArrayBuffer(r),o=new Uint8Array(n),i=0;r>i;i++)o[i]=e.charCodeAt(i);return n},r.readAsBinaryString=function(e,t){var n=new FileReader,o="function"==typeof n.readAsBinaryString;n.onloadend=function(e){var n=e.target.result||"";return o?t(n):void t(r.arrayBufferToBinaryString(n))},o?n.readAsBinaryString(e):n.readAsArrayBuffer(e)},r.once=function(e){var t=!1;return r.getArguments(function(r){if(t)throw new Error("once called more than once");t=!0,e.apply(this,r)})},r.toPromise=function(e){return r.getArguments(function(n){var o,i=this,s="function"==typeof n[n.length-1]?n.pop():!1;s&&(o=function(e,r){t.nextTick(function(){s(e,r)})});var a=new d(function(t,o){var s;try{var a=r.once(function(e,r){e?o(e):t(r)});n.push(a),s=e.apply(i,n),s&&"function"==typeof s.then&&t(s)}catch(u){o(u)}});return o&&a.then(function(e){o(null,e)},o),a.cancel=function(){return this},a})},r.adapterFun=function(t,n){function o(e,t,r){if(i.enabled){for(var n=[e._db_name,t],o=0;o<r.length-1;o++)n.push(r[o]);i.apply(null,n);var s=r[r.length-1];r[r.length-1]=function(r,n){var o=[e._db_name,t];o=o.concat(r?["error",r]:["success",n]),i.apply(null,o),s(r,n)}}}var i=e("debug")("pouchdb:api");return r.toPromise(r.getArguments(function(e){if(this._closed)return d.reject(new Error("database is closed"));var i=this;return o(i,t,e),this.taskqueue.isReady?n.apply(this,e):new r.Promise(function(r,n){i.taskqueue.addTask(function(o){o?n(o):r(i[t].apply(i,e))})})}))},r.arrayBufferToBinaryString=function(e){for(var t="",r=new Uint8Array(e),n=r.byteLength,o=0;n>o;o++)t+=String.fromCharCode(r[o]);return t},r.cancellableFun=function(e,t,n){n=n?r.clone(!0,{},n):{};var o=new f,i=n.complete||function(){},s=n.complete=r.once(function(e,t){e?i(e):(o.emit("end",t),i(null,t)),o.removeAllListeners()}),a=n.onChange||function(){},u=0;t.on("destroyed",function(){o.removeAllListeners()}),n.onChange=function(e){a(e),e.seq<=u||(u=e.seq,o.emit("change",e),e.deleted?o.emit("delete",e):1===e.changes.length&&"1-"===e.changes[0].rev.slice(0,1)?o.emit("create",e):o.emit("update",e))};var c=new d(function(e,t){n.complete=function(r,n){r?t(r):e(n)}});return c.then(function(e){s(null,e)},s),c.cancel=function(){c.isCancelled=!0,t.taskqueue.isReady&&n.complete(null,{status:"cancelled"})},t.taskqueue.isReady?e(t,n,c):t.taskqueue.addTask(function(){c.isCancelled?n.complete(null,{status:"cancelled"}):e(t,n,c)}),c.on=o.on.bind(o),c.once=o.once.bind(o),c.addListener=o.addListener.bind(o),c.removeListener=o.removeListener.bind(o),c.removeAllListeners=o.removeAllListeners.bind(o),c.setMaxListeners=o.setMaxListeners.bind(o),c.listeners=o.listeners.bind(o),c.emit=o.emit.bind(o),c},r.MD5=r.toPromise(e("./deps/md5")),r.explain404=function(e){t.browser&&"console"in n&&"info"in console&&console.info("The above 404 is totally normal. "+e)},r.parseUri=e("./deps/parse-uri"),r.compare=function(e,t){return t>e?-1:e>t?1:0},r.updateDoc=function(e,t,n,o,i,s,u){if(r.revExists(e,t.metadata.rev))return n[o]=t,i();var f=r.isDeleted(e),l=r.isDeleted(t.metadata),d=/^1-/.test(t.metadata.rev);if(f&&!l&&u&&d){var h=t.data;h._rev=a.winningRev(e),h._id=t.metadata.id,t=r.parseDoc(h,u)}var p=a.merge(e.rev_tree,t.metadata.rev_tree[0],1e3),v=u&&(f&&l||!f&&"new_leaf"!==p.conflicts||f&&!l&&"new_branch"===p.conflicts);if(v){var y=c.REV_CONFLICT;return n[o]=y,i()}t.metadata.rev_tree=p.tree;var g=a.winningRev(t.metadata);l=r.isDeleted(t.metadata,g),s(t,g,l,i,!0,o)},r.processDocs=function(e,t,n,o,i,s,u){function f(e,t,n){var o=a.winningRev(e.metadata),f=r.isDeleted(e.metadata,o);return"was_delete"in u&&f?(i[t]=c.MISSING_DOC,n()):void s(e,o,f,n,!1,t)}if(e.length){var l=u.new_edits,d=new r.Map;e.forEach(function(e,n){if(e._id&&r.isLocalId(e._id))return void t[e._deleted?"_removeLocal":"_putLocal"](e,{ctx:o},function(e){i[n]=e?e:{}});var s=e.metadata.id;d.has(s)?d.get(s).push([e,n]):d.set(s,[[e,n]])}),d.forEach(function(e,t){function o(){++u<e.length&&a()}function a(){var a=e[u],c=a[0],d=a[1];n.has(t)?r.updateDoc(n.get(t),c,i,d,o,s,l):f(c,d,o)}var u=0;a()})}},r.preprocessAttachments=function(e,t,n){function o(e){try{return r.atob(e)}catch(t){var n=c.error(c.BAD_ARG,"Attachments need to be base64 encoded");return{error:n}}}function i(e,n){if(e.stub)return n();if("string"==typeof e.data){var i=o(e.data);if(i.error)return n(i.error);e.length=i.length,e.data="blob"===t?r.createBlob([r.fixBinary(i)],{type:e.content_type}):"base64"===t?r.btoa(i):i,r.MD5(i).then(function(t){e.digest="md5-"+t,n()})}else r.readAsBinaryString(e.data,function(o){"binary"===t?e.data=o:"base64"===t&&(e.data=r.btoa(o)),r.MD5(o).then(function(t){e.digest="md5-"+t,e.length=o.length,n()})})}function s(){u++,e.length===u&&(a?n(a):n())}if(!e.length)return n();var a,u=0;e.forEach(function(e){function t(e){a=e,n++,n===r.length&&s()}var r=e.data&&e.data._attachments?Object.keys(e.data._attachments):[],n=0;if(!r.length)return s();for(var o in e.data._attachments)e.data._attachments.hasOwnProperty(o)&&i(e.data._attachments[o],t)})}}).call(this,e("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./deps/ajax":2,"./deps/blob":3,"./deps/buffer":16,"./deps/collections":4,"./deps/errors":5,"./deps/md5":6,"./deps/parse-uri":8,"./deps/uuid":9,"./merge":10,_process:24,argsarray:14,bluebird:101,debug:40,events:21,inherits:44,"pouchdb-extend":116}],14:[function(e,t){"use strict";function r(e){return function(){var t=arguments.length;if(t){for(var r=[],n=-1;++n<t;)r[n]=arguments[n];return e.call(this,r)}return e.call(this,[])}}t.exports=r},{}],15:[function(){},{}],16:[function(e,t){t.exports=e(15)},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/lib/_empty.js":15}],17:[function(e,t,r){function n(e,t,r){if(!(this instanceof n))return new n(e,t,r);var o,i=typeof e;if("number"===i)o=e>0?e>>>0:0;else if("string"===i)"base64"===t&&(e=x(e)),o=n.byteLength(e,t);else{if("object"!==i||null===e)throw new TypeError("must start with number, buffer, array or string");"Buffer"===e.type&&B(e.data)&&(e=e.data),o=+e.length>0?Math.floor(+e.length):0}if(this.length>C)throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+C.toString(16)+" bytes");var s;n.TYPED_ARRAY_SUPPORT?s=n._augment(new Uint8Array(o)):(s=this,s.length=o,s._isBuffer=!0);var a;if(n.TYPED_ARRAY_SUPPORT&&"number"==typeof e.byteLength)s._set(e);else if(S(e))if(n.isBuffer(e))for(a=0;o>a;a++)s[a]=e.readUInt8(a);else for(a=0;o>a;a++)s[a]=(e[a]%256+256)%256;else if("string"===i)s.write(e,0,t);else if("number"===i&&!n.TYPED_ARRAY_SUPPORT&&!r)for(a=0;o>a;a++)s[a]=0;return s}function o(e,t,r,n){r=Number(r)||0;var o=e.length-r;n?(n=Number(n),n>o&&(n=o)):n=o;var i=t.length;if(i%2!==0)throw new Error("Invalid hex string");n>i/2&&(n=i/2);for(var s=0;n>s;s++){var a=parseInt(t.substr(2*s,2),16);if(isNaN(a))throw new Error("Invalid hex string");e[r+s]=a}return s}function i(e,t,r,n){var o=N(j(t),e,r,n);return o}function s(e,t,r,n){var o=N(O(t),e,r,n);return o}function a(e,t,r,n){return s(e,t,r,n)}function u(e,t,r,n){var o=N(I(t),e,r,n);return o}function c(e,t,r,n){var o=N(R(t),e,r,n);return o}function f(e,t,r){return L.fromByteArray(0===t&&r===e.length?e:e.slice(t,r))}function l(e,t,r){var n="",o="";r=Math.min(e.length,r);for(var i=t;r>i;i++)e[i]<=127?(n+=T(o)+String.fromCharCode(e[i]),o=""):o+="%"+e[i].toString(16);return n+T(o)}function d(e,t,r){var n="";r=Math.min(e.length,r);for(var o=t;r>o;o++)n+=String.fromCharCode(e[o]);return n}function h(e,t,r){return d(e,t,r)}function p(e,t,r){var n=e.length;(!t||0>t)&&(t=0),(!r||0>r||r>n)&&(r=n);for(var o="",i=t;r>i;i++)o+=A(e[i]);return o}function v(e,t,r){for(var n=e.slice(t,r),o="",i=0;i<n.length;i+=2)o+=String.fromCharCode(n[i]+256*n[i+1]);return o}function y(e,t,r){if(e%1!==0||0>e)throw new RangeError("offset is not uint");if(e+t>r)throw new RangeError("Trying to access beyond buffer length")}function g(e,t,r,o,i,s){if(!n.isBuffer(e))throw new TypeError("buffer must be a Buffer instance");if(t>i||s>t)throw new TypeError("value is out of bounds");if(r+o>e.length)throw new TypeError("index out of range")}function m(e,t,r,n){0>t&&(t=65535+t+1);for(var o=0,i=Math.min(e.length-r,2);i>o;o++)e[r+o]=(t&255<<8*(n?o:1-o))>>>8*(n?o:1-o)}function b(e,t,r,n){0>t&&(t=4294967295+t+1);for(var o=0,i=Math.min(e.length-r,4);i>o;o++)e[r+o]=t>>>8*(n?o:3-o)&255}function _(e,t,r,n,o,i){if(t>o||i>t)throw new TypeError("value is out of bounds");if(r+n>e.length)throw new TypeError("index out of range")}function w(e,t,r,n,o){return o||_(e,t,r,4,3.4028234663852886e38,-3.4028234663852886e38),D.write(e,t,r,n,23,4),r+4}function E(e,t,r,n,o){return o||_(e,t,r,8,1.7976931348623157e308,-1.7976931348623157e308),D.write(e,t,r,n,52,8),r+8}function x(e){for(e=k(e).replace(U,"");e.length%4!==0;)e+="=";return e}function k(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}function S(e){return B(e)||n.isBuffer(e)||e&&"object"==typeof e&&"number"==typeof e.length}function A(e){return 16>e?"0"+e.toString(16):e.toString(16)}function j(e){for(var t=[],r=0;r<e.length;r++){var n=e.charCodeAt(r);if(127>=n)t.push(n);else{var o=r;n>=55296&&57343>=n&&r++;for(var i=encodeURIComponent(e.slice(o,r+1)).substr(1).split("%"),s=0;s<i.length;s++)t.push(parseInt(i[s],16))}}return t}function O(e){for(var t=[],r=0;r<e.length;r++)t.push(255&e.charCodeAt(r));return t}function R(e){for(var t,r,n,o=[],i=0;i<e.length;i++)t=e.charCodeAt(i),r=t>>8,n=t%256,o.push(n),o.push(r);return o}function I(e){return L.toByteArray(e)}function N(e,t,r,n){for(var o=0;n>o&&!(o+r>=t.length||o>=e.length);o++)t[o+r]=e[o];return o}function T(e){try{return decodeURIComponent(e)}catch(t){return String.fromCharCode(65533)}}var L=e("base64-js"),D=e("ieee754"),B=e("is-array");r.Buffer=n,r.SlowBuffer=n,r.INSPECT_MAX_BYTES=50,n.poolSize=8192;var C=1073741823;n.TYPED_ARRAY_SUPPORT=function(){try{var e=new ArrayBuffer(0),t=new Uint8Array(e);return t.foo=function(){return 42},42===t.foo()&&"function"==typeof t.subarray&&0===new Uint8Array(1).subarray(1,1).byteLength}catch(r){return!1}}(),n.isBuffer=function(e){return!(null==e||!e._isBuffer)},n.compare=function(e,t){if(!n.isBuffer(e)||!n.isBuffer(t))throw new TypeError("Arguments must be Buffers");for(var r=e.length,o=t.length,i=0,s=Math.min(r,o);s>i&&e[i]===t[i];i++);return i!==s&&(r=e[i],o=t[i]),o>r?-1:r>o?1:0},n.isEncoding=function(e){switch(String(e).toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"raw":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return!0;default:return!1}},n.concat=function(e,t){if(!B(e))throw new TypeError("Usage: Buffer.concat(list[, length])");if(0===e.length)return new n(0);if(1===e.length)return e[0];var r;if(void 0===t)for(t=0,r=0;r<e.length;r++)t+=e[r].length;var o=new n(t),i=0;for(r=0;r<e.length;r++){var s=e[r];s.copy(o,i),i+=s.length}return o},n.byteLength=function(e,t){var r;switch(e+="",t||"utf8"){case"ascii":case"binary":case"raw":r=e.length;break;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":r=2*e.length;break;case"hex":r=e.length>>>1;break;case"utf8":case"utf-8":r=j(e).length;break;case"base64":r=I(e).length;break;default:r=e.length}return r},n.prototype.length=void 0,n.prototype.parent=void 0,n.prototype.toString=function(e,t,r){var n=!1;if(t>>>=0,r=void 0===r||1/0===r?this.length:r>>>0,e||(e="utf8"),0>t&&(t=0),r>this.length&&(r=this.length),t>=r)return"";for(;;)switch(e){case"hex":return p(this,t,r);case"utf8":case"utf-8":return l(this,t,r);case"ascii":return d(this,t,r);case"binary":return h(this,t,r);case"base64":return f(this,t,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return v(this,t,r);default:if(n)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),n=!0}},n.prototype.equals=function(e){if(!n.isBuffer(e))throw new TypeError("Argument must be a Buffer");return 0===n.compare(this,e)},n.prototype.inspect=function(){var e="",t=r.INSPECT_MAX_BYTES;return this.length>0&&(e=this.toString("hex",0,t).match(/.{2}/g).join(" "),this.length>t&&(e+=" ... ")),"<Buffer "+e+">"},n.prototype.compare=function(e){if(!n.isBuffer(e))throw new TypeError("Argument must be a Buffer");return n.compare(this,e)},n.prototype.get=function(e){return console.log(".get() is deprecated. Access using array indexes instead."),this.readUInt8(e)},n.prototype.set=function(e,t){return console.log(".set() is deprecated. Access using array indexes instead."),this.writeUInt8(e,t)},n.prototype.write=function(e,t,r,n){if(isFinite(t))isFinite(r)||(n=r,r=void 0);else{var f=n;n=t,t=r,r=f}t=Number(t)||0;var l=this.length-t;r?(r=Number(r),r>l&&(r=l)):r=l,n=String(n||"utf8").toLowerCase();var d;switch(n){case"hex":d=o(this,e,t,r);break;case"utf8":case"utf-8":d=i(this,e,t,r);break;case"ascii":d=s(this,e,t,r);break;case"binary":d=a(this,e,t,r);break;case"base64":d=u(this,e,t,r);break;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":d=c(this,e,t,r);break;default:throw new TypeError("Unknown encoding: "+n)}return d},n.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}},n.prototype.slice=function(e,t){var r=this.length;if(e=~~e,t=void 0===t?r:~~t,0>e?(e+=r,0>e&&(e=0)):e>r&&(e=r),0>t?(t+=r,0>t&&(t=0)):t>r&&(t=r),e>t&&(t=e),n.TYPED_ARRAY_SUPPORT)return n._augment(this.subarray(e,t));for(var o=t-e,i=new n(o,void 0,!0),s=0;o>s;s++)i[s]=this[s+e];return i},n.prototype.readUInt8=function(e,t){return t||y(e,1,this.length),this[e]},n.prototype.readUInt16LE=function(e,t){return t||y(e,2,this.length),this[e]|this[e+1]<<8},n.prototype.readUInt16BE=function(e,t){return t||y(e,2,this.length),this[e]<<8|this[e+1]},n.prototype.readUInt32LE=function(e,t){return t||y(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},n.prototype.readUInt32BE=function(e,t){return t||y(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},n.prototype.readInt8=function(e,t){return t||y(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},n.prototype.readInt16LE=function(e,t){t||y(e,2,this.length);var r=this[e]|this[e+1]<<8;return 32768&r?4294901760|r:r},n.prototype.readInt16BE=function(e,t){t||y(e,2,this.length);var r=this[e+1]|this[e]<<8;return 32768&r?4294901760|r:r},n.prototype.readInt32LE=function(e,t){return t||y(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},n.prototype.readInt32BE=function(e,t){return t||y(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},n.prototype.readFloatLE=function(e,t){return t||y(e,4,this.length),D.read(this,e,!0,23,4)},n.prototype.readFloatBE=function(e,t){return t||y(e,4,this.length),D.read(this,e,!1,23,4)},n.prototype.readDoubleLE=function(e,t){return t||y(e,8,this.length),D.read(this,e,!0,52,8)},n.prototype.readDoubleBE=function(e,t){return t||y(e,8,this.length),D.read(this,e,!1,52,8)},n.prototype.writeUInt8=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,1,255,0),n.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=e,t+1},n.prototype.writeUInt16LE=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,2,65535,0),n.TYPED_ARRAY_SUPPORT?(this[t]=e,this[t+1]=e>>>8):m(this,e,t,!0),t+2},n.prototype.writeUInt16BE=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,2,65535,0),n.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=e):m(this,e,t,!1),t+2},n.prototype.writeUInt32LE=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,4,4294967295,0),n.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=e):b(this,e,t,!0),t+4},n.prototype.writeUInt32BE=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,4,4294967295,0),n.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=e):b(this,e,t,!1),t+4},n.prototype.writeInt8=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,1,127,-128),n.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),0>e&&(e=255+e+1),this[t]=e,t+1},n.prototype.writeInt16LE=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,2,32767,-32768),n.TYPED_ARRAY_SUPPORT?(this[t]=e,this[t+1]=e>>>8):m(this,e,t,!0),t+2},n.prototype.writeInt16BE=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,2,32767,-32768),n.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=e):m(this,e,t,!1),t+2},n.prototype.writeInt32LE=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,4,2147483647,-2147483648),n.TYPED_ARRAY_SUPPORT?(this[t]=e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):b(this,e,t,!0),t+4},n.prototype.writeInt32BE=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,4,2147483647,-2147483648),0>e&&(e=4294967295+e+1),n.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=e):b(this,e,t,!1),t+4},n.prototype.writeFloatLE=function(e,t,r){return w(this,e,t,!0,r)},n.prototype.writeFloatBE=function(e,t,r){return w(this,e,t,!1,r)},n.prototype.writeDoubleLE=function(e,t,r){return E(this,e,t,!0,r)},n.prototype.writeDoubleBE=function(e,t,r){return E(this,e,t,!1,r)},n.prototype.copy=function(e,t,r,o){var i=this;if(r||(r=0),o||0===o||(o=this.length),t||(t=0),o!==r&&0!==e.length&&0!==i.length){if(r>o)throw new TypeError("sourceEnd < sourceStart");if(0>t||t>=e.length)throw new TypeError("targetStart out of bounds");if(0>r||r>=i.length)throw new TypeError("sourceStart out of bounds");if(0>o||o>i.length)throw new TypeError("sourceEnd out of bounds");o>this.length&&(o=this.length),e.length-t<o-r&&(o=e.length-t+r);var s=o-r;if(1e3>s||!n.TYPED_ARRAY_SUPPORT)for(var a=0;s>a;a++)e[a+t]=this[a+r];else e._set(this.subarray(r,r+s),t)}},n.prototype.fill=function(e,t,r){if(e||(e=0),t||(t=0),r||(r=this.length),t>r)throw new TypeError("end < start");if(r!==t&&0!==this.length){if(0>t||t>=this.length)throw new TypeError("start out of bounds");if(0>r||r>this.length)throw new TypeError("end out of bounds");var n;if("number"==typeof e)for(n=t;r>n;n++)this[n]=e;else{var o=j(e.toString()),i=o.length;for(n=t;r>n;n++)this[n]=o[n%i]}return this}},n.prototype.toArrayBuffer=function(){if("undefined"!=typeof Uint8Array){if(n.TYPED_ARRAY_SUPPORT)return new n(this).buffer;for(var e=new Uint8Array(this.length),t=0,r=e.length;r>t;t+=1)e[t]=this[t];return e.buffer}throw new TypeError("Buffer.toArrayBuffer not supported in this browser")};var P=n.prototype;n._augment=function(e){return e.constructor=n,e._isBuffer=!0,e._get=e.get,e._set=e.set,e.get=P.get,e.set=P.set,e.write=P.write,e.toString=P.toString,e.toLocaleString=P.toString,e.toJSON=P.toJSON,e.equals=P.equals,e.compare=P.compare,e.copy=P.copy,e.slice=P.slice,e.readUInt8=P.readUInt8,e.readUInt16LE=P.readUInt16LE,e.readUInt16BE=P.readUInt16BE,e.readUInt32LE=P.readUInt32LE,e.readUInt32BE=P.readUInt32BE,e.readInt8=P.readInt8,e.readInt16LE=P.readInt16LE,e.readInt16BE=P.readInt16BE,e.readInt32LE=P.readInt32LE,e.readInt32BE=P.readInt32BE,e.readFloatLE=P.readFloatLE,e.readFloatBE=P.readFloatBE,e.readDoubleLE=P.readDoubleLE,e.readDoubleBE=P.readDoubleBE,e.writeUInt8=P.writeUInt8,e.writeUInt16LE=P.writeUInt16LE,e.writeUInt16BE=P.writeUInt16BE,e.writeUInt32LE=P.writeUInt32LE,e.writeUInt32BE=P.writeUInt32BE,e.writeInt8=P.writeInt8,e.writeInt16LE=P.writeInt16LE,e.writeInt16BE=P.writeInt16BE,e.writeInt32LE=P.writeInt32LE,e.writeInt32BE=P.writeInt32BE,e.writeFloatLE=P.writeFloatLE,e.writeFloatBE=P.writeFloatBE,e.writeDoubleLE=P.writeDoubleLE,e.writeDoubleBE=P.writeDoubleBE,e.fill=P.fill,e.inspect=P.inspect,e.toArrayBuffer=P.toArrayBuffer,e};var U=/[^+\/0-9A-z]/g},{"base64-js":18,ieee754:19,"is-array":20}],18:[function(e,t,r){var n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";!function(e){"use strict";function t(e){var t=e.charCodeAt(0);return t===s?62:t===a?63:u>t?-1:u+10>t?t-u+26+26:f+26>t?t-f:c+26>t?t-c+26:void 0}function r(e){function r(e){c[l++]=e}var n,o,s,a,u,c;if(e.length%4>0)throw new Error("Invalid string. Length must be a multiple of 4");var f=e.length;u="="===e.charAt(f-2)?2:"="===e.charAt(f-1)?1:0,c=new i(3*e.length/4-u),s=u>0?e.length-4:e.length;var l=0;for(n=0,o=0;s>n;n+=4,o+=3)a=t(e.charAt(n))<<18|t(e.charAt(n+1))<<12|t(e.charAt(n+2))<<6|t(e.charAt(n+3)),r((16711680&a)>>16),r((65280&a)>>8),r(255&a);return 2===u?(a=t(e.charAt(n))<<2|t(e.charAt(n+1))>>4,r(255&a)):1===u&&(a=t(e.charAt(n))<<10|t(e.charAt(n+1))<<4|t(e.charAt(n+2))>>2,r(a>>8&255),r(255&a)),c}function o(e){function t(e){return n.charAt(e)}function r(e){return t(e>>18&63)+t(e>>12&63)+t(e>>6&63)+t(63&e)}var o,i,s,a=e.length%3,u="";for(o=0,s=e.length-a;s>o;o+=3)i=(e[o]<<16)+(e[o+1]<<8)+e[o+2],u+=r(i);switch(a){case 1:i=e[e.length-1],u+=t(i>>2),u+=t(i<<4&63),u+="==";break;case 2:i=(e[e.length-2]<<8)+e[e.length-1],u+=t(i>>10),u+=t(i>>4&63),u+=t(i<<2&63),u+="="}return u}var i="undefined"!=typeof Uint8Array?Uint8Array:Array,s="+".charCodeAt(0),a="/".charCodeAt(0),u="0".charCodeAt(0),c="a".charCodeAt(0),f="A".charCodeAt(0);e.toByteArray=r,e.fromByteArray=o}("undefined"==typeof r?this.base64js={}:r)},{}],19:[function(e,t,r){r.read=function(e,t,r,n,o){var i,s,a=8*o-n-1,u=(1<<a)-1,c=u>>1,f=-7,l=r?o-1:0,d=r?-1:1,h=e[t+l];for(l+=d,i=h&(1<<-f)-1,h>>=-f,f+=a;f>0;i=256*i+e[t+l],l+=d,f-=8);for(s=i&(1<<-f)-1,i>>=-f,f+=n;f>0;s=256*s+e[t+l],l+=d,f-=8);if(0===i)i=1-c;else{if(i===u)return s?0/0:1/0*(h?-1:1);s+=Math.pow(2,n),i-=c}return(h?-1:1)*s*Math.pow(2,i-n)},r.write=function(e,t,r,n,o,i){var s,a,u,c=8*i-o-1,f=(1<<c)-1,l=f>>1,d=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,h=n?0:i-1,p=n?1:-1,v=0>t||0===t&&0>1/t?1:0;for(t=Math.abs(t),isNaN(t)||1/0===t?(a=isNaN(t)?1:0,s=f):(s=Math.floor(Math.log(t)/Math.LN2),t*(u=Math.pow(2,-s))<1&&(s--,u*=2),t+=s+l>=1?d/u:d*Math.pow(2,1-l),t*u>=2&&(s++,u/=2),s+l>=f?(a=0,s=f):s+l>=1?(a=(t*u-1)*Math.pow(2,o),s+=l):(a=t*Math.pow(2,l-1)*Math.pow(2,o),s=0));o>=8;e[r+h]=255&a,h+=p,a/=256,o-=8);for(s=s<<o|a,c+=o;c>0;e[r+h]=255&s,h+=p,s/=256,c-=8);e[r+h-p]|=128*v}},{}],20:[function(e,t){var r=Array.isArray,n=Object.prototype.toString;t.exports=r||function(e){return!!e&&"[object Array]"==n.call(e)}},{}],21:[function(e,t){function r(){this._events=this._events||{},this._maxListeners=this._maxListeners||void 0}function n(e){return"function"==typeof e}function o(e){return"number"==typeof e}function i(e){return"object"==typeof e&&null!==e}function s(e){return void 0===e}t.exports=r,r.EventEmitter=r,r.prototype._events=void 0,r.prototype._maxListeners=void 0,r.defaultMaxListeners=10,r.prototype.setMaxListeners=function(e){if(!o(e)||0>e||isNaN(e))throw TypeError("n must be a positive number");return this._maxListeners=e,this},r.prototype.emit=function(e){var t,r,o,a,u,c;if(this._events||(this._events={}),"error"===e&&(!this._events.error||i(this._events.error)&&!this._events.error.length)){if(t=arguments[1],t instanceof Error)throw t;throw TypeError('Uncaught, unspecified "error" event.')}if(r=this._events[e],s(r))return!1;if(n(r))switch(arguments.length){case 1:r.call(this);break;case 2:r.call(this,arguments[1]);break;case 3:r.call(this,arguments[1],arguments[2]);break;default:for(o=arguments.length,a=new Array(o-1),u=1;o>u;u++)a[u-1]=arguments[u];r.apply(this,a)}else if(i(r)){for(o=arguments.length,a=new Array(o-1),u=1;o>u;u++)a[u-1]=arguments[u];for(c=r.slice(),o=c.length,u=0;o>u;u++)c[u].apply(this,a)}return!0},r.prototype.addListener=function(e,t){var o;if(!n(t))throw TypeError("listener must be a function");if(this._events||(this._events={}),this._events.newListener&&this.emit("newListener",e,n(t.listener)?t.listener:t),this._events[e]?i(this._events[e])?this._events[e].push(t):this._events[e]=[this._events[e],t]:this._events[e]=t,i(this._events[e])&&!this._events[e].warned){var o;o=s(this._maxListeners)?r.defaultMaxListeners:this._maxListeners,o&&o>0&&this._events[e].length>o&&(this._events[e].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[e].length),"function"==typeof console.trace&&console.trace())}return this},r.prototype.on=r.prototype.addListener,r.prototype.once=function(e,t){function r(){this.removeListener(e,r),o||(o=!0,t.apply(this,arguments))}if(!n(t))throw TypeError("listener must be a function");var o=!1;return r.listener=t,this.on(e,r),this},r.prototype.removeListener=function(e,t){var r,o,s,a;if(!n(t))throw TypeError("listener must be a function");if(!this._events||!this._events[e])return this;if(r=this._events[e],s=r.length,o=-1,r===t||n(r.listener)&&r.listener===t)delete this._events[e],this._events.removeListener&&this.emit("removeListener",e,t);else if(i(r)){for(a=s;a-->0;)if(r[a]===t||r[a].listener&&r[a].listener===t){o=a;break}if(0>o)return this;1===r.length?(r.length=0,delete this._events[e]):r.splice(o,1),this._events.removeListener&&this.emit("removeListener",e,t)}return this},r.prototype.removeAllListeners=function(e){var t,r;if(!this._events)return this;if(!this._events.removeListener)return 0===arguments.length?this._events={}:this._events[e]&&delete this._events[e],this;if(0===arguments.length){for(t in this._events)"removeListener"!==t&&this.removeAllListeners(t);return this.removeAllListeners("removeListener"),this._events={},this}if(r=this._events[e],n(r))this.removeListener(e,r);else for(;r.length;)this.removeListener(e,r[r.length-1]);return delete this._events[e],this},r.prototype.listeners=function(e){var t;return t=this._events&&this._events[e]?n(this._events[e])?[this._events[e]]:this._events[e].slice():[]},r.listenerCount=function(e,t){var r;return r=e._events&&e._events[t]?n(e._events[t])?1:e._events[t].length:0}},{}],22:[function(e,t){t.exports=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)}},{}],23:[function(e,t,r){(function(e){function t(e,t){for(var r=0,n=e.length-1;n>=0;n--){var o=e[n];"."===o?e.splice(n,1):".."===o?(e.splice(n,1),r++):r&&(e.splice(n,1),r--)}if(t)for(;r--;r)e.unshift("..");return e}function n(e,t){if(e.filter)return e.filter(t);for(var r=[],n=0;n<e.length;n++)t(e[n],n,e)&&r.push(e[n]);return r}var o=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/,i=function(e){return o.exec(e).slice(1)};r.resolve=function(){for(var r="",o=!1,i=arguments.length-1;i>=-1&&!o;i--){var s=i>=0?arguments[i]:e.cwd();if("string"!=typeof s)throw new TypeError("Arguments to path.resolve must be strings");s&&(r=s+"/"+r,o="/"===s.charAt(0))}return r=t(n(r.split("/"),function(e){return!!e}),!o).join("/"),(o?"/":"")+r||"."},r.normalize=function(e){var o=r.isAbsolute(e),i="/"===s(e,-1);return e=t(n(e.split("/"),function(e){return!!e}),!o).join("/"),e||o||(e="."),e&&i&&(e+="/"),(o?"/":"")+e},r.isAbsolute=function(e){return"/"===e.charAt(0)},r.join=function(){var e=Array.prototype.slice.call(arguments,0);return r.normalize(n(e,function(e){if("string"!=typeof e)throw new TypeError("Arguments to path.join must be strings");return e}).join("/"))},r.relative=function(e,t){function n(e){for(var t=0;t<e.length&&""===e[t];t++);for(var r=e.length-1;r>=0&&""===e[r];r--);return t>r?[]:e.slice(t,r-t+1)}e=r.resolve(e).substr(1),t=r.resolve(t).substr(1);for(var o=n(e.split("/")),i=n(t.split("/")),s=Math.min(o.length,i.length),a=s,u=0;s>u;u++)if(o[u]!==i[u]){a=u;break}for(var c=[],u=a;u<o.length;u++)c.push("..");return c=c.concat(i.slice(a)),c.join("/")},r.sep="/",r.delimiter=":",r.dirname=function(e){var t=i(e),r=t[0],n=t[1];return r||n?(n&&(n=n.substr(0,n.length-1)),r+n):"."},r.basename=function(e,t){var r=i(e)[2];return t&&r.substr(-1*t.length)===t&&(r=r.substr(0,r.length-t.length)),r},r.extname=function(e){return i(e)[3]};var s="b"==="ab".substr(-1)?function(e,t,r){return e.substr(t,r)}:function(e,t,r){return 0>t&&(t=e.length+t),e.substr(t,r)}}).call(this,e("_process"))},{_process:24}],24:[function(e,t){function r(){}var n=t.exports={};n.nextTick=function(){var e="undefined"!=typeof window&&window.setImmediate,t="undefined"!=typeof window&&window.MutationObserver,r="undefined"!=typeof window&&window.postMessage&&window.addEventListener;if(e)return function(e){return window.setImmediate(e)};var n=[];if(t){var o=document.createElement("div"),i=new MutationObserver(function(){var e=n.slice();n.length=0,e.forEach(function(e){e()})});return i.observe(o,{attributes:!0}),function(e){n.length||o.setAttribute("yes","no"),n.push(e)}}return r?(window.addEventListener("message",function(e){var t=e.source;if((t===window||null===t)&&"process-tick"===e.data&&(e.stopPropagation(),n.length>0)){var r=n.shift();r()}},!0),function(e){n.push(e),window.postMessage("process-tick","*")}):function(e){setTimeout(e,0)}}(),n.title="browser",n.browser=!0,n.env={},n.argv=[],n.on=r,n.addListener=r,n.once=r,n.off=r,n.removeListener=r,n.removeAllListeners=r,n.emit=r,n.binding=function(){throw new Error("process.binding is not supported")},n.cwd=function(){return"/"},n.chdir=function(){throw new Error("process.chdir is not supported")}},{}],25:[function(e,t){t.exports=e("./lib/_stream_duplex.js")},{"./lib/_stream_duplex.js":26}],26:[function(e,t){(function(r){function n(e){return this instanceof n?(u.call(this,e),c.call(this,e),e&&e.readable===!1&&(this.readable=!1),e&&e.writable===!1&&(this.writable=!1),this.allowHalfOpen=!0,e&&e.allowHalfOpen===!1&&(this.allowHalfOpen=!1),void this.once("end",o)):new n(e)}function o(){this.allowHalfOpen||this._writableState.ended||r.nextTick(this.end.bind(this)) +}function i(e,t){for(var r=0,n=e.length;n>r;r++)t(e[r],r)}t.exports=n;var s=Object.keys||function(e){var t=[];for(var r in e)t.push(r);return t},a=e("core-util-is");a.inherits=e("inherits");var u=e("./_stream_readable"),c=e("./_stream_writable");a.inherits(n,u),i(s(c.prototype),function(e){n.prototype[e]||(n.prototype[e]=c.prototype[e])})}).call(this,e("_process"))},{"./_stream_readable":28,"./_stream_writable":30,_process:24,"core-util-is":31,inherits:44}],27:[function(e,t){function r(e){return this instanceof r?void n.call(this,e):new r(e)}t.exports=r;var n=e("./_stream_transform"),o=e("core-util-is");o.inherits=e("inherits"),o.inherits(r,n),r.prototype._transform=function(e,t,r){r(null,e)}},{"./_stream_transform":29,"core-util-is":31,inherits:44}],28:[function(e,t){(function(r){function n(t){t=t||{};var r=t.highWaterMark;this.highWaterMark=r||0===r?r:16384,this.highWaterMark=~~this.highWaterMark,this.buffer=[],this.length=0,this.pipes=null,this.pipesCount=0,this.flowing=!1,this.ended=!1,this.endEmitted=!1,this.reading=!1,this.calledRead=!1,this.sync=!0,this.needReadable=!1,this.emittedReadable=!1,this.readableListening=!1,this.objectMode=!!t.objectMode,this.defaultEncoding=t.defaultEncoding||"utf8",this.ranOut=!1,this.awaitDrain=0,this.readingMore=!1,this.decoder=null,this.encoding=null,t.encoding&&(O||(O=e("string_decoder/").StringDecoder),this.decoder=new O(t.encoding),this.encoding=t.encoding)}function o(e){return this instanceof o?(this._readableState=new n(e,this),this.readable=!0,void A.call(this)):new o(e)}function i(e,t,r,n,o){var i=c(t,r);if(i)e.emit("error",i);else if(null===r||void 0===r)t.reading=!1,t.ended||f(e,t);else if(t.objectMode||r&&r.length>0)if(t.ended&&!o){var a=new Error("stream.push() after EOF");e.emit("error",a)}else if(t.endEmitted&&o){var a=new Error("stream.unshift() after end event");e.emit("error",a)}else!t.decoder||o||n||(r=t.decoder.write(r)),t.length+=t.objectMode?1:r.length,o?t.buffer.unshift(r):(t.reading=!1,t.buffer.push(r)),t.needReadable&&l(e),h(e,t);else o||(t.reading=!1);return s(t)}function s(e){return!e.ended&&(e.needReadable||e.length<e.highWaterMark||0===e.length)}function a(e){if(e>=R)e=R;else{e--;for(var t=1;32>t;t<<=1)e|=e>>t;e++}return e}function u(e,t){return 0===t.length&&t.ended?0:t.objectMode?0===e?0:1:null===e||isNaN(e)?t.flowing&&t.buffer.length?t.buffer[0].length:t.length:0>=e?0:(e>t.highWaterMark&&(t.highWaterMark=a(e)),e>t.length?t.ended?t.length:(t.needReadable=!0,0):e)}function c(e,t){var r=null;return k.isBuffer(t)||"string"==typeof t||null===t||void 0===t||e.objectMode||(r=new TypeError("Invalid non-string/buffer chunk")),r}function f(e,t){if(t.decoder&&!t.ended){var r=t.decoder.end();r&&r.length&&(t.buffer.push(r),t.length+=t.objectMode?1:r.length)}t.ended=!0,t.length>0?l(e):_(e)}function l(e){var t=e._readableState;t.needReadable=!1,t.emittedReadable||(t.emittedReadable=!0,t.sync?r.nextTick(function(){d(e)}):d(e))}function d(e){e.emit("readable")}function h(e,t){t.readingMore||(t.readingMore=!0,r.nextTick(function(){p(e,t)}))}function p(e,t){for(var r=t.length;!t.reading&&!t.flowing&&!t.ended&&t.length<t.highWaterMark&&(e.read(0),r!==t.length);)r=t.length;t.readingMore=!1}function v(e){return function(){var t=e._readableState;t.awaitDrain--,0===t.awaitDrain&&y(e)}}function y(e){function t(e){var t=e.write(r);!1===t&&n.awaitDrain++}var r,n=e._readableState;for(n.awaitDrain=0;n.pipesCount&&null!==(r=e.read());)if(1===n.pipesCount?t(n.pipes,0,null):w(n.pipes,t),e.emit("data",r),n.awaitDrain>0)return;return 0===n.pipesCount?(n.flowing=!1,void(S.listenerCount(e,"data")>0&&m(e))):void(n.ranOut=!0)}function g(){this._readableState.ranOut&&(this._readableState.ranOut=!1,y(this))}function m(e,t){var n=e._readableState;if(n.flowing)throw new Error("Cannot switch to old mode now.");var o=t||!1,i=!1;e.readable=!0,e.pipe=A.prototype.pipe,e.on=e.addListener=A.prototype.on,e.on("readable",function(){i=!0;for(var t;!o&&null!==(t=e.read());)e.emit("data",t);null===t&&(i=!1,e._readableState.needReadable=!0)}),e.pause=function(){o=!0,this.emit("pause")},e.resume=function(){o=!1,i?r.nextTick(function(){e.emit("readable")}):this.read(0),this.emit("resume")},e.emit("readable")}function b(e,t){var r,n=t.buffer,o=t.length,i=!!t.decoder,s=!!t.objectMode;if(0===n.length)return null;if(0===o)r=null;else if(s)r=n.shift();else if(!e||e>=o)r=i?n.join(""):k.concat(n,o),n.length=0;else if(e<n[0].length){var a=n[0];r=a.slice(0,e),n[0]=a.slice(e)}else if(e===n[0].length)r=n.shift();else{r=i?"":new k(e);for(var u=0,c=0,f=n.length;f>c&&e>u;c++){var a=n[0],l=Math.min(e-u,a.length);i?r+=a.slice(0,l):a.copy(r,u,0,l),l<a.length?n[0]=a.slice(l):n.shift(),u+=l}}return r}function _(e){var t=e._readableState;if(t.length>0)throw new Error("endReadable called on non-empty stream");!t.endEmitted&&t.calledRead&&(t.ended=!0,r.nextTick(function(){t.endEmitted||0!==t.length||(t.endEmitted=!0,e.readable=!1,e.emit("end"))}))}function w(e,t){for(var r=0,n=e.length;n>r;r++)t(e[r],r)}function E(e,t){for(var r=0,n=e.length;n>r;r++)if(e[r]===t)return r;return-1}t.exports=o;var x=e("isarray"),k=e("buffer").Buffer;o.ReadableState=n;var S=e("events").EventEmitter;S.listenerCount||(S.listenerCount=function(e,t){return e.listeners(t).length});var A=e("stream"),j=e("core-util-is");j.inherits=e("inherits");var O;j.inherits(o,A),o.prototype.push=function(e,t){var r=this._readableState;return"string"!=typeof e||r.objectMode||(t=t||r.defaultEncoding,t!==r.encoding&&(e=new k(e,t),t="")),i(this,r,e,t,!1)},o.prototype.unshift=function(e){var t=this._readableState;return i(this,t,e,"",!0)},o.prototype.setEncoding=function(t){O||(O=e("string_decoder/").StringDecoder),this._readableState.decoder=new O(t),this._readableState.encoding=t};var R=8388608;o.prototype.read=function(e){var t=this._readableState;t.calledRead=!0;var r,n=e;if(("number"!=typeof e||e>0)&&(t.emittedReadable=!1),0===e&&t.needReadable&&(t.length>=t.highWaterMark||t.ended))return l(this),null;if(e=u(e,t),0===e&&t.ended)return r=null,t.length>0&&t.decoder&&(r=b(e,t),t.length-=r.length),0===t.length&&_(this),r;var o=t.needReadable;return t.length-e<=t.highWaterMark&&(o=!0),(t.ended||t.reading)&&(o=!1),o&&(t.reading=!0,t.sync=!0,0===t.length&&(t.needReadable=!0),this._read(t.highWaterMark),t.sync=!1),o&&!t.reading&&(e=u(n,t)),r=e>0?b(e,t):null,null===r&&(t.needReadable=!0,e=0),t.length-=e,0!==t.length||t.ended||(t.needReadable=!0),t.ended&&!t.endEmitted&&0===t.length&&_(this),r},o.prototype._read=function(){this.emit("error",new Error("not implemented"))},o.prototype.pipe=function(e,t){function n(e){e===f&&i()}function o(){e.end()}function i(){e.removeListener("close",a),e.removeListener("finish",u),e.removeListener("drain",p),e.removeListener("error",s),e.removeListener("unpipe",n),f.removeListener("end",o),f.removeListener("end",i),(!e._writableState||e._writableState.needDrain)&&p()}function s(t){c(),e.removeListener("error",s),0===S.listenerCount(e,"error")&&e.emit("error",t)}function a(){e.removeListener("finish",u),c()}function u(){e.removeListener("close",a),c()}function c(){f.unpipe(e)}var f=this,l=this._readableState;switch(l.pipesCount){case 0:l.pipes=e;break;case 1:l.pipes=[l.pipes,e];break;default:l.pipes.push(e)}l.pipesCount+=1;var d=(!t||t.end!==!1)&&e!==r.stdout&&e!==r.stderr,h=d?o:i;l.endEmitted?r.nextTick(h):f.once("end",h),e.on("unpipe",n);var p=v(f);return e.on("drain",p),e._events&&e._events.error?x(e._events.error)?e._events.error.unshift(s):e._events.error=[s,e._events.error]:e.on("error",s),e.once("close",a),e.once("finish",u),e.emit("pipe",f),l.flowing||(this.on("readable",g),l.flowing=!0,r.nextTick(function(){y(f)})),e},o.prototype.unpipe=function(e){var t=this._readableState;if(0===t.pipesCount)return this;if(1===t.pipesCount)return e&&e!==t.pipes?this:(e||(e=t.pipes),t.pipes=null,t.pipesCount=0,this.removeListener("readable",g),t.flowing=!1,e&&e.emit("unpipe",this),this);if(!e){var r=t.pipes,n=t.pipesCount;t.pipes=null,t.pipesCount=0,this.removeListener("readable",g),t.flowing=!1;for(var o=0;n>o;o++)r[o].emit("unpipe",this);return this}var o=E(t.pipes,e);return-1===o?this:(t.pipes.splice(o,1),t.pipesCount-=1,1===t.pipesCount&&(t.pipes=t.pipes[0]),e.emit("unpipe",this),this)},o.prototype.on=function(e,t){var r=A.prototype.on.call(this,e,t);if("data"!==e||this._readableState.flowing||m(this),"readable"===e&&this.readable){var n=this._readableState;n.readableListening||(n.readableListening=!0,n.emittedReadable=!1,n.needReadable=!0,n.reading?n.length&&l(this,n):this.read(0))}return r},o.prototype.addListener=o.prototype.on,o.prototype.resume=function(){m(this),this.read(0),this.emit("resume")},o.prototype.pause=function(){m(this,!0),this.emit("pause")},o.prototype.wrap=function(e){var t=this._readableState,r=!1,n=this;e.on("end",function(){if(t.decoder&&!t.ended){var e=t.decoder.end();e&&e.length&&n.push(e)}n.push(null)}),e.on("data",function(o){if(t.decoder&&(o=t.decoder.write(o)),(!t.objectMode||null!==o&&void 0!==o)&&(t.objectMode||o&&o.length)){var i=n.push(o);i||(r=!0,e.pause())}});for(var o in e)"function"==typeof e[o]&&"undefined"==typeof this[o]&&(this[o]=function(t){return function(){return e[t].apply(e,arguments)}}(o));var i=["error","close","destroy","pause","resume"];return w(i,function(t){e.on(t,n.emit.bind(n,t))}),n._read=function(){r&&(r=!1,e.resume())},n},o._fromList=b}).call(this,e("_process"))},{_process:24,buffer:17,"core-util-is":31,events:21,inherits:44,isarray:22,stream:36,"string_decoder/":37}],29:[function(e,t){function r(e,t){this.afterTransform=function(e,r){return n(t,e,r)},this.needTransform=!1,this.transforming=!1,this.writecb=null,this.writechunk=null}function n(e,t,r){var n=e._transformState;n.transforming=!1;var o=n.writecb;if(!o)return e.emit("error",new Error("no writecb in Transform class"));n.writechunk=null,n.writecb=null,null!==r&&void 0!==r&&e.push(r),o&&o(t);var i=e._readableState;i.reading=!1,(i.needReadable||i.length<i.highWaterMark)&&e._read(i.highWaterMark)}function o(e){if(!(this instanceof o))return new o(e);s.call(this,e);var t=(this._transformState=new r(e,this),this);this._readableState.needReadable=!0,this._readableState.sync=!1,this.once("finish",function(){"function"==typeof this._flush?this._flush(function(e){i(t,e)}):i(t)})}function i(e,t){if(t)return e.emit("error",t);var r=e._writableState,n=(e._readableState,e._transformState);if(r.length)throw new Error("calling transform done when ws.length != 0");if(n.transforming)throw new Error("calling transform done when still transforming");return e.push(null)}t.exports=o;var s=e("./_stream_duplex"),a=e("core-util-is");a.inherits=e("inherits"),a.inherits(o,s),o.prototype.push=function(e,t){return this._transformState.needTransform=!1,s.prototype.push.call(this,e,t)},o.prototype._transform=function(){throw new Error("not implemented")},o.prototype._write=function(e,t,r){var n=this._transformState;if(n.writecb=r,n.writechunk=e,n.writeencoding=t,!n.transforming){var o=this._readableState;(n.needTransform||o.needReadable||o.length<o.highWaterMark)&&this._read(o.highWaterMark)}},o.prototype._read=function(){var e=this._transformState;null!==e.writechunk&&e.writecb&&!e.transforming?(e.transforming=!0,this._transform(e.writechunk,e.writeencoding,e.afterTransform)):e.needTransform=!0}},{"./_stream_duplex":26,"core-util-is":31,inherits:44}],30:[function(e,t){(function(r){function n(e,t,r){this.chunk=e,this.encoding=t,this.callback=r}function o(e,t){e=e||{};var r=e.highWaterMark;this.highWaterMark=r||0===r?r:16384,this.objectMode=!!e.objectMode,this.highWaterMark=~~this.highWaterMark,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1;var n=e.decodeStrings===!1;this.decodeStrings=!n,this.defaultEncoding=e.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(e){h(t,e)},this.writecb=null,this.writelen=0,this.buffer=[],this.errorEmitted=!1}function i(t){var r=e("./_stream_duplex");return this instanceof i||this instanceof r?(this._writableState=new o(t,this),this.writable=!0,void E.call(this)):new i(t)}function s(e,t,n){var o=new Error("write after end");e.emit("error",o),r.nextTick(function(){n(o)})}function a(e,t,n,o){var i=!0;if(!_.isBuffer(n)&&"string"!=typeof n&&null!==n&&void 0!==n&&!t.objectMode){var s=new TypeError("Invalid non-string/buffer chunk");e.emit("error",s),r.nextTick(function(){o(s)}),i=!1}return i}function u(e,t,r){return e.objectMode||e.decodeStrings===!1||"string"!=typeof t||(t=new _(t,r)),t}function c(e,t,r,o,i){r=u(t,r,o),_.isBuffer(r)&&(o="buffer");var s=t.objectMode?1:r.length;t.length+=s;var a=t.length<t.highWaterMark;return a||(t.needDrain=!0),t.writing?t.buffer.push(new n(r,o,i)):f(e,t,s,r,o,i),a}function f(e,t,r,n,o,i){t.writelen=r,t.writecb=i,t.writing=!0,t.sync=!0,e._write(n,o,t.onwrite),t.sync=!1}function l(e,t,n,o,i){n?r.nextTick(function(){i(o)}):i(o),e._writableState.errorEmitted=!0,e.emit("error",o)}function d(e){e.writing=!1,e.writecb=null,e.length-=e.writelen,e.writelen=0}function h(e,t){var n=e._writableState,o=n.sync,i=n.writecb;if(d(n),t)l(e,n,o,t,i);else{var s=g(e,n);s||n.bufferProcessing||!n.buffer.length||y(e,n),o?r.nextTick(function(){p(e,n,s,i)}):p(e,n,s,i)}}function p(e,t,r,n){r||v(e,t),n(),r&&m(e,t)}function v(e,t){0===t.length&&t.needDrain&&(t.needDrain=!1,e.emit("drain"))}function y(e,t){t.bufferProcessing=!0;for(var r=0;r<t.buffer.length;r++){var n=t.buffer[r],o=n.chunk,i=n.encoding,s=n.callback,a=t.objectMode?1:o.length;if(f(e,t,a,o,i,s),t.writing){r++;break}}t.bufferProcessing=!1,r<t.buffer.length?t.buffer=t.buffer.slice(r):t.buffer.length=0}function g(e,t){return t.ending&&0===t.length&&!t.finished&&!t.writing}function m(e,t){var r=g(e,t);return r&&(t.finished=!0,e.emit("finish")),r}function b(e,t,n){t.ending=!0,m(e,t),n&&(t.finished?r.nextTick(n):e.once("finish",n)),t.ended=!0}t.exports=i;var _=e("buffer").Buffer;i.WritableState=o;var w=e("core-util-is");w.inherits=e("inherits");var E=e("stream");w.inherits(i,E),i.prototype.pipe=function(){this.emit("error",new Error("Cannot pipe. Not readable."))},i.prototype.write=function(e,t,r){var n=this._writableState,o=!1;return"function"==typeof t&&(r=t,t=null),_.isBuffer(e)?t="buffer":t||(t=n.defaultEncoding),"function"!=typeof r&&(r=function(){}),n.ended?s(this,n,r):a(this,n,e,r)&&(o=c(this,n,e,t,r)),o},i.prototype._write=function(e,t,r){r(new Error("not implemented"))},i.prototype.end=function(e,t,r){var n=this._writableState;"function"==typeof e?(r=e,e=null,t=null):"function"==typeof t&&(r=t,t=null),"undefined"!=typeof e&&null!==e&&this.write(e,t),n.ending||n.finished||b(this,n,r)}}).call(this,e("_process"))},{"./_stream_duplex":26,_process:24,buffer:17,"core-util-is":31,inherits:44,stream:36}],31:[function(e,t,r){(function(e){function t(e){return Array.isArray(e)}function n(e){return"boolean"==typeof e}function o(e){return null===e}function i(e){return null==e}function s(e){return"number"==typeof e}function a(e){return"string"==typeof e}function u(e){return"symbol"==typeof e}function c(e){return void 0===e}function f(e){return l(e)&&"[object RegExp]"===g(e)}function l(e){return"object"==typeof e&&null!==e}function d(e){return l(e)&&"[object Date]"===g(e)}function h(e){return l(e)&&("[object Error]"===g(e)||e instanceof Error)}function p(e){return"function"==typeof e}function v(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||"undefined"==typeof e}function y(t){return e.isBuffer(t)}function g(e){return Object.prototype.toString.call(e)}r.isArray=t,r.isBoolean=n,r.isNull=o,r.isNullOrUndefined=i,r.isNumber=s,r.isString=a,r.isSymbol=u,r.isUndefined=c,r.isRegExp=f,r.isObject=l,r.isDate=d,r.isError=h,r.isFunction=p,r.isPrimitive=v,r.isBuffer=y}).call(this,e("buffer").Buffer)},{buffer:17}],32:[function(e,t){t.exports=e("./lib/_stream_passthrough.js")},{"./lib/_stream_passthrough.js":27}],33:[function(e,t,r){var n=e("stream");r=t.exports=e("./lib/_stream_readable.js"),r.Stream=n,r.Readable=r,r.Writable=e("./lib/_stream_writable.js"),r.Duplex=e("./lib/_stream_duplex.js"),r.Transform=e("./lib/_stream_transform.js"),r.PassThrough=e("./lib/_stream_passthrough.js")},{"./lib/_stream_duplex.js":26,"./lib/_stream_passthrough.js":27,"./lib/_stream_readable.js":28,"./lib/_stream_transform.js":29,"./lib/_stream_writable.js":30,stream:36}],34:[function(e,t){t.exports=e("./lib/_stream_transform.js")},{"./lib/_stream_transform.js":29}],35:[function(e,t){t.exports=e("./lib/_stream_writable.js")},{"./lib/_stream_writable.js":30}],36:[function(e,t){function r(){n.call(this)}t.exports=r;var n=e("events").EventEmitter,o=e("inherits");o(r,n),r.Readable=e("readable-stream/readable.js"),r.Writable=e("readable-stream/writable.js"),r.Duplex=e("readable-stream/duplex.js"),r.Transform=e("readable-stream/transform.js"),r.PassThrough=e("readable-stream/passthrough.js"),r.Stream=r,r.prototype.pipe=function(e,t){function r(t){e.writable&&!1===e.write(t)&&c.pause&&c.pause()}function o(){c.readable&&c.resume&&c.resume()}function i(){f||(f=!0,e.end())}function s(){f||(f=!0,"function"==typeof e.destroy&&e.destroy())}function a(e){if(u(),0===n.listenerCount(this,"error"))throw e}function u(){c.removeListener("data",r),e.removeListener("drain",o),c.removeListener("end",i),c.removeListener("close",s),c.removeListener("error",a),e.removeListener("error",a),c.removeListener("end",u),c.removeListener("close",u),e.removeListener("close",u)}var c=this;c.on("data",r),e.on("drain",o),e._isStdio||t&&t.end===!1||(c.on("end",i),c.on("close",s));var f=!1;return c.on("error",a),e.on("error",a),c.on("end",u),c.on("close",u),e.on("close",u),e.emit("pipe",c),e}},{events:21,inherits:44,"readable-stream/duplex.js":25,"readable-stream/passthrough.js":32,"readable-stream/readable.js":33,"readable-stream/transform.js":34,"readable-stream/writable.js":35}],37:[function(e,t,r){function n(e){if(e&&!u(e))throw new Error("Unknown encoding: "+e)}function o(e){return e.toString(this.encoding)}function i(e){this.charReceived=e.length%2,this.charLength=this.charReceived?2:0}function s(e){this.charReceived=e.length%3,this.charLength=this.charReceived?3:0}var a=e("buffer").Buffer,u=a.isEncoding||function(e){switch(e&&e.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}},c=r.StringDecoder=function(e){switch(this.encoding=(e||"utf8").toLowerCase().replace(/[-_]/,""),n(e),this.encoding){case"utf8":this.surrogateSize=3;break;case"ucs2":case"utf16le":this.surrogateSize=2,this.detectIncompleteChar=i;break;case"base64":this.surrogateSize=3,this.detectIncompleteChar=s;break;default:return void(this.write=o)}this.charBuffer=new a(6),this.charReceived=0,this.charLength=0};c.prototype.write=function(e){for(var t="";this.charLength;){var r=e.length>=this.charLength-this.charReceived?this.charLength-this.charReceived:e.length;if(e.copy(this.charBuffer,this.charReceived,0,r),this.charReceived+=r,this.charReceived<this.charLength)return"";e=e.slice(r,e.length),t=this.charBuffer.slice(0,this.charLength).toString(this.encoding);var n=t.charCodeAt(t.length-1);if(!(n>=55296&&56319>=n)){if(this.charReceived=this.charLength=0,0===e.length)return t;break}this.charLength+=this.surrogateSize,t=""}this.detectIncompleteChar(e);var o=e.length;this.charLength&&(e.copy(this.charBuffer,0,e.length-this.charReceived,o),o-=this.charReceived),t+=e.toString(this.encoding,0,o);var o=t.length-1,n=t.charCodeAt(o);if(n>=55296&&56319>=n){var i=this.surrogateSize;return this.charLength+=i,this.charReceived+=i,this.charBuffer.copy(this.charBuffer,i,0,i),e.copy(this.charBuffer,0,0,i),t.substring(0,o)}return t},c.prototype.detectIncompleteChar=function(e){for(var t=e.length>=3?3:e.length;t>0;t--){var r=e[e.length-t];if(1==t&&r>>5==6){this.charLength=2;break}if(2>=t&&r>>4==14){this.charLength=3;break}if(3>=t&&r>>3==30){this.charLength=4;break}}this.charReceived=t},c.prototype.end=function(e){var t="";if(e&&e.length&&(t=this.write(e)),this.charReceived){var r=this.charReceived,n=this.charBuffer,o=this.encoding;t+=n.slice(0,r).toString(o)}return t}},{buffer:17}],38:[function(e,t){t.exports=function(e){return e&&"object"==typeof e&&"function"==typeof e.copy&&"function"==typeof e.fill&&"function"==typeof e.readUInt8}},{}],39:[function(e,t,r){(function(t,n){function o(e,t){var n={seen:[],stylize:s};return arguments.length>=3&&(n.depth=arguments[2]),arguments.length>=4&&(n.colors=arguments[3]),v(t)?n.showHidden=t:t&&r._extend(n,t),w(n.showHidden)&&(n.showHidden=!1),w(n.depth)&&(n.depth=2),w(n.colors)&&(n.colors=!1),w(n.customInspect)&&(n.customInspect=!0),n.colors&&(n.stylize=i),u(n,e,n.depth)}function i(e,t){var r=o.styles[t];return r?"["+o.colors[r][0]+"m"+e+"["+o.colors[r][1]+"m":e}function s(e){return e}function a(e){var t={};return e.forEach(function(e){t[e]=!0}),t}function u(e,t,n){if(e.customInspect&&t&&A(t.inspect)&&t.inspect!==r.inspect&&(!t.constructor||t.constructor.prototype!==t)){var o=t.inspect(n,e);return b(o)||(o=u(e,o,n)),o}var i=c(e,t);if(i)return i;var s=Object.keys(t),v=a(s);if(e.showHidden&&(s=Object.getOwnPropertyNames(t)),S(t)&&(s.indexOf("message")>=0||s.indexOf("description")>=0))return f(t);if(0===s.length){if(A(t)){var y=t.name?": "+t.name:"";return e.stylize("[Function"+y+"]","special")}if(E(t))return e.stylize(RegExp.prototype.toString.call(t),"regexp");if(k(t))return e.stylize(Date.prototype.toString.call(t),"date");if(S(t))return f(t)}var g="",m=!1,_=["{","}"];if(p(t)&&(m=!0,_=["[","]"]),A(t)){var w=t.name?": "+t.name:"";g=" [Function"+w+"]"}if(E(t)&&(g=" "+RegExp.prototype.toString.call(t)),k(t)&&(g=" "+Date.prototype.toUTCString.call(t)),S(t)&&(g=" "+f(t)),0===s.length&&(!m||0==t.length))return _[0]+g+_[1];if(0>n)return E(t)?e.stylize(RegExp.prototype.toString.call(t),"regexp"):e.stylize("[Object]","special");e.seen.push(t);var x;return x=m?l(e,t,n,v,s):s.map(function(r){return d(e,t,n,v,r,m)}),e.seen.pop(),h(x,g,_)}function c(e,t){if(w(t))return e.stylize("undefined","undefined");if(b(t)){var r="'"+JSON.stringify(t).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return e.stylize(r,"string")}return m(t)?e.stylize(""+t,"number"):v(t)?e.stylize(""+t,"boolean"):y(t)?e.stylize("null","null"):void 0}function f(e){return"["+Error.prototype.toString.call(e)+"]"}function l(e,t,r,n,o){for(var i=[],s=0,a=t.length;a>s;++s)i.push(N(t,String(s))?d(e,t,r,n,String(s),!0):"");return o.forEach(function(o){o.match(/^\d+$/)||i.push(d(e,t,r,n,o,!0))}),i}function d(e,t,r,n,o,i){var s,a,c;if(c=Object.getOwnPropertyDescriptor(t,o)||{value:t[o]},c.get?a=c.set?e.stylize("[Getter/Setter]","special"):e.stylize("[Getter]","special"):c.set&&(a=e.stylize("[Setter]","special")),N(n,o)||(s="["+o+"]"),a||(e.seen.indexOf(c.value)<0?(a=y(r)?u(e,c.value,null):u(e,c.value,r-1),a.indexOf("\n")>-1&&(a=i?a.split("\n").map(function(e){return" "+e}).join("\n").substr(2):"\n"+a.split("\n").map(function(e){return" "+e}).join("\n"))):a=e.stylize("[Circular]","special")),w(s)){if(i&&o.match(/^\d+$/))return a;s=JSON.stringify(""+o),s.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(s=s.substr(1,s.length-2),s=e.stylize(s,"name")):(s=s.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),s=e.stylize(s,"string"))}return s+": "+a}function h(e,t,r){var n=0,o=e.reduce(function(e,t){return n++,t.indexOf("\n")>=0&&n++,e+t.replace(/\u001b\[\d\d?m/g,"").length+1},0);return o>60?r[0]+(""===t?"":t+"\n ")+" "+e.join(",\n ")+" "+r[1]:r[0]+t+" "+e.join(", ")+" "+r[1]}function p(e){return Array.isArray(e)}function v(e){return"boolean"==typeof e}function y(e){return null===e}function g(e){return null==e}function m(e){return"number"==typeof e}function b(e){return"string"==typeof e}function _(e){return"symbol"==typeof e}function w(e){return void 0===e}function E(e){return x(e)&&"[object RegExp]"===O(e)}function x(e){return"object"==typeof e&&null!==e}function k(e){return x(e)&&"[object Date]"===O(e)}function S(e){return x(e)&&("[object Error]"===O(e)||e instanceof Error)}function A(e){return"function"==typeof e}function j(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||"undefined"==typeof e}function O(e){return Object.prototype.toString.call(e)}function R(e){return 10>e?"0"+e.toString(10):e.toString(10)}function I(){var e=new Date,t=[R(e.getHours()),R(e.getMinutes()),R(e.getSeconds())].join(":");return[e.getDate(),B[e.getMonth()],t].join(" ")}function N(e,t){return Object.prototype.hasOwnProperty.call(e,t)}var T=/%[sdj%]/g;r.format=function(e){if(!b(e)){for(var t=[],r=0;r<arguments.length;r++)t.push(o(arguments[r]));return t.join(" ")}for(var r=1,n=arguments,i=n.length,s=String(e).replace(T,function(e){if("%"===e)return"%";if(r>=i)return e;switch(e){case"%s":return String(n[r++]);case"%d":return Number(n[r++]);case"%j":try{return JSON.stringify(n[r++])}catch(t){return"[Circular]"}default:return e}}),a=n[r];i>r;a=n[++r])s+=y(a)||!x(a)?" "+a:" "+o(a);return s},r.deprecate=function(e,o){function i(){if(!s){if(t.throwDeprecation)throw new Error(o);t.traceDeprecation?console.trace(o):console.error(o),s=!0}return e.apply(this,arguments)}if(w(n.process))return function(){return r.deprecate(e,o).apply(this,arguments)};if(t.noDeprecation===!0)return e;var s=!1;return i};var L,D={};r.debuglog=function(e){if(w(L)&&(L=t.env.NODE_DEBUG||""),e=e.toUpperCase(),!D[e])if(new RegExp("\\b"+e+"\\b","i").test(L)){var n=t.pid;D[e]=function(){var t=r.format.apply(r,arguments);console.error("%s %d: %s",e,n,t)}}else D[e]=function(){};return D[e]},r.inspect=o,o.colors={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},o.styles={special:"cyan",number:"yellow","boolean":"yellow",undefined:"grey","null":"bold",string:"green",date:"magenta",regexp:"red"},r.isArray=p,r.isBoolean=v,r.isNull=y,r.isNullOrUndefined=g,r.isNumber=m,r.isString=b,r.isSymbol=_,r.isUndefined=w,r.isRegExp=E,r.isObject=x,r.isDate=k,r.isError=S,r.isFunction=A,r.isPrimitive=j,r.isBuffer=e("./support/isBuffer");var B=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];r.log=function(){console.log("%s - %s",I(),r.format.apply(r,arguments))},r.inherits=e("inherits"),r._extend=function(e,t){if(!t||!x(t))return e;for(var r=Object.keys(t),n=r.length;n--;)e[r[n]]=t[r[n]];return e}}).call(this,e("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./support/isBuffer":38,_process:24,inherits:44}],40:[function(e,t,r){function n(){return"WebkitAppearance"in document.documentElement.style||window.console&&(console.firebug||console.exception&&console.table)||navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)&&parseInt(RegExp.$1,10)>=31}function o(){var e=arguments,t=this.useColors;if(e[0]=(t?"%c":"")+this.namespace+(t?" %c":" ")+e[0]+(t?"%c ":" ")+"+"+r.humanize(this.diff),!t)return e;var n="color: "+this.color;e=[e[0],n,"color: inherit"].concat(Array.prototype.slice.call(e,1));var o=0,i=0;return e[0].replace(/%[a-z%]/g,function(e){"%"!==e&&(o++,"%c"===e&&(i=o))}),e.splice(i,0,n),e}function i(){return"object"==typeof console&&"function"==typeof console.log&&Function.prototype.apply.call(console.log,console,arguments)}function s(e){try{null==e?localStorage.removeItem("debug"):localStorage.debug=e}catch(t){}}function a(){var e;try{e=localStorage.debug}catch(t){}return e}r=t.exports=e("./debug"),r.log=i,r.formatArgs=o,r.save=s,r.load=a,r.useColors=n,r.colors=["lightseagreen","forestgreen","goldenrod","dodgerblue","darkorchid","crimson"],r.formatters.j=function(e){return JSON.stringify(e)},r.enable(a())},{"./debug":41}],41:[function(e,t,r){function n(){return r.colors[f++%r.colors.length]}function o(e){function t(){}function o(){var e=o,t=+new Date,i=t-(c||t);e.diff=i,e.prev=c,e.curr=t,c=t,null==e.useColors&&(e.useColors=r.useColors()),null==e.color&&e.useColors&&(e.color=n());var s=Array.prototype.slice.call(arguments);s[0]=r.coerce(s[0]),"string"!=typeof s[0]&&(s=["%o"].concat(s));var a=0;s[0]=s[0].replace(/%([a-z%])/g,function(t,n){if("%"===t)return t;a++;var o=r.formatters[n];if("function"==typeof o){var i=s[a];t=o.call(e,i),s.splice(a,1),a--}return t}),"function"==typeof r.formatArgs&&(s=r.formatArgs.apply(e,s));var u=o.log||r.log||console.log.bind(console);u.apply(e,s)}t.enabled=!1,o.enabled=!0;var i=r.enabled(e)?o:t;return i.namespace=e,i}function i(e){r.save(e);for(var t=(e||"").split(/[\s,]+/),n=t.length,o=0;n>o;o++)t[o]&&(e=t[o].replace(/\*/g,".*?"),"-"===e[0]?r.skips.push(new RegExp("^"+e.substr(1)+"$")):r.names.push(new RegExp("^"+e+"$")))}function s(){r.enable("")}function a(e){var t,n;for(t=0,n=r.skips.length;n>t;t++)if(r.skips[t].test(e))return!1;for(t=0,n=r.names.length;n>t;t++)if(r.names[t].test(e))return!0;return!1}function u(e){return e instanceof Error?e.stack||e.message:e}r=t.exports=o,r.coerce=u,r.disable=s,r.enable=i,r.enabled=a,r.humanize=e("ms"),r.names=[],r.skips=[],r.formatters={};var c,f=0},{ms:42}],42:[function(e,t){function r(e){var t=/^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(e);if(t){var r=parseFloat(t[1]),n=(t[2]||"ms").toLowerCase();switch(n){case"years":case"year":case"y":return r*f;case"days":case"day":case"d":return r*c;case"hours":case"hour":case"h":return r*u;case"minutes":case"minute":case"m":return r*a;case"seconds":case"second":case"s":return r*s;case"ms":return r}}}function n(e){return e>=c?Math.round(e/c)+"d":e>=u?Math.round(e/u)+"h":e>=a?Math.round(e/a)+"m":e>=s?Math.round(e/s)+"s":e+"ms"}function o(e){return i(e,c,"day")||i(e,u,"hour")||i(e,a,"minute")||i(e,s,"second")||e+" ms"}function i(e,t,r){return t>e?void 0:1.5*t>e?Math.floor(e/t)+" "+r:Math.ceil(e/t)+" "+r+"s"}var s=1e3,a=60*s,u=60*a,c=24*u,f=365.25*c;t.exports=function(e,t){return t=t||{},"string"==typeof e?r(e):t.long?o(e):n(e)}},{}],43:[function(e,t){"use strict";function r(e){if(this._capacity=i(e),this._length=0,this._front=0,this._makeCapacity(),s(e)){for(var t=e.length,r=0;t>r;++r)this[r]=e[r];this._length=t}}function n(e,t,r,n,o){for(var i=0;o>i;++i)r[i+n]=e[i+t]}function o(e){return e>>>=0,e-=1,e|=e>>1,e|=e>>2,e|=e>>4,e|=e>>8,e|=e>>16,e+1}function i(e){if("number"!=typeof e){if(!s(e))return 16;e=e.length}return o(Math.min(Math.max(16,e),1073741824))}r.prototype.toArray=function(){for(var e=this._length,t=new Array(e),r=this._front,n=this._capacity,o=0;e>o;++o)t[o]=this[r+o&n-1];return t},r.prototype.push=function(e){var t=arguments.length,r=this._length;if(t>1){var n=this._capacity;if(r+t>n){for(var o=0;t>o;++o){this._checkCapacity(r+1);var i=this._front+r&this._capacity-1;this[i]=arguments[o],r++,this._length=r}return r}for(var i=this._front,o=0;t>o;++o)this[i+r&n-1]=arguments[o],i++;return this._length=r+t,r+t}if(0===t)return r;this._checkCapacity(r+1);var o=this._front+r&this._capacity-1;return this[o]=e,this._length=r+1,r+1},r.prototype.pop=function(){var e=this._length;if(0===e)return void 0;var t=this._front+e-1&this._capacity-1,r=this[t];return this[t]=void 0,this._length=e-1,r},r.prototype.shift=function(){var e=this._length;if(0===e)return void 0;var t=this._front,r=this[t];return this[t]=void 0,this._front=t+1&this._capacity-1,this._length=e-1,r},r.prototype.unshift=function(e){var t=this._length,r=arguments.length;if(r>1){var n=this._capacity;if(t+r>n){for(var o=r-1;o>=0;o--){this._checkCapacity(t+1);var n=this._capacity,i=(this._front-1&n-1^n)-n;this[i]=arguments[o],t++,this._length=t,this._front=i}return t}for(var s=this._front,o=r-1;o>=0;o--){var i=(s-1&n-1^n)-n;this[i]=arguments[o],s=i}return this._front=s,this._length=t+r,t+r}if(0===r)return t;this._checkCapacity(t+1);var n=this._capacity,o=(this._front-1&n-1^n)-n;return this[o]=e,this._length=t+1,this._front=o,t+1},r.prototype.peekBack=function(){var e=this._length;if(0===e)return void 0;var t=this._front+e-1&this._capacity-1;return this[t]},r.prototype.peekFront=function(){return 0===this._length?void 0:this[this._front] +},r.prototype.get=function(e){var t=e;if(t!==(0|t))return void 0;var r=this._length;return 0>t&&(t+=r),0>t||t>=r?void 0:this[this._front+t&this._capacity-1]},r.prototype.isEmpty=function(){return 0===this._length},r.prototype.clear=function(){this._length=0,this._front=0,this._makeCapacity()},r.prototype.toString=function(){return this.toArray().toString()},r.prototype.valueOf=r.prototype.toString,r.prototype.removeFront=r.prototype.shift,r.prototype.removeBack=r.prototype.pop,r.prototype.insertFront=r.prototype.unshift,r.prototype.insertBack=r.prototype.push,r.prototype.enqueue=r.prototype.push,r.prototype.dequeue=r.prototype.shift,r.prototype.toJSON=r.prototype.toArray,Object.defineProperty(r.prototype,"length",{get:function(){return this._length},set:function(){throw new RangeError("")}}),r.prototype._makeCapacity=function(){for(var e=this._capacity,t=0;e>t;++t)this[t]=void 0},r.prototype._checkCapacity=function(e){this._capacity<e&&this._resizeTo(i(1.5*this._capacity+16))},r.prototype._resizeTo=function(e){var t=this._front,r=this._capacity,o=new Array(r),i=this._length;if(n(this,0,o,0,r),this._capacity=e,this._makeCapacity(),this._front=0,r>=t+i)n(o,t,this,0,i);else{var s=i-(t+i&r-1);n(o,t,this,0,s),n(o,0,this,s,i-s)}};var s=Array.isArray;t.exports=r},{}],44:[function(e,t){t.exports="function"==typeof Object.create?function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:function(e,t){e.super_=t;var r=function(){};r.prototype=t.prototype,e.prototype=new r,e.prototype.constructor=e}},{}],45:[function(e,t){function r(e,t){t||(t={}),this.options=t,o.call(this,e),this._order=t.reverse?"DESC":"ASC",this._limit=t.limit,this._count=0,this._done=!1;var r=i.lowerBound(t),n=i.upperBound(t);this._keyRange=r||n?this.db.makeKeyRange({lower:r,upper:n,excludeLower:i.lowerBoundExclusive(t),excludeUpper:i.upperBoundExclusive(t)}):null,this.callback=null}var n=e("util"),o=e("abstract-leveldown").AbstractIterator,i=e("ltgt");t.exports=r,n.inherits(r,o),r.prototype.createIterator=function(){var e=this;e.iterator=e.db.iterate(function(){e.onItem.apply(e,arguments)},{keyRange:e._keyRange,autoContinue:!1,order:e._order,onError:function(e){console.log("horrible error",e)}})},r.prototype.onItem=function(e,t){if(!t&&this.callback)return this.callback(),void(this.callback=!1);var r=!0;this._limit&&this._limit>0&&this._count++>=this._limit&&(r=!1),r&&this.callback(!1,t.key,t.value),t&&t["continue"]()},r.prototype._next=function(e){return e?(this._started||(this.createIterator(),this._started=!0),void(this.callback=e)):new Error("next() requires a callback argument")}},{"abstract-leveldown":48,ltgt:52,util:39}],46:[function(e,t){(function(e){function r(e){this._db=e,this._operations=[],this._written=!1}r.prototype._checkWritten=function(){if(this._written)throw new Error("write() already called on this batch")},r.prototype.put=function(e,t){this._checkWritten();var r=this._db._checkKeyValue(e,"key",this._db._isBuffer);if(r)throw r;if(r=this._db._checkKeyValue(t,"value",this._db._isBuffer))throw r;return this._db._isBuffer(e)||(e=String(e)),this._db._isBuffer(t)||(t=String(t)),"function"==typeof this._put?this._put(e,t):this._operations.push({type:"put",key:e,value:t}),this},r.prototype.del=function(e){this._checkWritten();var t=this._db._checkKeyValue(e,"key",this._db._isBuffer);if(t)throw t;return this._db._isBuffer(e)||(e=String(e)),"function"==typeof this._del?this._del(e):this._operations.push({type:"del",key:e}),this},r.prototype.clear=function(){return this._checkWritten(),this._operations=[],"function"==typeof this._clear&&this._clear(),this},r.prototype.write=function(t,r){if(this._checkWritten(),"function"==typeof t&&(r=t),"function"!=typeof r)throw new Error("write() requires a callback argument");return"object"!=typeof t&&(t={}),this._written=!0,"function"==typeof this._write?this._write(r):"function"==typeof this._db._batch?this._db._batch(this._operations,t,r):void e.nextTick(r)},t.exports=r}).call(this,e("_process"))},{_process:24}],47:[function(e,t){(function(e){function r(e){this.db=e,this._ended=!1,this._nexting=!1}r.prototype.next=function(t){var r=this;if("function"!=typeof t)throw new Error("next() requires a callback argument");return r._ended?t(new Error("cannot call next() after end()")):r._nexting?t(new Error("cannot call next() before previous next() has completed")):(r._nexting=!0,"function"==typeof r._next?r._next(function(){r._nexting=!1,t.apply(null,arguments)}):void e.nextTick(function(){r._nexting=!1,t()}))},r.prototype.end=function(t){if("function"!=typeof t)throw new Error("end() requires a callback argument");return this._ended?t(new Error("end() already called on iterator")):(this._ended=!0,"function"==typeof this._end?this._end(t):void e.nextTick(t))},t.exports=r}).call(this,e("_process"))},{_process:24}],48:[function(e,t){(function(r,n){function o(e){if(!arguments.length||void 0===e)throw new Error("constructor requires at least a location argument");if("string"!=typeof e)throw new Error("constructor requires a location string argument");this.location=e}var i=e("xtend"),s=e("./abstract-iterator"),a=e("./abstract-chained-batch");o.prototype.open=function(e,t){if("function"==typeof e&&(t=e),"function"!=typeof t)throw new Error("open() requires a callback argument");return"object"!=typeof e&&(e={}),"function"==typeof this._open?this._open(e,t):void r.nextTick(t)},o.prototype.close=function(e){if("function"!=typeof e)throw new Error("close() requires a callback argument");return"function"==typeof this._close?this._close(e):void r.nextTick(e)},o.prototype.get=function(e,t,n){var o;if("function"==typeof t&&(n=t),"function"!=typeof n)throw new Error("get() requires a callback argument");return(o=this._checkKeyValue(e,"key",this._isBuffer))?n(o):(this._isBuffer(e)||(e=String(e)),"object"!=typeof t&&(t={}),"function"==typeof this._get?this._get(e,t,n):void r.nextTick(function(){n(new Error("NotFound"))}))},o.prototype.put=function(e,t,n,o){var i;if("function"==typeof n&&(o=n),"function"!=typeof o)throw new Error("put() requires a callback argument");return(i=this._checkKeyValue(e,"key",this._isBuffer))?o(i):(i=this._checkKeyValue(t,"value",this._isBuffer))?o(i):(this._isBuffer(e)||(e=String(e)),this._isBuffer(t)||r.browser||(t=String(t)),"object"!=typeof n&&(n={}),"function"==typeof this._put?this._put(e,t,n,o):void r.nextTick(o))},o.prototype.del=function(e,t,n){var o;if("function"==typeof t&&(n=t),"function"!=typeof n)throw new Error("del() requires a callback argument");return(o=this._checkKeyValue(e,"key",this._isBuffer))?n(o):(this._isBuffer(e)||(e=String(e)),"object"!=typeof t&&(t={}),"function"==typeof this._del?this._del(e,t,n):void r.nextTick(n))},o.prototype.batch=function(e,t,n){if(!arguments.length)return this._chainedBatch();if("function"==typeof t&&(n=t),"function"!=typeof n)throw new Error("batch(array) requires a callback argument");if(!Array.isArray(e))return n(new Error("batch(array) requires an array argument"));"object"!=typeof t&&(t={});for(var o,i,s=0,a=e.length;a>s;s++)if(o=e[s],"object"==typeof o){if(i=this._checkKeyValue(o.type,"type",this._isBuffer))return n(i);if(i=this._checkKeyValue(o.key,"key",this._isBuffer))return n(i);if("put"==o.type&&(i=this._checkKeyValue(o.value,"value",this._isBuffer)))return n(i)}return"function"==typeof this._batch?this._batch(e,t,n):void r.nextTick(n)},o.prototype.approximateSize=function(e,t,n){if(null==e||null==t||"function"==typeof e||"function"==typeof t)throw new Error("approximateSize() requires valid `start`, `end` and `callback` arguments");if("function"!=typeof n)throw new Error("approximateSize() requires a callback argument");return this._isBuffer(e)||(e=String(e)),this._isBuffer(t)||(t=String(t)),"function"==typeof this._approximateSize?this._approximateSize(e,t,n):void r.nextTick(function(){n(null,0)})},o.prototype._setupIteratorOptions=function(e){var t=this;return e=i(e),["start","end","gt","gte","lt","lte"].forEach(function(r){e[r]&&t._isBuffer(e[r])&&0===e[r].length&&delete e[r]}),e.reverse=!!e.reverse,e.reverse&&e.lt&&(e.start=e.lt),e.reverse&&e.lte&&(e.start=e.lte),!e.reverse&&e.gt&&(e.start=e.gt),!e.reverse&&e.gte&&(e.start=e.gte),(e.reverse&&e.lt&&!e.lte||!e.reverse&&e.gt&&!e.gte)&&(e.exclusiveStart=!0),e},o.prototype.iterator=function(e){return"object"!=typeof e&&(e={}),e=this._setupIteratorOptions(e),"function"==typeof this._iterator?this._iterator(e):new s(this)},o.prototype._chainedBatch=function(){return new a(this)},o.prototype._isBuffer=function(e){return n.isBuffer(e)},o.prototype._checkKeyValue=function(e,t){if(null===e||void 0===e)return new Error(t+" cannot be `null` or `undefined`");if(this._isBuffer(e)){if(0===e.length)return new Error(t+" cannot be an empty Buffer")}else if(""===String(e))return new Error(t+" cannot be an empty String")},t.exports.AbstractLevelDOWN=o,t.exports.AbstractIterator=s,t.exports.AbstractChainedBatch=a}).call(this,e("_process"),e("buffer").Buffer)},{"./abstract-chained-batch":46,"./abstract-iterator":47,_process:24,buffer:17,xtend:49}],49:[function(e,t){function r(){for(var e={},t=0;t<arguments.length;t++){var r=arguments[t];for(var n in r)r.hasOwnProperty(n)&&(e[n]=r[n])}return e}t.exports=r},{}],50:[function(e,t){!function(e,r,n){"function"==typeof define?define(r):"undefined"!=typeof t&&t.exports?t.exports=r():n[e]=r()}("IDBStore",function(){"use strict";var e=function(e){throw e},t={storeName:"Store",storePrefix:"IDBWrapper-",dbVersion:1,keyPath:"id",autoIncrement:!0,onStoreReady:function(){},onError:e,indexes:[]},r=function(e,r){"undefined"==typeof r&&"function"==typeof e&&(r=e),"[object Object]"!=Object.prototype.toString.call(e)&&(e={});for(var n in t)this[n]="undefined"!=typeof e[n]?e[n]:t[n];this.dbName=this.storePrefix+this.storeName,this.dbVersion=parseInt(this.dbVersion,10)||1,r&&(this.onStoreReady=r);var o="object"==typeof window?window:self;this.idb=o.indexedDB||o.webkitIndexedDB||o.mozIndexedDB,this.keyRange=o.IDBKeyRange||o.webkitIDBKeyRange||o.mozIDBKeyRange,this.features={hasAutoIncrement:!o.mozIndexedDB},this.consts={READ_ONLY:"readonly",READ_WRITE:"readwrite",VERSION_CHANGE:"versionchange",NEXT:"next",NEXT_NO_DUPLICATE:"nextunique",PREV:"prev",PREV_NO_DUPLICATE:"prevunique"},this.openDB()};r.prototype={constructor:r,version:"1.4.1",db:null,dbName:null,dbVersion:null,store:null,storeName:null,keyPath:null,autoIncrement:null,indexes:null,features:null,onStoreReady:null,onError:null,_insertIdCount:0,openDB:function(){var e=this.idb.open(this.dbName,this.dbVersion),t=!1;e.onerror=function(e){var t=!1;"error"in e.target?t="VersionError"==e.target.error.name:"errorCode"in e.target&&(t=12==e.target.errorCode),this.onError(t?new Error("The version number provided is lower than the existing one."):e)}.bind(this),e.onsuccess=function(e){if(!t){if(this.db)return void this.onStoreReady();if(this.db=e.target.result,"string"==typeof this.db.version)return void this.onError(new Error("The IndexedDB implementation in this browser is outdated. Please upgrade your browser."));if(!this.db.objectStoreNames.contains(this.storeName))return void this.onError(new Error("Something is wrong with the IndexedDB implementation in this browser. Please upgrade your browser."));var r=this.db.transaction([this.storeName],this.consts.READ_ONLY);this.store=r.objectStore(this.storeName);var n=Array.prototype.slice.call(this.getIndexList());this.indexes.forEach(function(e){var r=e.name;if(!r)return t=!0,void this.onError(new Error("Cannot create index: No index name given."));if(this.normalizeIndexData(e),this.hasIndex(r)){var o=this.store.index(r),i=this.indexComplies(o,e);i||(t=!0,this.onError(new Error('Cannot modify index "'+r+'" for current version. Please bump version number to '+(this.dbVersion+1)+"."))),n.splice(n.indexOf(r),1)}else t=!0,this.onError(new Error('Cannot create new index "'+r+'" for current version. Please bump version number to '+(this.dbVersion+1)+"."))},this),n.length&&(t=!0,this.onError(new Error('Cannot delete index(es) "'+n.toString()+'" for current version. Please bump version number to '+(this.dbVersion+1)+"."))),t||this.onStoreReady()}}.bind(this),e.onupgradeneeded=function(e){if(this.db=e.target.result,this.db.objectStoreNames.contains(this.storeName))this.store=e.target.transaction.objectStore(this.storeName);else{var r={autoIncrement:this.autoIncrement};null!==this.keyPath&&(r.keyPath=this.keyPath),this.store=this.db.createObjectStore(this.storeName,r)}var n=Array.prototype.slice.call(this.getIndexList());this.indexes.forEach(function(e){var r=e.name;if(r||(t=!0,this.onError(new Error("Cannot create index: No index name given."))),this.normalizeIndexData(e),this.hasIndex(r)){var o=this.store.index(r),i=this.indexComplies(o,e);i||(this.store.deleteIndex(r),this.store.createIndex(r,e.keyPath,{unique:e.unique,multiEntry:e.multiEntry})),n.splice(n.indexOf(r),1)}else this.store.createIndex(r,e.keyPath,{unique:e.unique,multiEntry:e.multiEntry})},this),n.length&&n.forEach(function(e){this.store.deleteIndex(e)},this)}.bind(this)},deleteDatabase:function(){this.idb.deleteDatabase&&this.idb.deleteDatabase(this.dbName)},put:function(t,r,o,i){null!==this.keyPath&&(i=o,o=r,r=t),i||(i=e),o||(o=n);var s,a=!1,u=null,c=this.db.transaction([this.storeName],this.consts.READ_WRITE);return c.oncomplete=function(){var e=a?o:i;e(u)},c.onabort=i,c.onerror=i,null!==this.keyPath?(this._addIdPropertyIfNeeded(r),s=c.objectStore(this.storeName).put(r)):s=c.objectStore(this.storeName).put(r,t),s.onsuccess=function(e){a=!0,u=e.target.result},s.onerror=i,c},get:function(t,r,o){o||(o=e),r||(r=n);var i=!1,s=null,a=this.db.transaction([this.storeName],this.consts.READ_ONLY);a.oncomplete=function(){var e=i?r:o;e(s)},a.onabort=o,a.onerror=o;var u=a.objectStore(this.storeName).get(t);return u.onsuccess=function(e){i=!0,s=e.target.result},u.onerror=o,a},remove:function(t,r,o){o||(o=e),r||(r=n);var i=!1,s=null,a=this.db.transaction([this.storeName],this.consts.READ_WRITE);a.oncomplete=function(){var e=i?r:o;e(s)},a.onabort=o,a.onerror=o;var u=a.objectStore(this.storeName)["delete"](t);return u.onsuccess=function(e){i=!0,s=e.target.result},u.onerror=o,a},batch:function(t,r,o){o||(o=e),r||(r=n),"[object Array]"!=Object.prototype.toString.call(t)&&o(new Error("dataArray argument must be of type Array."));var i=this.db.transaction([this.storeName],this.consts.READ_WRITE);i.oncomplete=function(){var e=u?r:o;e(u)},i.onabort=o,i.onerror=o;var s=t.length,a=!1,u=!1,c=function(){s--,0!==s||a||(a=!0,u=!0)};return t.forEach(function(e){var t=e.type,r=e.key,n=e.value,s=function(e){i.abort(),a||(a=!0,o(e,t,r))};if("remove"==t){var u=i.objectStore(this.storeName)["delete"](r);u.onsuccess=c,u.onerror=s}else if("put"==t){var f;null!==this.keyPath?(this._addIdPropertyIfNeeded(n),f=i.objectStore(this.storeName).put(n)):f=i.objectStore(this.storeName).put(n,r),f.onsuccess=c,f.onerror=s}},this),i},putBatch:function(e,t,r){var n=e.map(function(e){return{type:"put",value:e}});return this.batch(n,t,r)},removeBatch:function(e,t,r){var n=e.map(function(e){return{type:"remove",key:e}});return this.batch(n,t,r)},getBatch:function(t,r,o,i){o||(o=e),r||(r=n),i||(i="sparse"),"[object Array]"!=Object.prototype.toString.call(t)&&o(new Error("keyArray argument must be of type Array."));var s=this.db.transaction([this.storeName],this.consts.READ_ONLY);s.oncomplete=function(){var e=f?r:o;e(l)},s.onabort=o,s.onerror=o;var a=[],u=t.length,c=!1,f=!1,l=null,d=function(e){e.target.result||"dense"==i?a.push(e.target.result):"sparse"==i&&a.length++,u--,0===u&&(c=!0,f=!0,l=a)};return t.forEach(function(e){var t=function(e){c=!0,l=e,o(e),s.abort()},r=s.objectStore(this.storeName).get(e);r.onsuccess=d,r.onerror=t},this),s},getAll:function(t,r){r||(r=e),t||(t=n);var o=this.db.transaction([this.storeName],this.consts.READ_ONLY),i=o.objectStore(this.storeName);return i.getAll?this._getAllNative(o,i,t,r):this._getAllCursor(o,i,t,r),o},_getAllNative:function(e,t,r,n){var o=!1,i=null;e.oncomplete=function(){var e=o?r:n;e(i)},e.onabort=n,e.onerror=n;var s=t.getAll();s.onsuccess=function(e){o=!0,i=e.target.result},s.onerror=n},_getAllCursor:function(e,t,r,n){var o=[],i=!1,s=null;e.oncomplete=function(){var e=i?r:n;e(s)},e.onabort=n,e.onerror=n;var a=t.openCursor();a.onsuccess=function(e){var t=e.target.result;t?(o.push(t.value),t["continue"]()):(i=!0,s=o)},a.onError=n},clear:function(t,r){r||(r=e),t||(t=n);var o=!1,i=null,s=this.db.transaction([this.storeName],this.consts.READ_WRITE);s.oncomplete=function(){var e=o?t:r;e(i)},s.onabort=r,s.onerror=r;var a=s.objectStore(this.storeName).clear();return a.onsuccess=function(e){o=!0,i=e.target.result},a.onerror=r,s},_addIdPropertyIfNeeded:function(e){this.features.hasAutoIncrement||"undefined"!=typeof e[this.keyPath]||(e[this.keyPath]=this._insertIdCount++ +Date.now())},getIndexList:function(){return this.store.indexNames},hasIndex:function(e){return this.store.indexNames.contains(e)},normalizeIndexData:function(e){e.keyPath=e.keyPath||e.name,e.unique=!!e.unique,e.multiEntry=!!e.multiEntry},indexComplies:function(e,t){var r=["keyPath","unique","multiEntry"].every(function(r){if("multiEntry"==r&&void 0===e[r]&&t[r]===!1)return!0;if("keyPath"==r&&"[object Array]"==Object.prototype.toString.call(t[r])){var n=t.keyPath,o=e.keyPath;if("string"==typeof o)return n.toString()==o;if("function"!=typeof o.contains&&"function"!=typeof o.indexOf)return!1;if(o.length!==n.length)return!1;for(var i=0,s=n.length;s>i;i++)if(!(o.contains&&o.contains(n[i])||o.indexOf(-1!==n[i])))return!1;return!0}return t[r]==e[r]});return r},iterate:function(t,r){r=i({index:null,order:"ASC",autoContinue:!0,filterDuplicates:!1,keyRange:null,writeAccess:!1,onEnd:null,onError:e},r||{});var n="desc"==r.order.toLowerCase()?"PREV":"NEXT";r.filterDuplicates&&(n+="_NO_DUPLICATE");var o=!1,s=this.db.transaction([this.storeName],this.consts[r.writeAccess?"READ_WRITE":"READ_ONLY"]),a=s.objectStore(this.storeName);r.index&&(a=a.index(r.index)),s.oncomplete=function(){return o?void(r.onEnd?r.onEnd():t(null)):void r.onError(null)},s.onabort=r.onError,s.onerror=r.onError;var u=a.openCursor(r.keyRange,this.consts[n]);return u.onerror=r.onError,u.onsuccess=function(e){var n=e.target.result;n?(t(n.value,n,s),r.autoContinue&&n["continue"]()):o=!0},s},query:function(e,t){var r=[];return t=t||{},t.onEnd=function(){e(r)},this.iterate(function(e){r.push(e)},t)},count:function(t,r){r=i({index:null,keyRange:null},r||{});var n=r.onError||e,o=!1,s=null,a=this.db.transaction([this.storeName],this.consts.READ_ONLY);a.oncomplete=function(){var e=o?t:n;e(s)},a.onabort=n,a.onerror=n;var u=a.objectStore(this.storeName);r.index&&(u=u.index(r.index));var c=u.count(r.keyRange);return c.onsuccess=function(e){o=!0,s=e.target.result},c.onError=n,a},makeKeyRange:function(e){var t,r="undefined"!=typeof e.lower,n="undefined"!=typeof e.upper,o="undefined"!=typeof e.only;switch(!0){case o:t=this.keyRange.only(e.only);break;case r&&n:t=this.keyRange.bound(e.lower,e.upper,e.excludeLower,e.excludeUpper);break;case r:t=this.keyRange.lowerBound(e.lower,e.excludeLower);break;case n:t=this.keyRange.upperBound(e.upper,e.excludeUpper);break;default:throw new Error('Cannot create KeyRange. Provide one or both of "lower" or "upper" value, or an "only" value.')}return t}};var n=function(){},o={},i=function(e,t){var r,n;for(r in t)n=t[r],n!==o[r]&&n!==e[r]&&(e[r]=n);return e};return r.version=r.prototype.version,r},this)},{}],51:[function(e,t){function r(e){return n.isBuffer(e)||/\[object (.+Array|Array.+)\]/.test(Object.prototype.toString.call(e))}var n=e("buffer").Buffer;t.exports=r},{buffer:17}],52:[function(e,t,r){(function(e){function t(e,t){return Object.hasOwnProperty.call(e,t)}function n(e){return void 0!==e&&""!==e}function t(e,t){return Object.hasOwnProperty.call(e,t)}function o(e,t){return Object.hasOwnProperty.call(e,t)&&t}function i(e){return e}r.compare=function(t,r){if(e.isBuffer(t)){for(var n=Math.min(t.length,r.length),o=0;n>o;o++){var i=t[o]-r[o];if(i)return i}return t.length-r.length}return r>t?-1:t>r?1:0};var s=r.lowerBoundKey=function(e){return o(e,"gt")||o(e,"gte")||o(e,"min")||(e.reverse?o(e,"end"):o(e,"start"))||void 0},a=r.lowerBound=function(e){var t=s(e);return t&&e[t]};r.lowerBoundInclusive=function(e){return t(e,"gt")?!1:!0},r.upperBoundInclusive=function(e){return t(e,"lt")||!e.minEx?!1:!0};var u=r.lowerBoundExclusive=function(e){return t(e,"gt")||e.minEx?!0:!1},c=r.upperBoundExclusive=function(e){return t(e,"lt")?!0:!1},f=r.upperBoundKey=function(e){return o(e,"lt")||o(e,"lte")||o(e,"max")||(e.reverse?o(e,"start"):o(e,"end"))||void 0},l=r.upperBound=function(e){var t=f(e);return t&&e[t]};r.toLtgt=function(e,t,n,o,s){t=t||{},n=n||i;var a=arguments.length>3,u=r.lowerBoundKey(e),c=r.upperBoundKey(e);return u?"gt"===u?t.gt=n(e.gt):t.gte=n(e[u]):a&&(t.gte=o),c?"lt"===c?t.lt=n(e.lt):t.lte=n(e[c]):a&&(t.lte=s),t.reverse=!!e.reverse,t},r.contains=function(e,t,o){o=o||r.compare;var i=a(e);if(n(i)){var s=o(t,i);if(0>s||0===s&&u(e))return!1}var f=l(e);if(n(f)){var s=o(t,f);if(s>0||0===s&&c(e))return!1}return!0},r.filter=function(e,t){return function(n){return r.contains(e,n,t)}}}).call(this,e("buffer").Buffer)},{buffer:17}],53:[function(e,t){(function(e){t.exports=function(t){return"function"==typeof e._augment&&e.TYPED_ARRAY_SUPPORT?e._augment(t):new e(t)}}).call(this,e("buffer").Buffer)},{buffer:17}],54:[function(e,t){function r(e){return null!==e&&("object"==typeof e||"function"==typeof e)}t.exports=r},{}],55:[function(e,t){function r(){for(var e={},t=0;t<arguments.length;t++){var r=arguments[t];if(o(r))for(var i=n(r),s=0;s<i.length;s++){var a=i[s];e[a]=r[a]}}return e}var n=e("object-keys"),o=e("./has-keys");t.exports=r},{"./has-keys":54,"object-keys":57}],56:[function(e,t){var r=Object.prototype.hasOwnProperty,n=Object.prototype.toString,o=function(e){var t="function"==typeof e&&!(e instanceof RegExp)||"[object Function]"===n.call(e);return t||"undefined"==typeof window||(t=e===window.setTimeout||e===window.alert||e===window.confirm||e===window.prompt),t};t.exports=function(e,t){if(!o(t))throw new TypeError("iterator must be a function");var n,i,s="string"==typeof e,a=e.length,u=arguments.length>2?arguments[2]:null;if(a===+a)for(n=0;a>n;n++)null===u?t(s?e.charAt(n):e[n],n,e):t.call(u,s?e.charAt(n):e[n],n,e);else for(i in e)r.call(e,i)&&(null===u?t(e[i],i,e):t.call(u,e[i],i,e))}},{}],57:[function(e,t){t.exports=Object.keys||e("./shim")},{"./shim":59}],58:[function(e,t){var r=Object.prototype.toString;t.exports=function n(e){var t=r.call(e),n="[object Arguments]"===t;return n||(n="[object Array]"!==t&&null!==e&&"object"==typeof e&&"number"==typeof e.length&&e.length>=0&&"[object Function]"===r.call(e.callee)),n}},{}],59:[function(e,t){!function(){"use strict";var r,n=Object.prototype.hasOwnProperty,o=Object.prototype.toString,i=e("./foreach"),s=e("./isArguments"),a=!{toString:null}.propertyIsEnumerable("toString"),u=function(){}.propertyIsEnumerable("prototype"),c=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"];r=function(e){var t=null!==e&&"object"==typeof e,r="[object Function]"===o.call(e),f=s(e),l=[];if(!t&&!r&&!f)throw new TypeError("Object.keys called on a non-object");if(f)i(e,function(e){l.push(e)});else{var d,h=u&&r;for(d in e)h&&"prototype"===d||!n.call(e,d)||l.push(d)}if(a){var p=e.constructor,v=p&&p.prototype===e;i(c,function(t){v&&"constructor"===t||!n.call(e,t)||l.push(t)})}return l},t.exports=r}()},{"./foreach":56,"./isArguments":58}],60:[function(e,t){function r(e,t,r,n){var o={type:e,key:t,value:r,options:n};return n&&n.prefix&&(o.prefix=n.prefix,delete n.prefix),this._operations.push(o),this}function n(e){this._operations=[],this._sdb=e,this.put=r.bind(this,"put"),this.del=r.bind(this,"del")}var o=n.prototype;o.clear=function(){this._operations=[]},o.write=function(e){this._sdb.batch(this._operations,e)},t.exports=n},{}],61:[function(e,t){(function(r){var n=(e("events").EventEmitter,r.nextTick,e("./sub")),o=e("./batch"),i=e("level-fix-range"),s=e("level-hooks");t.exports=function(e,t){function r(){}function a(e){return function(t){return t=t||{},t=i(t),t.reverse?t.start=t.start||c:t.end=t.end||c,e.call(u,t)}}r.prototype=e;var u=new r;if(u.sublevel)return u;t=t||{};var c=t.sep=t.sep||"ÿ";u._options=t,s(u),u.sublevels={},u.sublevel=function(e,t){return u.sublevels[e]?u.sublevels[e]:new n(u,e,t||this._options)},u.methods={},u.prefix=function(e){return""+(e||"")},u.pre=function(e,t){return t||(t=e,e={max:c}),u.hooks.pre(e,t)},u.post=function(e,t){return t||(t=e,e={max:c}),u.hooks.post(e,t)},u.readStream=u.createReadStream=a(u.createReadStream),u.keyStream=u.createKeyStream=a(u.createKeyStream),u.valuesStream=u.createValueStream=a(u.createValueStream);var f=u.batch;return u.batch=function(e,t,r){return Array.isArray(e)?(e.forEach(function(e){e.prefix&&("function"==typeof e.prefix.prefix?e.key=e.prefix.prefix(e.key):"string"==typeof e.prefix&&(e.key=e.prefix+e.key))}),void f.call(u,e,t,r)):new o(u)},u}}).call(this,e("_process"))},{"./batch":60,"./sub":72,_process:24,events:21,"level-fix-range":62,"level-hooks":64}],62:[function(e,t){var r=e("clone");t.exports=function(e){e=r(e);var t=e.reverse,n=e.max||e.end,o=e.min||e.start,i=[o,n];return null!=o&&null!=n&&i.sort(),t&&(i=i.reverse()),e.start=i[0],e.end=i[1],delete e.min,delete e.max,e}},{clone:63}],63:[function(e,t){(function(e){"use strict";function r(e){return Object.prototype.toString.call(e)}function n(t,r,n,i){function s(t,n){if(null===t)return null;if(0==n)return t;var f,l;if("object"!=typeof t)return t;if(o.isArray(t))f=[];else if(o.isRegExp(t))f=new RegExp(t.source,o.getRegExpFlags(t)),t.lastIndex&&(f.lastIndex=t.lastIndex);else if(o.isDate(t))f=new Date(t.getTime());else{if(c&&e.isBuffer(t))return f=new e(t.length),t.copy(f),f;"undefined"==typeof i?(l=Object.getPrototypeOf(t),f=Object.create(l)):(f=Object.create(i),l=i)}if(r){var d=a.indexOf(t);if(-1!=d)return u[d];a.push(t),u.push(f)}for(var h in t){var p;l&&(p=Object.getOwnPropertyDescriptor(l,h)),p&&null==p.set||(f[h]=s(t[h],n-1))}return f}var a=[],u=[],c="undefined"!=typeof e;return"undefined"==typeof r&&(r=!0),"undefined"==typeof n&&(n=1/0),s(t,n)}var o={isArray:function(e){return Array.isArray(e)||"object"==typeof e&&"[object Array]"===r(e)},isDate:function(e){return"object"==typeof e&&"[object Date]"===r(e)},isRegExp:function(e){return"object"==typeof e&&"[object RegExp]"===r(e)},getRegExpFlags:function(e){var t="";return e.global&&(t+="g"),e.ignoreCase&&(t+="i"),e.multiline&&(t+="m"),t}};"object"==typeof t&&(t.exports=n),n.clonePrototype=function(e){if(null===e)return null;var t=function(){};return t.prototype=e,new t}}).call(this,e("buffer").Buffer)},{buffer:17}],64:[function(e,t){var r=e("string-range");t.exports=function(e){function t(e){return e&&("string"==typeof e?e:"string"==typeof e.prefix?e.prefix:"function"==typeof e.prefix?e.prefix():"")}function n(e){return e&&e._getKeyEncoding?e._getKeyEncoding(e):void 0}function o(e){return e&&e._getValueEncoding?e._getValueEncoding(e):void 0}function i(e,t){return function(){var r=e.indexOf(t);return~r?(e.splice(r,1),!0):!1}}function s(e){e&&e.type&&u.forEach(function(t){t.test(e.key)&&t.hook(e)})}function a(r,i,s,a){try{i.forEach(function p(e,r){c.forEach(function(s){if(s.test(String(e.key))){var a={add:function(e,a){if("undefined"==typeof e)return this;if(e===!1)return delete i[r];var u=t(e.prefix)||t(a)||s.prefix||"";if(u&&(e.prefix=u),e.key=u+e.key,s.safe&&s.test(String(e.key)))throw new Error("prehook cannot insert into own range");var c=e.keyEncoding||n(e.prefix),f=e.valueEncoding||o(e.prefix);return c&&(e.keyEncoding=c),f&&(e.valueEncoding=f),i.push(e),p(e,i.length-1),this},put:function(e,t){return"object"==typeof e&&(e.type="put"),this.add(e,t)},del:function(e,t){return"object"==typeof e&&(e.type="del"),this.add(e,t)},veto:function(){return this.add(!1)}};s.hook.call(a,e,a.add,i)}})})}catch(u){return(a||s)(u)}if(i=i.filter(function(e){return e&&e.type}),1==i.length&&!r){var h=i[0];return"put"==h.type?f.call(e,h.key,h.value,s,a):l.call(e,h.key,s,a)}return d.call(e,i,s,a)}if(!e.hooks){var u=[],c=[];e.hooks={post:function(e,t){t||(t=e,e="");var n={test:r.checker(e),hook:t};return u.push(n),i(u,n)},pre:function(e,t){t||(t=e,e="");var n={test:r.checker(e),hook:t,safe:!1!==e.safe};return c.push(n),i(c,n)},posthooks:u,prehooks:c},e.on("put",function(e,t){s({type:"put",key:e,value:t})}),e.on("del",function(e,t){s({type:"del",key:e,value:t})}),e.on("batch",function(e){e.forEach(s)});var f=e.put,l=e.del,d=e.batch;e.put=function(e,t,r,n){var o=[{key:e,value:t,type:"put"}];return a(!1,o,r,n)},e.del=function(e,t,r){var n=[{key:e,type:"del"}];return a(!1,n,t,r)},e.batch=function(e,t,r){return a(!0,e,t,r)}}}},{"string-range":65}],65:[function(e,t,r){{var n=r.range=function(e){return null==e?{}:"string"==typeof n?{min:n,max:n+"ÿ"}:e},o=(r.prefix=function(e,t,n){e=r.range(e);var o={};return n=n||"ÿ",e instanceof RegExp||"function"==typeof e?(o.min=t,o.max=t+n,o.inner=function(r){var n=r.substring(t.length);return e.test?e.test(n):e(n)}):"object"==typeof e&&(o.min=t+(e.min||e.start||""),o.max=t+(e.max||e.end||n||"~"),o.reverse=!!e.reverse),o},r.checker=function(e){return e||(e={}),"string"==typeof e?function(t){return 0==t.indexOf(e)}:e instanceof RegExp?function(t){return e.test(t)}:"object"==typeof e?function(t){var r=e.min||e.start,n=e.max||e.end;return t=String(t),(!r||t>=r)&&(!n||n>=t)&&(!e.inner||(e.inner.test?e.inner.test(t):e.inner(t)))}:"function"==typeof e?e:void 0});r.satisfies=function(e,t){return o(t)(e)}}},{}],66:[function(e,t){t.exports=e(54)},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/has-keys.js":54}],67:[function(e,t,r){arguments[4][55][0].apply(r,arguments)},{"./has-keys":66,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/index.js":55,"object-keys":68}],68:[function(e,t,r){arguments[4][57][0].apply(r,arguments)},{"./shim":71,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/index.js":57}],69:[function(e,t){var r=Object.prototype.hasOwnProperty,n=Object.prototype.toString;t.exports=function(e,t,o){if("[object Function]"!==n.call(t))throw new TypeError("iterator must be a function");var i=e.length;if(i===+i)for(var s=0;i>s;s++)t.call(o,e[s],s,e);else for(var a in e)r.call(e,a)&&t.call(o,e[a],a,e)}},{}],70:[function(e,t){var r=Object.prototype,n=r.hasOwnProperty,o=r.toString,i=function(e){return e!==e},s={"boolean":1,number:1,string:1,undefined:1},a=t.exports={};a.a=a.type=function(e,t){return typeof e===t},a.defined=function(e){return void 0!==e},a.empty=function(e){var t,r=o.call(e);if("[object Array]"===r||"[object Arguments]"===r)return 0===e.length;if("[object Object]"===r){for(t in e)if(n.call(e,t))return!1;return!0}return"[object String]"===r?""===e:!1},a.equal=function(e,t){var r,n=o.call(e);if(n!==o.call(t))return!1;if("[object Object]"===n){for(r in e)if(!a.equal(e[r],t[r]))return!1;return!0}if("[object Array]"===n){if(r=e.length,r!==t.length)return!1;for(;--r;)if(!a.equal(e[r],t[r]))return!1;return!0}return"[object Function]"===n?e.prototype===t.prototype:"[object Date]"===n?e.getTime()===t.getTime():e===t},a.hosted=function(e,t){var r=typeof t[e];return"object"===r?!!t[e]:!s[r]},a.instance=a["instanceof"]=function(e,t){return e instanceof t},a["null"]=function(e){return null===e},a.undefined=function(e){return void 0===e},a.arguments=function(e){var t="[object Arguments]"===o.call(e),r=!a.array(e)&&a.arraylike(e)&&a.object(e)&&a.fn(e.callee);return t||r},a.array=function(e){return"[object Array]"===o.call(e)},a.arguments.empty=function(e){return a.arguments(e)&&0===e.length},a.array.empty=function(e){return a.array(e)&&0===e.length},a.arraylike=function(e){return!!e&&!a.boolean(e)&&n.call(e,"length")&&isFinite(e.length)&&a.number(e.length)&&e.length>=0},a.boolean=function(e){return"[object Boolean]"===o.call(e)},a["false"]=function(e){return a.boolean(e)&&(e===!1||e.valueOf()===!1) +},a["true"]=function(e){return a.boolean(e)&&(e===!0||e.valueOf()===!0)},a.date=function(e){return"[object Date]"===o.call(e)},a.element=function(e){return void 0!==e&&"undefined"!=typeof HTMLElement&&e instanceof HTMLElement&&1===e.nodeType},a.error=function(e){return"[object Error]"===o.call(e)},a.fn=a["function"]=function(e){var t="undefined"!=typeof window&&e===window.alert;return t||"[object Function]"===o.call(e)},a.number=function(e){return"[object Number]"===o.call(e)},a.infinite=function(e){return 1/0===e||e===-1/0},a.decimal=function(e){return a.number(e)&&!i(e)&&!a.infinite(e)&&e%1!==0},a.divisibleBy=function(e,t){var r=a.infinite(e),n=a.infinite(t),o=a.number(e)&&!i(e)&&a.number(t)&&!i(t)&&0!==t;return r||n||o&&e%t===0},a.int=function(e){return a.number(e)&&!i(e)&&e%1===0},a.maximum=function(e,t){if(i(e))throw new TypeError("NaN is not a valid value");if(!a.arraylike(t))throw new TypeError("second argument must be array-like");for(var r=t.length;--r>=0;)if(e<t[r])return!1;return!0},a.minimum=function(e,t){if(i(e))throw new TypeError("NaN is not a valid value");if(!a.arraylike(t))throw new TypeError("second argument must be array-like");for(var r=t.length;--r>=0;)if(e>t[r])return!1;return!0},a.nan=function(e){return!a.number(e)||e!==e},a.even=function(e){return a.infinite(e)||a.number(e)&&e===e&&e%2===0},a.odd=function(e){return a.infinite(e)||a.number(e)&&e===e&&e%2!==0},a.ge=function(e,t){if(i(e)||i(t))throw new TypeError("NaN is not a valid value");return!a.infinite(e)&&!a.infinite(t)&&e>=t},a.gt=function(e,t){if(i(e)||i(t))throw new TypeError("NaN is not a valid value");return!a.infinite(e)&&!a.infinite(t)&&e>t},a.le=function(e,t){if(i(e)||i(t))throw new TypeError("NaN is not a valid value");return!a.infinite(e)&&!a.infinite(t)&&t>=e},a.lt=function(e,t){if(i(e)||i(t))throw new TypeError("NaN is not a valid value");return!a.infinite(e)&&!a.infinite(t)&&t>e},a.within=function(e,t,r){if(i(e)||i(t)||i(r))throw new TypeError("NaN is not a valid value");if(!a.number(e)||!a.number(t)||!a.number(r))throw new TypeError("all arguments must be numbers");var n=a.infinite(e)||a.infinite(t)||a.infinite(r);return n||e>=t&&r>=e},a.object=function(e){return e&&"[object Object]"===o.call(e)},a.hash=function(e){return a.object(e)&&e.constructor===Object&&!e.nodeType&&!e.setInterval},a.regexp=function(e){return"[object RegExp]"===o.call(e)},a.string=function(e){return"[object String]"===o.call(e)}},{}],71:[function(e,t){!function(){"use strict";var r,n=Object.prototype.hasOwnProperty,o=e("is"),i=e("foreach"),s=!{toString:null}.propertyIsEnumerable("toString"),a=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"];r=function(e){if(!o.object(e)&&!o.array(e))throw new TypeError("Object.keys called on a non-object");var t,r=[];for(t in e)n.call(e,t)&&r.push(t);return s&&i(a,function(t){n.call(e,t)&&r.push(t)}),r},t.exports=r}()},{foreach:69,is:70}],72:[function(e,t){function r(e,t,n){if("string"==typeof n&&(console.error("db.sublevel(name, seperator<string>) is depreciated"),console.error("use db.sublevel(name, {sep: separator})) if you must"),n={sep:n}),!(this instanceof r))return new r(e,t,n);if(!e)throw new Error("must provide db");if(!t)throw new Error("must provide prefix");n=n||{},n.sep=n.sep||"ÿ",this._parent=e,this._options=n,this.options=n,this._prefix=t,this._root=o(this),e.sublevels[t]=this,this.sublevels={},this.methods={};var i=this;this.hooks={pre:function(){return i.pre.apply(i,arguments)},post:function(){return i.post.apply(i,arguments)}}}function n(e,t){["valueEncoding","encoding","keyEncoding","reverse","values","keys","limit","fillCache"].forEach(function(r){t.hasOwnProperty(r)&&(e[r]=t[r])})}function o(e){return e._parent?o(e._parent):e}var i=e("events").EventEmitter,s=e("util").inherits,a=e("string-range"),u=e("level-fix-range"),c=e("xtend"),f=e("./batch");s(r,i);var l=r.prototype;l._key=function(e){var t=this._options.sep;return t+this._prefix+t+e},l._getOptsAndCb=function(e,t){return"function"==typeof e&&(t=e,e={}),{opts:c(e,this._options),cb:t}},l.sublevel=function(e,t){return this.sublevels[e]?this.sublevels[e]:new r(this,e,t||this._options)},l.put=function(e,t,r,n){var o=this._getOptsAndCb(r,n);this._root.put(this.prefix(e),t,o.opts,o.cb)},l.get=function(e,t,r){var n=this._getOptsAndCb(t,r);this._root.get(this.prefix(e),n.opts,n.cb)},l.del=function(e,t,r){var n=this._getOptsAndCb(t,r);this._root.del(this.prefix(e),n.opts,n.cb)},l.batch=function(e,t,r){if(!Array.isArray(e))return new f(this);var n=this,o=this._getOptsAndCb(t,r);e.forEach(function(e){e.key="string"==typeof e.prefix?e.prefix+e.key:(e.prefix||n).prefix(e.key),e.prefix&&(e.prefix=null)}),this._root.batch(e,o.opts,o.cb)},l._getKeyEncoding=function(){return this.options.keyEncoding?this.options.keyEncoding:this._parent&&this._parent._getKeyEncoding?this._parent._getKeyEncoding():void 0},l._getValueEncoding=function(){return this.options.valueEncoding?this.options.valueEncoding:this._parent&&this._parent._getValueEncoding?this._parent._getValueEncoding():void 0},l.prefix=function(e){var t=this._options.sep;return this._parent.prefix()+t+this._prefix+t+(e||"")},l.keyStream=l.createKeyStream=function(e){return e=e||{},e.keys=!0,e.values=!1,this.createReadStream(e)},l.valueStream=l.createValueStream=function(e){return e=e||{},e.keys=!1,e.values=!0,e.keys=!1,this.createReadStream(e)},l.readStream=l.createReadStream=function(e){e=e||{};var t=o(this),r=this.prefix(),i=a.prefix(e,r);n(i,c(e,this._options));var s=t.createReadStream(i);if(i.values===!1){var u=s.read;if(u)s.read=function(e){var t=u.call(this,e);return t&&(t=t.substring(r.length)),t};else{var f=s.emit;s.emit=function(e,t){"data"===e?f.call(this,"data",t.substring(r.length)):f.call(this,e,t)}}return s}if(i.keys===!1)return s;var u=s.read;return u?s.read=function(e){var t=u.call(this,e);return t&&(t.key=t.key.substring(r.length)),t}:s.on("data",function(e){e.key=e.key.substring(r.length)}),s},l.writeStream=l.createWriteStream=function(){var e=o(this),t=this.prefix(),r=e.createWriteStream.apply(e,arguments),n=r.write,i=this._options.encoding,s=this._options.valueEncoding,a=this._options.keyEncoding,u=!i&&!s&&!a;return r.write=u?function(e){return e.key=t+e.key,n.call(r,e)}:function(e){return e.key=t+e.key,i&&"undefined"==typeof e.encoding&&(e.encoding=i),s&&"undefined"==typeof e.valueEncoding&&(e.valueEncoding=s),a&&"undefined"==typeof e.keyEncoding&&(e.keyEncoding=a),n.call(r,e)},r},l.approximateSize=function(){var e=o(db);return e.approximateSize.apply(e,arguments)},l.pre=function(e,t){t||(t=e,e=null),e=a.prefix(e,this.prefix(),this._options.sep);var r=o(this._parent),n=this.prefix();return r.hooks.pre(u(e),function(e,r,o){t({key:e.key.substring(n.length),value:e.value,type:e.type},function(e,t){r(e,e.prefix?t:t||n)},o)})},l.post=function(e,t){t||(t=e,e=null);var r=o(this._parent),n=this.prefix();return e=a.prefix(e,n,this._options.sep),r.hooks.post(u(e),function(e){t({key:e.key.substring(n.length),value:e.value,type:e.type})})};t.exports=r},{"./batch":60,events:21,"level-fix-range":62,"string-range":65,util:39,xtend:67}],73:[function(e,t){function r(e){this._levelup=e,this.batch=e.db.batch(),this.ops=[]}var n=e("./util"),o=e("./errors").WriteError,i=n.getOptions,s=n.dispatchError;r.prototype.put=function(e,t,r){r=i(this._levelup,r);var s=n.encodeKey(e,r),a=n.encodeValue(t,r);try{this.batch.put(s,a)}catch(u){throw new o(u)}return this.ops.push({type:"put",key:s,value:a}),this},r.prototype.del=function(e,t){t=i(this._levelup,t);var r=n.encodeKey(e,t);try{this.batch.del(r)}catch(s){throw new o(s)}return this.ops.push({type:"del",key:r}),this},r.prototype.clear=function(){try{this.batch.clear()}catch(e){throw new o(e)}return this.ops=[],this},r.prototype.write=function(e){var t=this._levelup,r=this.ops;try{this.batch.write(function(n){return n?s(t,new o(n),e):(t.emit("batch",r),void(e&&e()))})}catch(n){throw new o(n)}},t.exports=r},{"./errors":74,"./util":77}],74:[function(e,t){var r=e("errno").create,n=r("LevelUPError"),o=r("NotFoundError",n);o.prototype.notFound=!0,o.prototype.status=404,t.exports={LevelUPError:n,InitializationError:r("InitializationError",n),OpenError:r("OpenError",n),ReadError:r("ReadError",n),WriteError:r("WriteError",n),NotFoundError:o,EncodingError:r("EncodingError",n)}},{errno:85}],75:[function(e,t){(function(r){function n(e,t){return"function"==typeof e?e:t}function o(e,t,n){if(!(this instanceof o))return new o(e,t,n);var i;if(s.call(this),this.setMaxListeners(1/0),"function"==typeof e?(t="object"==typeof t?t:{},t.db=e,e=null):"object"==typeof e&&"function"==typeof e.db&&(t=e,e=null),"function"==typeof t&&(n=t,t={}),(!t||"function"!=typeof t.db)&&"string"!=typeof e){if(i=new y("Must provide a location for the database"),n)return r.nextTick(function(){n(i)});throw i}t=w(this,t),this.options=u(E,t),this._status="new",c(this,"location",e,"e"),this.open(n)}function i(e){return function(t,r){x()[e](t,r||function(){})}}var s=e("events").EventEmitter,a=e("util").inherits,u=e("xtend"),c=e("prr"),f=e("deferred-leveldown"),l=e("./errors").WriteError,d=e("./errors").ReadError,h=e("./errors").NotFoundError,p=e("./errors").OpenError,v=e("./errors").EncodingError,y=e("./errors").InitializationError,g=e("./read-stream"),m=e("./write-stream"),b=e("./util"),_=e("./batch"),w=b.getOptions,E=b.defaultOptions,x=b.getLevelDOWN,k=b.dispatchError;a(o,s),o.prototype.open=function(e){var t,n,o=this;return this.isOpen()?(e&&r.nextTick(function(){e(null,o)}),this):this._isOpening()?e&&this.once("open",function(){e(null,o)}):(this.emit("opening"),this._status="opening",this.db=new f(this.location),t=this.options.db||x(),n=t(this.location),void n.open(this.options,function(t){return t?k(o,new p(t),e):(o.db.setDb(n),o.db=n,o._status="open",e&&e(null,o),o.emit("open"),o.emit("ready"),void 0)}))},o.prototype.close=function(e){var t=this;if(this.isOpen())this._status="closing",this.db.close(function(){t._status="closed",t.emit("closed"),e&&e.apply(null,arguments)}),this.emit("closing"),this.db=null;else{if("closed"==this._status&&e)return r.nextTick(e);"closing"==this._status&&e?this.once("closed",e):this._isOpening()&&this.once("open",function(){t.close(e)})}},o.prototype.isOpen=function(){return"open"==this._status},o.prototype._isOpening=function(){return"opening"==this._status},o.prototype.isClosed=function(){return/^clos/.test(this._status)},o.prototype.get=function(e,t,r){var o,i=this;return r=n(t,r),"function"!=typeof r?k(this,new d("get() requires key and callback arguments")):this._isOpening()||this.isOpen()?(t=b.getOptions(this,t),o=b.encodeKey(e,t),t.asBuffer=b.isValueAsBuffer(t),void this.db.get(o,t,function(n,o){if(n)return n=/notfound/i.test(n)?new h("Key not found in database ["+e+"]",n):new d(n),k(i,n,r);if(r){try{o=b.decodeValue(o,t)}catch(s){return r(new v(s))}r(null,o)}})):k(this,new d("Database is not open"),r)},o.prototype.put=function(e,t,r,o){var i,s,a=this;return o=n(r,o),null===e||void 0===e||null===t||void 0===t?k(this,new l("put() requires key and value arguments"),o):this._isOpening()||this.isOpen()?(r=w(this,r),i=b.encodeKey(e,r),s=b.encodeValue(t,r),void this.db.put(i,s,r,function(r){return r?k(a,new l(r),o):(a.emit("put",e,t),void(o&&o()))})):k(this,new l("Database is not open"),o)},o.prototype.del=function(e,t,r){var o,i=this;return r=n(t,r),null===e||void 0===e?k(this,new l("del() requires a key argument"),r):this._isOpening()||this.isOpen()?(t=w(this,t),o=b.encodeKey(e,t),void this.db.del(o,t,function(t){return t?k(i,new l(t),r):(i.emit("del",e),void(r&&r()))})):k(this,new l("Database is not open"),r)},o.prototype.batch=function(e,t,r){var o,i,s,a=this;return arguments.length?(r=n(t,r),Array.isArray(e)?this._isOpening()||this.isOpen()?(t=w(this,t),o=t.keyEncoding,i=t.valueEncoding,s=e.map(function(e){if(void 0===e.type||void 0===e.key)return{};var r,n=e.keyEncoding||o,s=e.valueEncoding||e.encoding||i;return"utf8"!=n&&"binary"!=n||"utf8"!=s&&"binary"!=s?(r={type:e.type,key:b.encodeKey(e.key,t,e)},void 0!==e.value&&(r.value=b.encodeValue(e.value,t,e)),r):e}),void this.db.batch(s,t,function(t){return t?k(a,new l(t),r):(a.emit("batch",e),void(r&&r()))})):k(this,new l("Database is not open"),r):k(this,new l("batch() requires an array argument"),r)):new _(this)},o.prototype.approximateSize=function(e,t,r){var n,o,i=this;return null===e||void 0===e||null===t||void 0===t||"function"!=typeof r?k(this,new d("approximateSize() requires start, end and callback arguments"),r):(n=b.encodeKey(e,this.options),o=b.encodeKey(t,this.options),this._isOpening()||this.isOpen()?void this.db.approximateSize(n,o,function(e,t){return e?k(i,new p(e),r):void(r&&r(null,t))}):k(this,new l("Database is not open"),r))},o.prototype.readStream=o.prototype.createReadStream=function(e){var t=this;return e=u(this.options,e),new g(e,this,function(e){return t.db.iterator(e)})},o.prototype.keyStream=o.prototype.createKeyStream=function(e){return this.createReadStream(u(e,{keys:!0,values:!1}))},o.prototype.valueStream=o.prototype.createValueStream=function(e){return this.createReadStream(u(e,{keys:!1,values:!0}))},o.prototype.writeStream=o.prototype.createWriteStream=function(e){return new m(u(e),this)},o.prototype.toString=function(){return"LevelUP"},t.exports=o,t.exports.copy=b.copy,t.exports.destroy=i("destroy"),t.exports.repair=i("repair")}).call(this,e("_process"))},{"./batch":73,"./errors":74,"./read-stream":76,"./util":77,"./write-stream":78,_process:24,"deferred-leveldown":80,events:21,prr:86,util:39,xtend:96}],76:[function(e,t){function r(e,t,o){if(!(this instanceof r))return new r(e,t,o);n.call(this,{objectMode:!0,highWaterMark:e.highWaterMark}),this._db=t,e=this._options=i(u,e),this._keyEncoding=e.keyEncoding||e.encoding,this._valueEncoding=e.valueEncoding||e.encoding,"undefined"!=typeof this._options.start&&(this._options.start=a.encodeKey(this._options.start,this._options)),"undefined"!=typeof this._options.end&&(this._options.end=a.encodeKey(this._options.end,this._options)),"number"!=typeof this._options.limit&&(this._options.limit=-1),this._options.keyAsBuffer=a.isKeyAsBuffer(this._options),this._options.valueAsBuffer=a.isValueAsBuffer(this._options),this._makeData=this._options.keys&&this._options.values?c:this._options.keys?f:this._options.values?l:d;var s=this;this._db.isOpen()?this._iterator=o(this._options):this._db.once("ready",function(){s._destroyed||(s._iterator=o(s._options))})}var n=e("readable-stream").Readable,o=e("util").inherits,i=e("xtend"),s=e("./errors").EncodingError,a=e("./util"),u={keys:!0,values:!0},c=function(e,t){return{key:a.decodeKey(e,this._options),value:a.decodeValue(t,this._options)}},f=function(e){return a.decodeKey(e,this._options)},l=function(e,t){return a.decodeValue(t,this._options)},d=function(){return null};o(r,n),r.prototype._read=function h(){var e=this;return e._db.isOpen()?void(e._destroyed||e._iterator.next(function(t,r,n){if(t||void 0===r&&void 0===n)return t||e._destroyed||e.push(null),e._cleanup(t);try{n=e._makeData(r,n)}catch(o){return e._cleanup(new s(o))}e._destroyed||e.push(n)})):e._db.once("ready",function(){h.call(e)})},r.prototype._cleanup=function(e){if(!this._destroyed){this._destroyed=!0;var t=this;e&&t.emit("error",e),t._iterator?t._iterator.end(function(){t._iterator=null,t.emit("close")}):t.emit("close")}},r.prototype.destroy=function(){this._cleanup()},r.prototype.toString=function(){return"LevelUP.ReadStream"},t.exports=r},{"./errors":74,"./util":77,"readable-stream":95,util:39,xtend:96}],77:[function(e,t){(function(r,n){function o(e,t,r){e.readStream().pipe(t.writeStream()).on("close",r?r:function(){}).on("error",r?r:function(e){throw e})}function i(e,t){var r="string"==typeof t;return!r&&t&&t.encoding&&!t.valueEncoding&&(t.valueEncoding=t.encoding),g(e&&e.options||{},r?E[t]||E[_.valueEncoding]:t)}function s(){if(y)return y;var t,r=e("../package.json").devDependencies.leveldown,n="Could not locate LevelDOWN, try `npm install leveldown`";try{t=e("leveldown/package").version}catch(o){throw new m(n)}if(!e("semver").satisfies(t,r))throw new m("Installed version of LevelDOWN ("+t+") does not match required version ("+r+")");try{return y=e("leveldown")}catch(o){throw new m(n)}}function a(e,t,r){return"function"==typeof r?r(t):e.emit("error",t)}function u(e,t){var r=t&&t.keyEncoding||e.keyEncoding||"utf8";return w[r]||r}function c(e,t){var r=t&&(t.valueEncoding||t.encoding)||e.valueEncoding||e.encoding||"utf8";return w[r]||r}function f(e,t,r){return u(t,r).encode(e)}function l(e,t,r){return c(t,r).encode(e)}function d(e,t){return u(t).decode(e)}function h(e,t){return c(t).decode(e)}function p(e,t){return c(e,t).buffer}function v(e,t){return u(e,t).buffer}var y,g=e("xtend"),m=e("./errors").LevelUPError,b=["hex","utf8","utf-8","ascii","binary","base64","ucs2","ucs-2","utf16le","utf-16le"],_={createIfMissing:!0,errorIfExists:!1,keyEncoding:"utf8",valueEncoding:"utf8",compression:!0},w=function(){function e(e){return void 0===e||null===e||n.isBuffer(e)}var t={};return t.utf8=t["utf-8"]={encode:function(t){return e(t)?t:String(t)},decode:function(e){return e},buffer:!1,type:"utf8"},t.json={encode:JSON.stringify,decode:JSON.parse,buffer:!1,type:"json"},b.forEach(function(o){t[o]||(t[o]={encode:function(t){return e(t)?t:new n(t,o)},decode:function(e){return r.browser?e.toString(o):e},buffer:!0,type:o})}),t}(),E=function(){var e={};return b.forEach(function(t){e[t]={valueEncoding:t}}),e}();t.exports={defaultOptions:_,copy:o,getOptions:i,getLevelDOWN:s,dispatchError:a,encodeKey:f,encodeValue:l,isValueAsBuffer:p,isKeyAsBuffer:v,decodeValue:h,decodeKey:d}}).call(this,e("_process"),e("buffer").Buffer)},{"../package.json":97,"./errors":74,_process:24,buffer:17,leveldown:"leveldown","leveldown/package":16,semver:16,xtend:96}],78:[function(e,t){(function(r,n){function o(e,t){if(!(this instanceof o))return new o(e,t);i.call(this),this._options=a(l,f(t,e)),this._db=t,this._buffer=[],this._status="init",this._end=!1,this.writable=!0,this.readable=!1;var r=this,n=function(){r.writable&&(r._status="ready",r.emit("ready"),r._process())};t.isOpen()?c(n):t.once("ready",n)}var i=e("stream").Stream,s=e("util").inherits,a=e("xtend"),u=e("bl"),c=n.setImmediate||r.nextTick,f=e("./util").getOptions,l={type:"put"};s(o,i),o.prototype.write=function(e){return this.writable?(this._buffer.push(e),"init"!=this._status&&this._processDelayed(),this._options.maxBufferLength&&this._buffer.length>this._options.maxBufferLength?(this._writeBlock=!0,!1):!0):!1},o.prototype.end=function(e){var t=this;e&&this.write(e),c(function(){t._end=!0,t._process()})},o.prototype.destroy=function(){this.writable=!1,this.end()},o.prototype.destroySoon=function(){this.end()},o.prototype.add=function(e){return e.props?(e.props.Directory?e.pipe(this._db.writeStream(this._options)):(e.props.File||e.File||"File"==e.type)&&this._write(e),!0):void 0},o.prototype._processDelayed=function(){var e=this;c(function(){e._process()})},o.prototype._process=function(){var e,t=this,r=function(e){return t.writable?("closed"!=t._status&&(t._status="ready"),e?(t.writable=!1,t.emit("error",e)):void t._process()):void 0};return"ready"!=t._status&&t.writable?void(t._buffer.length&&"closed"!=t._status&&t._processDelayed()):t._buffer.length&&t.writable?(t._status="writing",e=t._buffer,t._buffer=[],t._db.batch(e.map(function(e){return{type:e.type||t._options.type,key:e.key,value:e.value,keyEncoding:e.keyEncoding||t._options.keyEncoding,valueEncoding:e.valueEncoding||e.encoding||t._options.valueEncoding}}),r),void(t._writeBlock&&(t._writeBlock=!1,t.emit("drain")))):void(t._end&&"closed"!=t._status&&(t._status="closed",t.writable=!1,t.emit("close")))},o.prototype._write=function(e){var t=e.path||e.props.path,r=this;t&&e.pipe(u(function(e,n){return e?(r.writable=!1,r.emit("error",e)):(r._options.fstreamRoot&&t.indexOf(r._options.fstreamRoot)>-1&&(t=t.substr(r._options.fstreamRoot.length+1)),void r.write({key:t,value:n.slice(0)}))}))},o.prototype.toString=function(){return"LevelUP.WriteStream"},t.exports=o}).call(this,e("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./util":77,_process:24,bl:79,stream:36,util:39,xtend:96}],79:[function(e,t){(function(r){function n(e){if(!(this instanceof n))return new n(e);if(this._bufs=[],this.length=0,"function"==typeof e){this._callback=e;var t=function(e){this._callback&&(this._callback(e),this._callback=null)}.bind(this);this.on("pipe",function(e){e.on("error",t)}),this.on("unpipe",function(e){e.removeListener("error",t)})}else r.isBuffer(e)?this.append(e):Array.isArray(e)&&e.forEach(function(e){r.isBuffer(e)&&this.append(e)}.bind(this));o.call(this)}var o=e("readable-stream").Duplex,i=e("util");i.inherits(n,o),n.prototype._offset=function(e){for(var t,r=0,n=0;n<this._bufs.length;n++){if(t=r+this._bufs[n].length,t>e)return[n,e-r];r=t}},n.prototype.append=function(e){return this._bufs.push(r.isBuffer(e)?e:new r(e)),this.length+=e.length,this},n.prototype._write=function(e,t,r){this.append(e),r&&r()},n.prototype._read=function(e){return this.length?(e=Math.min(e,this.length),this.push(this.slice(0,e)),void this.consume(e)):this.push(null)},n.prototype.end=function(e){o.prototype.end.call(this,e),this._callback&&(this._callback(null,this.slice()),this._callback=null)},n.prototype.get=function(e){return this.slice(e,e+1)[0]},n.prototype.slice=function(e,t){return this.copy(null,0,e,t)},n.prototype.copy=function(e,t,n,o){if(("number"!=typeof n||0>n)&&(n=0),("number"!=typeof o||o>this.length)&&(o=this.length),n>=this.length)return e||new r(0);if(0>=o)return e||new r(0);var i,s,a=!!e,u=this._offset(n),c=o-n,f=c,l=a&&t||0,d=u[1];if(0===n&&o==this.length){if(!a)return r.concat(this._bufs);for(s=0;s<this._bufs.length;s++)this._bufs[s].copy(e,l),l+=this._bufs[s].length;return e}if(f<=this._bufs[u[0]].length-d)return a?this._bufs[u[0]].copy(e,t,d,d+f):this._bufs[u[0]].slice(d,d+f);for(a||(e=new r(c)),s=u[0];s<this._bufs.length;s++){if(i=this._bufs[s].length-d,!(f>i)){this._bufs[s].copy(e,l,d,d+f);break}this._bufs[s].copy(e,l,d),l+=i,f-=i,d&&(d=0)}return e},n.prototype.toString=function(e,t,r){return this.slice(t,r).toString(e)},n.prototype.consume=function(e){for(;this._bufs.length;){if(!(e>this._bufs[0].length)){this._bufs[0]=this._bufs[0].slice(e),this.length-=e;break}e-=this._bufs[0].length,this.length-=this._bufs[0].length,this._bufs.shift()}return this},n.prototype.duplicate=function(){for(var e=0,t=new n;e<this._bufs.length;e++)t.append(this._bufs[e]);return t},n.prototype.destroy=function(){this._bufs.length=0,this.length=0,this.push(null)},function(){var e={readDoubleBE:8,readDoubleLE:8,readFloatBE:4,readFloatLE:4,readInt32BE:4,readInt32LE:4,readUInt32BE:4,readUInt32LE:4,readInt16BE:2,readInt16LE:2,readUInt16BE:2,readUInt16LE:2,readInt8:1,readUInt8:1};for(var t in e)!function(t){n.prototype[t]=function(r){return this.slice(r,r+e[t])[t](0)}}(t)}(),t.exports=n}).call(this,e("buffer").Buffer)},{buffer:17,"readable-stream":95,util:39}],80:[function(e,t){(function(r,n){function o(e){s.call(this,"string"==typeof e?e:""),this._db=void 0,this._operations=[]}var i=e("util"),s=e("abstract-leveldown").AbstractLevelDOWN;i.inherits(o,s),o.prototype.setDb=function(e){this._db=e,this._operations.forEach(function(t){e[t.method].apply(e,t.args)})},o.prototype._open=function(e,t){return r.nextTick(t)},o.prototype._operation=function(e,t){return this._db?this._db[e].apply(this._db,t):void this._operations.push({method:e,args:t})},"put get del batch approximateSize".split(" ").forEach(function(e){o.prototype["_"+e]=function(){this._operation(e,arguments)}}),o.prototype._isBuffer=function(e){return n.isBuffer(e)},o.prototype._iterator=function(){throw new TypeError("not implemented")},t.exports=o}).call(this,e("_process"),e("buffer").Buffer)},{_process:24,"abstract-leveldown":83,buffer:17,util:39}],81:[function(e,t){t.exports=e(46)},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/abstract-leveldown/abstract-chained-batch.js":46,_process:24}],82:[function(e,t){t.exports=e(47)},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/abstract-leveldown/abstract-iterator.js":47,_process:24}],83:[function(e,t){t.exports=e(48)},{"./abstract-chained-batch":81,"./abstract-iterator":82,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/abstract-leveldown/abstract-leveldown.js":48,_process:24,buffer:17,xtend:96}],84:[function(e,t){function r(e,t,r){i(this,{type:e,name:e,cause:"string"!=typeof t?t:r,message:t&&"string"!=typeof t?t.message:t},"ewr")}function n(e,t){Error.call(this),Error.captureStackTrace&&Error.captureStackTrace(this,arguments.callee),r.call(this,"CustomError",e,t)}function o(e,t,o){var i=function(n,o){r.call(this,t,n,o),"FilesystemError"==t&&(this.code=this.cause.code,this.path=this.cause.path,this.errno=this.cause.errno,this.message=(e.errno[this.cause.errno]?e.errno[this.cause.errno].description:this.cause.message)+(this.cause.path?" ["+this.cause.path+"]":"")),Error.call(this),Error.captureStackTrace&&Error.captureStackTrace(this,arguments.callee)};return i.prototype=o?new o:new n,i}var i=e("prr");n.prototype=new Error,t.exports=function(e){var t=function(t,r){return o(e,t,r)};return{CustomError:n,FilesystemError:t("FilesystemError"),createError:t}}},{prr:86}],85:[function(e,t){var r=t.exports.all=[{errno:-1,code:"UNKNOWN",description:"unknown error"},{errno:0,code:"OK",description:"success"},{errno:1,code:"EOF",description:"end of file"},{errno:2,code:"EADDRINFO",description:"getaddrinfo error"},{errno:3,code:"EACCES",description:"permission denied"},{errno:4,code:"EAGAIN",description:"resource temporarily unavailable"},{errno:5,code:"EADDRINUSE",description:"address already in use"},{errno:6,code:"EADDRNOTAVAIL",description:"address not available"},{errno:7,code:"EAFNOSUPPORT",description:"address family not supported"},{errno:8,code:"EALREADY",description:"connection already in progress"},{errno:9,code:"EBADF",description:"bad file descriptor"},{errno:10,code:"EBUSY",description:"resource busy or locked"},{errno:11,code:"ECONNABORTED",description:"software caused connection abort"},{errno:12,code:"ECONNREFUSED",description:"connection refused"},{errno:13,code:"ECONNRESET",description:"connection reset by peer"},{errno:14,code:"EDESTADDRREQ",description:"destination address required"},{errno:15,code:"EFAULT",description:"bad address in system call argument"},{errno:16,code:"EHOSTUNREACH",description:"host is unreachable"},{errno:17,code:"EINTR",description:"interrupted system call"},{errno:18,code:"EINVAL",description:"invalid argument"},{errno:19,code:"EISCONN",description:"socket is already connected"},{errno:20,code:"EMFILE",description:"too many open files"},{errno:21,code:"EMSGSIZE",description:"message too long"},{errno:22,code:"ENETDOWN",description:"network is down"},{errno:23,code:"ENETUNREACH",description:"network is unreachable"},{errno:24,code:"ENFILE",description:"file table overflow"},{errno:25,code:"ENOBUFS",description:"no buffer space available"},{errno:26,code:"ENOMEM",description:"not enough memory"},{errno:27,code:"ENOTDIR",description:"not a directory"},{errno:28,code:"EISDIR",description:"illegal operation on a directory"},{errno:29,code:"ENONET",description:"machine is not on the network"},{errno:31,code:"ENOTCONN",description:"socket is not connected"},{errno:32,code:"ENOTSOCK",description:"socket operation on non-socket"},{errno:33,code:"ENOTSUP",description:"operation not supported on socket"},{errno:34,code:"ENOENT",description:"no such file or directory"},{errno:35,code:"ENOSYS",description:"function not implemented"},{errno:36,code:"EPIPE",description:"broken pipe"},{errno:37,code:"EPROTO",description:"protocol error"},{errno:38,code:"EPROTONOSUPPORT",description:"protocol not supported"},{errno:39,code:"EPROTOTYPE",description:"protocol wrong type for socket"},{errno:40,code:"ETIMEDOUT",description:"connection timed out"},{errno:41,code:"ECHARSET",description:"invalid Unicode character"},{errno:42,code:"EAIFAMNOSUPPORT",description:"address family for hostname not supported"},{errno:44,code:"EAISERVICE",description:"servname not supported for ai_socktype"},{errno:45,code:"EAISOCKTYPE",description:"ai_socktype not supported"},{errno:46,code:"ESHUTDOWN",description:"cannot send after transport endpoint shutdown"},{errno:47,code:"EEXIST",description:"file already exists"},{errno:48,code:"ESRCH",description:"no such process"},{errno:49,code:"ENAMETOOLONG",description:"name too long"},{errno:50,code:"EPERM",description:"operation not permitted"},{errno:51,code:"ELOOP",description:"too many symbolic links encountered"},{errno:52,code:"EXDEV",description:"cross-device link not permitted"},{errno:53,code:"ENOTEMPTY",description:"directory not empty"},{errno:54,code:"ENOSPC",description:"no space left on device"},{errno:55,code:"EIO",description:"i/o error"},{errno:56,code:"EROFS",description:"read-only file system"},{errno:57,code:"ENODEV",description:"no such device"},{errno:58,code:"ESPIPE",description:"invalid seek"},{errno:59,code:"ECANCELED",description:"operation canceled"}];t.exports.errno={"-1":r[0],0:r[1],1:r[2],2:r[3],3:r[4],4:r[5],5:r[6],6:r[7],7:r[8],8:r[9],9:r[10],10:r[11],11:r[12],12:r[13],13:r[14],14:r[15],15:r[16],16:r[17],17:r[18],18:r[19],19:r[20],20:r[21],21:r[22],22:r[23],23:r[24],24:r[25],25:r[26],26:r[27],27:r[28],28:r[29],29:r[30],31:r[31],32:r[32],33:r[33],34:r[34],35:r[35],36:r[36],37:r[37],38:r[38],39:r[39],40:r[40],41:r[41],42:r[42],44:r[43],45:r[44],46:r[45],47:r[46],48:r[47],49:r[48],50:r[49],51:r[50],52:r[51],53:r[52],54:r[53],55:r[54],56:r[55],57:r[56],58:r[57],59:r[58]},t.exports.code={UNKNOWN:r[0],OK:r[1],EOF:r[2],EADDRINFO:r[3],EACCES:r[4],EAGAIN:r[5],EADDRINUSE:r[6],EADDRNOTAVAIL:r[7],EAFNOSUPPORT:r[8],EALREADY:r[9],EBADF:r[10],EBUSY:r[11],ECONNABORTED:r[12],ECONNREFUSED:r[13],ECONNRESET:r[14],EDESTADDRREQ:r[15],EFAULT:r[16],EHOSTUNREACH:r[17],EINTR:r[18],EINVAL:r[19],EISCONN:r[20],EMFILE:r[21],EMSGSIZE:r[22],ENETDOWN:r[23],ENETUNREACH:r[24],ENFILE:r[25],ENOBUFS:r[26],ENOMEM:r[27],ENOTDIR:r[28],EISDIR:r[29],ENONET:r[30],ENOTCONN:r[31],ENOTSOCK:r[32],ENOTSUP:r[33],ENOENT:r[34],ENOSYS:r[35],EPIPE:r[36],EPROTO:r[37],EPROTONOSUPPORT:r[38],EPROTOTYPE:r[39],ETIMEDOUT:r[40],ECHARSET:r[41],EAIFAMNOSUPPORT:r[42],EAISERVICE:r[43],EAISOCKTYPE:r[44],ESHUTDOWN:r[45],EEXIST:r[46],ESRCH:r[47],ENAMETOOLONG:r[48],EPERM:r[49],ELOOP:r[50],EXDEV:r[51],ENOTEMPTY:r[52],ENOSPC:r[53],EIO:r[54],EROFS:r[55],ENODEV:r[56],ESPIPE:r[57],ECANCELED:r[58]},t.exports.custom=e("./custom")(t.exports),t.exports.create=t.exports.custom.createError},{"./custom":84}],86:[function(e,t){!function(e,r,n){"undefined"!=typeof t&&t.exports?t.exports=n():r[e]=n()}("prr",this,function(){var e="function"==typeof Object.defineProperty?function(e,t,r){return Object.defineProperty(e,t,r),e}:function(e,t,r){return e[t]=r.value,e},t=function(e,t){var r="object"==typeof t,n=!r&&"string"==typeof t,o=function(e){return r?!!t[e]:n?t.indexOf(e[0])>-1:!1};return{enumerable:o("enumerable"),configurable:o("configurable"),writable:o("writable"),value:e}},r=function(r,n,o,i){var s;if(i=t(o,i),"object"==typeof n){for(s in n)Object.hasOwnProperty.call(n,s)&&(i.value=n[s],e(r,s,i));return r}return e(r,n,i)};return r})},{}],87:[function(e,t){t.exports=e(26)},{"./_stream_readable":89,"./_stream_writable":91,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_duplex.js":26,_process:24,"core-util-is":92,inherits:44}],88:[function(e,t){t.exports=e(27)},{"./_stream_transform":90,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_passthrough.js":27,"core-util-is":92,inherits:44}],89:[function(e,t){t.exports=e(28)},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_readable.js":28,_process:24,buffer:17,"core-util-is":92,events:21,inherits:44,isarray:93,stream:36,"string_decoder/":94}],90:[function(e,t){t.exports=e(29) +},{"./_stream_duplex":87,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_transform.js":29,"core-util-is":92,inherits:44}],91:[function(e,t){t.exports=e(30)},{"./_stream_duplex":87,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_writable.js":30,_process:24,buffer:17,"core-util-is":92,inherits:44,stream:36}],92:[function(e,t){t.exports=e(31)},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/node_modules/core-util-is/lib/util.js":31,buffer:17}],93:[function(e,t){t.exports=e(22)},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/isarray/index.js":22}],94:[function(e,t){t.exports=e(37)},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/string_decoder/index.js":37,buffer:17}],95:[function(e,t){t.exports=e(33)},{"./lib/_stream_duplex.js":87,"./lib/_stream_passthrough.js":88,"./lib/_stream_readable.js":89,"./lib/_stream_transform.js":90,"./lib/_stream_writable.js":91,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/readable.js":33,stream:36}],96:[function(e,t){t.exports=e(49)},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/abstract-leveldown/node_modules/xtend/index.js":49}],97:[function(e,t){t.exports={name:"levelup",description:"Fast & simple storage - a Node.js-style LevelDB wrapper",version:"0.18.6",contributors:[{name:"Rod Vagg",email:"r@va.gg",url:"https://github.com/rvagg"},{name:"John Chesley",email:"john@chesl.es",url:"https://github.com/chesles/"},{name:"Jake Verbaten",email:"raynos2@gmail.com",url:"https://github.com/raynos"},{name:"Dominic Tarr",email:"dominic.tarr@gmail.com",url:"https://github.com/dominictarr"},{name:"Max Ogden",email:"max@maxogden.com",url:"https://github.com/maxogden"},{name:"Lars-Magnus Skog",email:"lars.magnus.skog@gmail.com",url:"https://github.com/ralphtheninja"},{name:"David Björklund",email:"david.bjorklund@gmail.com",url:"https://github.com/kesla"},{name:"Julian Gruber",email:"julian@juliangruber.com",url:"https://github.com/juliangruber"},{name:"Paolo Fragomeni",email:"paolo@async.ly",url:"https://github.com/hij1nx"},{name:"Anton Whalley",email:"anton.whalley@nearform.com",url:"https://github.com/No9"},{name:"Matteo Collina",email:"matteo.collina@gmail.com",url:"https://github.com/mcollina"},{name:"Pedro Teixeira",email:"pedro.teixeira@gmail.com",url:"https://github.com/pgte"},{name:"James Halliday",email:"mail@substack.net",url:"https://github.com/substack"}],repository:{type:"git",url:"https://github.com/rvagg/node-levelup.git"},homepage:"https://github.com/rvagg/node-levelup",keywords:["leveldb","stream","database","db","store","storage","json"],main:"lib/levelup.js",dependencies:{bl:"~0.8.1","deferred-leveldown":"~0.2.0",errno:"~0.1.1",prr:"~0.0.0","readable-stream":"~1.0.26",semver:"~2.3.1",xtend:"~3.0.0"},devDependencies:{leveldown:"~0.10.0",bustermove:"*",tap:"*",referee:"*",rimraf:"*",async:"*",fstream:"*",tar:"*",mkfiletree:"*",readfiletree:"*","slow-stream":">=0.0.4",delayed:"*",boganipsum:"*",du:"*",memdown:"*","msgpack-js":"*"},browser:{leveldown:!1,"leveldown/package":!1,semver:!1},scripts:{test:"tap test/*-test.js --stderr",functionaltests:"node ./test/functional/fstream-test.js && node ./test/functional/binary-data-test.js && node ./test/functional/compat-test.js",alltests:"npm test && npm run-script functionaltests"},license:"MIT",gitHead:"213e989e2b75273e2b44c23f84f95e35bff7ea11",bugs:{url:"https://github.com/rvagg/node-levelup/issues"},_id:"levelup@0.18.6",_shasum:"e6a01cb089616c8ecc0291c2a9bd3f0c44e3e5eb",_from:"levelup@~0.18.4",_npmVersion:"1.4.14",_npmUser:{name:"rvagg",email:"rod@vagg.org"},maintainers:[{name:"rvagg",email:"rod@vagg.org"}],dist:{shasum:"e6a01cb089616c8ecc0291c2a9bd3f0c44e3e5eb",tarball:"http://127.0.0.1:5080/tarballs/levelup/0.18.6.tgz"},_resolved:"http://127.0.0.1:5080/tarballs/levelup/0.18.6.tgz",readme:"ERROR: No README data found!"}},{}],98:[function(e,t){"use strict";function r(){}t.exports=r},{}],99:[function(e,t){"use strict";function r(e){function t(e,t){function n(e){c[t]=e,++f===r&!u&&(u=!0,a.resolve(d,c))}i(e).then(n,function(e){u||(u=!0,a.reject(d,e))})}if("[object Array]"!==Object.prototype.toString.call(e))return o(new TypeError("must be an array"));var r=e.length,u=!1;if(!r)return i([]);for(var c=new Array(r),f=0,l=-1,d=new n(s);++l<r;)t(e[l],l);return d}var n=e("./promise"),o=e("./reject"),i=e("./resolve"),s=e("./INTERNAL"),a=e("./handlers");t.exports=r},{"./INTERNAL":98,"./handlers":100,"./promise":102,"./reject":105,"./resolve":106}],100:[function(e,t,r){"use strict";function n(e){var t=e&&e.then;return e&&"object"==typeof e&&"function"==typeof t?function(){t.apply(e,arguments)}:void 0}var o=e("./tryCatch"),i=e("./resolveThenable"),s=e("./states");r.resolve=function(e,t){var a=o(n,t);if("error"===a.status)return r.reject(e,a.value);var u=a.value;if(u)i.safely(e,u);else{e.state=s.FULFILLED,e.outcome=t;for(var c=-1,f=e.queue.length;++c<f;)e.queue[c].callFulfilled(t)}return e},r.reject=function(e,t){e.state=s.REJECTED,e.outcome=t;for(var r=-1,n=e.queue.length;++r<n;)e.queue[r].callRejected(t);return e}},{"./resolveThenable":107,"./states":108,"./tryCatch":109}],101:[function(e,t,r){t.exports=r=e("./promise"),r.resolve=e("./resolve"),r.reject=e("./reject"),r.all=e("./all"),r.race=e("./race")},{"./all":99,"./promise":102,"./race":104,"./reject":105,"./resolve":106}],102:[function(e,t){"use strict";function r(e){if(!(this instanceof r))return new r(e);if("function"!=typeof e)throw new TypeError("reslover must be a function");this.state=s.PENDING,this.queue=[],this.outcome=void 0,e!==o&&i.safely(this,e)}var n=e("./unwrap"),o=e("./INTERNAL"),i=e("./resolveThenable"),s=e("./states"),a=e("./queueItem");t.exports=r,r.prototype["catch"]=function(e){return this.then(null,e)},r.prototype.then=function(e,t){if("function"!=typeof e&&this.state===s.FULFILLED||"function"!=typeof t&&this.state===s.REJECTED)return this;var i=new r(o);if(this.state!==s.PENDING){var u=this.state===s.FULFILLED?e:t;n(i,u,this.outcome)}else this.queue.push(new a(i,e,t));return i}},{"./INTERNAL":98,"./queueItem":103,"./resolveThenable":107,"./states":108,"./unwrap":110}],103:[function(e,t){"use strict";function r(e,t,r){this.promise=e,"function"==typeof t&&(this.onFulfilled=t,this.callFulfilled=this.otherCallFulfilled),"function"==typeof r&&(this.onRejected=r,this.callRejected=this.otherCallRejected)}var n=e("./handlers"),o=e("./unwrap");t.exports=r,r.prototype.callFulfilled=function(e){n.resolve(this.promise,e)},r.prototype.otherCallFulfilled=function(e){o(this.promise,this.onFulfilled,e)},r.prototype.callRejected=function(e){n.reject(this.promise,e)},r.prototype.otherCallRejected=function(e){o(this.promise,this.onRejected,e)}},{"./handlers":100,"./unwrap":110}],104:[function(e,t){"use strict";function r(e){function t(e){i(e).then(function(e){u||(u=!0,a.resolve(f,e))},function(e){u||(u=!0,a.reject(f,e))})}if("[object Array]"!==Object.prototype.toString.call(e))return o(new TypeError("must be an array"));var r=e.length,u=!1;if(!r)return i([]);for(var c=-1,f=new n(s);++c<r;)t(e[c]);return f}var n=e("./promise"),o=e("./reject"),i=e("./resolve"),s=e("./INTERNAL"),a=e("./handlers");t.exports=r},{"./INTERNAL":98,"./handlers":100,"./promise":102,"./reject":105,"./resolve":106}],105:[function(e,t){"use strict";function r(e){var t=new n(o);return i.reject(t,e)}var n=e("./promise"),o=e("./INTERNAL"),i=e("./handlers");t.exports=r},{"./INTERNAL":98,"./handlers":100,"./promise":102}],106:[function(e,t){"use strict";function r(e){if(e)return e instanceof n?e:i.resolve(new n(o),e);var t=typeof e;switch(t){case"boolean":return s;case"undefined":return u;case"object":return a;case"number":return c;case"string":return f}}var n=e("./promise"),o=e("./INTERNAL"),i=e("./handlers");t.exports=r;var s=i.resolve(new n(o),!1),a=i.resolve(new n(o),null),u=i.resolve(new n(o),void 0),c=i.resolve(new n(o),0),f=i.resolve(new n(o),"")},{"./INTERNAL":98,"./handlers":100,"./promise":102}],107:[function(e,t,r){"use strict";function n(e,t){function r(t){a||(a=!0,o.reject(e,t))}function n(t){a||(a=!0,o.resolve(e,t))}function s(){t(n,r)}var a=!1,u=i(s);"error"===u.status&&r(u.value)}var o=e("./handlers"),i=e("./tryCatch");r.safely=n},{"./handlers":100,"./tryCatch":109}],108:[function(e,t,r){r.REJECTED=["REJECTED"],r.FULFILLED=["FULFILLED"],r.PENDING=["PENDING"]},{}],109:[function(e,t){"use strict";function r(e,t){var r={};try{r.value=e(t),r.status="success"}catch(n){r.status="error",r.value=n}return r}t.exports=r},{}],110:[function(e,t){"use strict";function r(e,t,r){n(function(){var n;try{n=t(r)}catch(i){return o.reject(e,i)}n===e?o.reject(e,new TypeError("Cannot resolve promise with itself")):o.resolve(e,n)})}var n=e("immediate"),o=e("./handlers");t.exports=r},{"./handlers":100,immediate:111}],111:[function(e,t){"use strict";function r(){o=!0;for(var e,t,r=a.length;r;){for(t=a,a=[],e=-1;++e<r;)t[e]();r=a.length}o=!1}function n(e){1!==a.push(e)||o||i()}for(var o,i,s=[e("./nextTick"),e("./mutation.js"),e("./messageChannel"),e("./stateChange"),e("./timeout")],a=[],u=-1,c=s.length;++u<c;)if(s[u]&&s[u].test&&s[u].test()){i=s[u].install(r);break}t.exports=n},{"./messageChannel":112,"./mutation.js":113,"./nextTick":16,"./stateChange":114,"./timeout":115}],112:[function(e,t,r){(function(e){"use strict";r.test=function(){return e.setImmediate?!1:"undefined"!=typeof e.MessageChannel},r.install=function(t){var r=new e.MessageChannel;return r.port1.onmessage=t,function(){r.port2.postMessage(0)}}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],113:[function(e,t,r){(function(e){"use strict";var t=e.MutationObserver||e.WebKitMutationObserver;r.test=function(){return t},r.install=function(r){var n=0,o=new t(r),i=e.document.createTextNode("");return o.observe(i,{characterData:!0}),function(){i.data=n=++n%2}}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],114:[function(e,t,r){(function(e){"use strict";r.test=function(){return"document"in e&&"onreadystatechange"in e.document.createElement("script")},r.install=function(t){return function(){var r=e.document.createElement("script");return r.onreadystatechange=function(){t(),r.onreadystatechange=null,r.parentNode.removeChild(r),r=null},e.document.documentElement.appendChild(r),t}}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],115:[function(e,t,r){"use strict";r.test=function(){return!0},r.install=function(e){return function(){setTimeout(e,0)}}},{}],116:[function(e,t){"use strict";function r(e){return null===e?String(e):"object"==typeof e||"function"==typeof e?u[d.call(e)]||"object":typeof e}function n(e){return null!==e&&e===e.window}function o(e){if(!e||"object"!==r(e)||e.nodeType||n(e))return!1;try{if(e.constructor&&!h.call(e,"constructor")&&!h.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(t){return!1}var o;for(o in e);return void 0===o||h.call(e,o)}function i(e){return"function"===r(e)}function s(){for(var e=[],t=-1,r=arguments.length,n=new Array(r);++t<r;)n[t]=arguments[t];var o={};e.push({args:n,result:{container:o,key:"key"}});for(var i;i=e.pop();)a(e,i.args,i.result);return o.key}function a(e,t,r){var n,s,a,u,c,f,l,d=t[0]||{},h=1,v=t.length,y=!1,g=/\d+/;for("boolean"==typeof d&&(y=d,d=t[1]||{},h=2),"object"==typeof d||i(d)||(d={}),v===h&&(d=this,--h);v>h;h++)if(null!=(n=t[h])){l=p(n);for(s in n)if(!(s in Object.prototype)){if(l&&!g.test(s))continue;if(a=d[s],u=n[s],d===u)continue;y&&u&&(o(u)||(c=p(u)))?(c?(c=!1,f=a&&p(a)?a:[]):f=a&&o(a)?a:{},e.push({args:[y,f,u],result:{container:d,key:s}})):void 0!==u&&(p(n)&&i(u)||(d[s]=u))}}r.container[r.key]=d}for(var u={},c=["Boolean","Number","String","Function","Array","Date","RegExp","Object","Error"],f=0;f<c.length;f++){var l=c[f];u["[object "+l+"]"]=l.toLowerCase()}var d=u.toString,h=u.hasOwnProperty,p=Array.isArray||function(e){return"array"===r(e)};t.exports=s},{}],117:[function(e,t,r){!function(e){if("object"==typeof r)t.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var n;try{n=window}catch(o){n=self}n.SparkMD5=e()}}(function(){"use strict";var e=function(e,t){return e+t&4294967295},t=function(t,r,n,o,i,s){return r=e(e(r,t),e(o,s)),e(r<<i|r>>>32-i,n)},r=function(e,r,n,o,i,s,a){return t(r&n|~r&o,e,r,i,s,a)},n=function(e,r,n,o,i,s,a){return t(r&o|n&~o,e,r,i,s,a)},o=function(e,r,n,o,i,s,a){return t(r^n^o,e,r,i,s,a)},i=function(e,r,n,o,i,s,a){return t(n^(r|~o),e,r,i,s,a)},s=function(t,s){var a=t[0],u=t[1],c=t[2],f=t[3];a=r(a,u,c,f,s[0],7,-680876936),f=r(f,a,u,c,s[1],12,-389564586),c=r(c,f,a,u,s[2],17,606105819),u=r(u,c,f,a,s[3],22,-1044525330),a=r(a,u,c,f,s[4],7,-176418897),f=r(f,a,u,c,s[5],12,1200080426),c=r(c,f,a,u,s[6],17,-1473231341),u=r(u,c,f,a,s[7],22,-45705983),a=r(a,u,c,f,s[8],7,1770035416),f=r(f,a,u,c,s[9],12,-1958414417),c=r(c,f,a,u,s[10],17,-42063),u=r(u,c,f,a,s[11],22,-1990404162),a=r(a,u,c,f,s[12],7,1804603682),f=r(f,a,u,c,s[13],12,-40341101),c=r(c,f,a,u,s[14],17,-1502002290),u=r(u,c,f,a,s[15],22,1236535329),a=n(a,u,c,f,s[1],5,-165796510),f=n(f,a,u,c,s[6],9,-1069501632),c=n(c,f,a,u,s[11],14,643717713),u=n(u,c,f,a,s[0],20,-373897302),a=n(a,u,c,f,s[5],5,-701558691),f=n(f,a,u,c,s[10],9,38016083),c=n(c,f,a,u,s[15],14,-660478335),u=n(u,c,f,a,s[4],20,-405537848),a=n(a,u,c,f,s[9],5,568446438),f=n(f,a,u,c,s[14],9,-1019803690),c=n(c,f,a,u,s[3],14,-187363961),u=n(u,c,f,a,s[8],20,1163531501),a=n(a,u,c,f,s[13],5,-1444681467),f=n(f,a,u,c,s[2],9,-51403784),c=n(c,f,a,u,s[7],14,1735328473),u=n(u,c,f,a,s[12],20,-1926607734),a=o(a,u,c,f,s[5],4,-378558),f=o(f,a,u,c,s[8],11,-2022574463),c=o(c,f,a,u,s[11],16,1839030562),u=o(u,c,f,a,s[14],23,-35309556),a=o(a,u,c,f,s[1],4,-1530992060),f=o(f,a,u,c,s[4],11,1272893353),c=o(c,f,a,u,s[7],16,-155497632),u=o(u,c,f,a,s[10],23,-1094730640),a=o(a,u,c,f,s[13],4,681279174),f=o(f,a,u,c,s[0],11,-358537222),c=o(c,f,a,u,s[3],16,-722521979),u=o(u,c,f,a,s[6],23,76029189),a=o(a,u,c,f,s[9],4,-640364487),f=o(f,a,u,c,s[12],11,-421815835),c=o(c,f,a,u,s[15],16,530742520),u=o(u,c,f,a,s[2],23,-995338651),a=i(a,u,c,f,s[0],6,-198630844),f=i(f,a,u,c,s[7],10,1126891415),c=i(c,f,a,u,s[14],15,-1416354905),u=i(u,c,f,a,s[5],21,-57434055),a=i(a,u,c,f,s[12],6,1700485571),f=i(f,a,u,c,s[3],10,-1894986606),c=i(c,f,a,u,s[10],15,-1051523),u=i(u,c,f,a,s[1],21,-2054922799),a=i(a,u,c,f,s[8],6,1873313359),f=i(f,a,u,c,s[15],10,-30611744),c=i(c,f,a,u,s[6],15,-1560198380),u=i(u,c,f,a,s[13],21,1309151649),a=i(a,u,c,f,s[4],6,-145523070),f=i(f,a,u,c,s[11],10,-1120210379),c=i(c,f,a,u,s[2],15,718787259),u=i(u,c,f,a,s[9],21,-343485551),t[0]=e(a,t[0]),t[1]=e(u,t[1]),t[2]=e(c,t[2]),t[3]=e(f,t[3])},a=function(e){var t,r=[];for(t=0;64>t;t+=4)r[t>>2]=e.charCodeAt(t)+(e.charCodeAt(t+1)<<8)+(e.charCodeAt(t+2)<<16)+(e.charCodeAt(t+3)<<24);return r},u=function(e){var t,r=[];for(t=0;64>t;t+=4)r[t>>2]=e[t]+(e[t+1]<<8)+(e[t+2]<<16)+(e[t+3]<<24);return r},c=function(e){var t,r,n,o,i,u,c=e.length,f=[1732584193,-271733879,-1732584194,271733878];for(t=64;c>=t;t+=64)s(f,a(e.substring(t-64,t)));for(e=e.substring(t-64),r=e.length,n=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],t=0;r>t;t+=1)n[t>>2]|=e.charCodeAt(t)<<(t%4<<3);if(n[t>>2]|=128<<(t%4<<3),t>55)for(s(f,n),t=0;16>t;t+=1)n[t]=0;return o=8*c,o=o.toString(16).match(/(.*?)(.{0,8})$/),i=parseInt(o[2],16),u=parseInt(o[1],16)||0,n[14]=i,n[15]=u,s(f,n),f},f=function(e){var t,r,n,o,i,a,c=e.length,f=[1732584193,-271733879,-1732584194,271733878];for(t=64;c>=t;t+=64)s(f,u(e.subarray(t-64,t)));for(e=c>t-64?e.subarray(t-64):new Uint8Array(0),r=e.length,n=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],t=0;r>t;t+=1)n[t>>2]|=e[t]<<(t%4<<3);if(n[t>>2]|=128<<(t%4<<3),t>55)for(s(f,n),t=0;16>t;t+=1)n[t]=0;return o=8*c,o=o.toString(16).match(/(.*?)(.{0,8})$/),i=parseInt(o[2],16),a=parseInt(o[1],16)||0,n[14]=i,n[15]=a,s(f,n),f},l=["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"],d=function(e){var t,r="";for(t=0;4>t;t+=1)r+=l[e>>8*t+4&15]+l[e>>8*t&15];return r},h=function(e){var t;for(t=0;t<e.length;t+=1)e[t]=d(e[t]);return e.join("")},p=function(e){return h(c(e))},v=function(){this.reset()};return"5d41402abc4b2a76b9719d911017c592"!==p("hello")&&(e=function(e,t){var r=(65535&e)+(65535&t),n=(e>>16)+(t>>16)+(r>>16);return n<<16|65535&r}),v.prototype.append=function(e){return/[\u0080-\uFFFF]/.test(e)&&(e=unescape(encodeURIComponent(e))),this.appendBinary(e),this},v.prototype.appendBinary=function(e){this._buff+=e,this._length+=e.length;var t,r=this._buff.length;for(t=64;r>=t;t+=64)s(this._state,a(this._buff.substring(t-64,t)));return this._buff=this._buff.substr(t-64),this},v.prototype.end=function(e){var t,r,n=this._buff,o=n.length,i=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];for(t=0;o>t;t+=1)i[t>>2]|=n.charCodeAt(t)<<(t%4<<3);return this._finish(i,o),r=e?this._state:h(this._state),this.reset(),r},v.prototype._finish=function(e,t){var r,n,o,i=t;if(e[i>>2]|=128<<(i%4<<3),i>55)for(s(this._state,e),i=0;16>i;i+=1)e[i]=0;r=8*this._length,r=r.toString(16).match(/(.*?)(.{0,8})$/),n=parseInt(r[2],16),o=parseInt(r[1],16)||0,e[14]=n,e[15]=o,s(this._state,e)},v.prototype.reset=function(){return this._buff="",this._length=0,this._state=[1732584193,-271733879,-1732584194,271733878],this},v.prototype.destroy=function(){delete this._state,delete this._buff,delete this._length},v.hash=function(e,t){/[\u0080-\uFFFF]/.test(e)&&(e=unescape(encodeURIComponent(e)));var r=c(e);return t?r:h(r)},v.hashBinary=function(e,t){var r=c(e);return t?r:h(r)},v.ArrayBuffer=function(){this.reset()},v.ArrayBuffer.prototype.append=function(e){var t,r=this._concatArrayBuffer(this._buff,e),n=r.length;for(this._length+=e.byteLength,t=64;n>=t;t+=64)s(this._state,u(r.subarray(t-64,t)));return this._buff=n>t-64?r.subarray(t-64):new Uint8Array(0),this},v.ArrayBuffer.prototype.end=function(e){var t,r,n=this._buff,o=n.length,i=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];for(t=0;o>t;t+=1)i[t>>2]|=n[t]<<(t%4<<3);return this._finish(i,o),r=e?this._state:h(this._state),this.reset(),r},v.ArrayBuffer.prototype._finish=v.prototype._finish,v.ArrayBuffer.prototype.reset=function(){return this._buff=new Uint8Array(0),this._length=0,this._state=[1732584193,-271733879,-1732584194,271733878],this},v.ArrayBuffer.prototype.destroy=v.prototype.destroy,v.ArrayBuffer.prototype._concatArrayBuffer=function(e,t){var r=e.length,n=new Uint8Array(r+t.byteLength);return n.set(e),n.set(new Uint8Array(t),r),n},v.ArrayBuffer.hash=function(e,t){var r=f(new Uint8Array(e));return t?r:h(r)},v})},{}],118:[function(e,t){t.exports=e(26)},{"./_stream_readable":119,"./_stream_writable":121,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_duplex.js":26,_process:24,"core-util-is":122,inherits:44}],119:[function(e,t){t.exports=e(28)},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_readable.js":28,_process:24,buffer:17,"core-util-is":122,events:21,inherits:44,isarray:123,stream:36,"string_decoder/":124}],120:[function(e,t){t.exports=e(29)},{"./_stream_duplex":118,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_transform.js":29,"core-util-is":122,inherits:44}],121:[function(e,t){t.exports=e(30)},{"./_stream_duplex":118,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_writable.js":30,_process:24,buffer:17,"core-util-is":122,inherits:44,stream:36}],122:[function(e,t){t.exports=e(31)},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/node_modules/core-util-is/lib/util.js":31,buffer:17}],123:[function(e,t){t.exports=e(22)},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/isarray/index.js":22}],124:[function(e,t){t.exports=e(37)},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/string_decoder/index.js":37,buffer:17}],125:[function(e,t){t.exports=e(34)},{"./lib/_stream_transform.js":120,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/transform.js":34}],126:[function(e,t){t.exports=e(54)},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/has-keys.js":54}],127:[function(e,t){t.exports=e(55)},{"./has-keys":126,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/index.js":55,"object-keys":129}],128:[function(e,t){t.exports=e(56)},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/foreach.js":56}],129:[function(e,t){t.exports=e(57)},{"./shim":131,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/index.js":57}],130:[function(e,t){t.exports=e(58)},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/isArguments.js":58}],131:[function(e,t){t.exports=e(59)},{"./foreach":128,"./isArguments":130,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/shim.js":59}],132:[function(e,t){function r(e,t,r){r(null,e)}function n(e){return function(t,n,o){return"function"==typeof t&&(o=n,n=t,t={}),"function"!=typeof n&&(n=r),"function"!=typeof o&&(o=null),e(t,n,o)}}var o=e("readable-stream/transform"),i=e("util").inherits,s=e("xtend");t.exports=n(function(e,t,r){var n=new o(e);return n._transform=t,r&&(n._flush=r),n}),t.exports.ctor=n(function(e,t,r){function n(t){return this instanceof n?(this.options=s(e,t),void o.call(this,this.options)):new n(t)}return i(n,o),n.prototype._transform=t,r&&(n.prototype._flush=r),n}),t.exports.obj=n(function(e,t,r){var n=new o(s({objectMode:!0},e));return n._transform=t,r&&(n._flush=r),n})},{"readable-stream/transform":125,util:39,xtend:127}],133:[function(e,t,r){"use strict";function n(e,t,r){var n=r[r.length-1];e===n.element&&(r.pop(),n=r[r.length-1]);var o=n.element,i=n.index;if(Array.isArray(o))o.push(e);else if(i===t.length-2){var s=t.pop();o[s]=e}else t.push(e)}r.stringify=function(e){var t=[];t.push({obj:e});for(var r,n,o,i,s,a,u,c,f,l,d,h="";r=t.pop();)if(n=r.obj,o=r.prefix||"",i=r.val||"",h+=o,i)h+=i;else if("object"!=typeof n)h+="undefined"==typeof n?null:JSON.stringify(n);else if(null===n)h+="null";else if(Array.isArray(n)){for(t.push({val:"]"}),s=n.length-1;s>=0;s--)a=0===s?"":",",t.push({obj:n[s],prefix:a});t.push({val:"["})}else{u=[];for(c in n)n.hasOwnProperty(c)&&u.push(c);for(t.push({val:"}"}),s=u.length-1;s>=0;s--)f=u[s],l=n[f],d=s>0?",":"",d+=JSON.stringify(f)+":",t.push({obj:l,prefix:d});t.push({val:"{"})}return h},r.parse=function(e){for(var t,r,o,i,s,a,u,c,f,l=[],d=[],h=0;;)if(t=e[h++],"}"!==t&&"]"!==t&&"undefined"!=typeof t)switch(t){case" ":case" ":case"\n":case":":case",":break;case"n":h+=3,n(null,l,d);break;case"t":h+=3,n(!0,l,d);break;case"f":h+=4,n(!1,l,d);break;case"0":case"1":case"2":case"3":case"4":case"5":case"6":case"7":case"8":case"9":case"-":for(r="",h--;;){if(o=e[h++],!/[\d\.\-e\+]/.test(o)){h--;break}r+=o}n(parseFloat(r),l,d);break;case'"':for(i="",s=void 0,a=0;;){if(u=e[h++],'"'===u&&("\\"!==s||a%2!==1))break;i+=u,s=u,"\\"===s?a++:a=0}n(JSON.parse('"'+i+'"'),l,d);break;case"[":c={element:[],index:l.length},l.push(c.element),d.push(c);break;case"{":f={element:{},index:l.length},l.push(f.element),d.push(f);break;default:throw new Error("unexpectedly reached end of input: "+t)}else{if(1===l.length)return l.pop();n(l.pop(),l,d)}}},{}],"adapter-config":[function(e,t){(function(r){"use strict";t.exports={name:"idb-alt",valid:function(){var t=r.PouchDB||e("pouchdb");return"idb"in t.adapters&&t.adapters.idb.valid()},use_prefix:!0}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{pouchdb:"pouchdb"}],leveldown:[function(e,t){(function(r){function n(e){if(!(this instanceof n))return new n(e);if(!e)throw new Error("constructor requires at least a location argument");this.IDBOptions={},this.location=e}t.exports=n;var o=e("idb-wrapper"),i=e("abstract-leveldown").AbstractLevelDOWN,s=e("util"),a=e("./iterator"),u=e("isbuffer"),c=e("xtend"),f=e("typedarray-to-buffer");s.inherits(n,i),n.prototype._open=function(e,t){var r=this,n={storeName:this.location,autoIncrement:!1,keyPath:null,onStoreReady:function(){t&&t(null,r.idb)},onError:function(e){t&&t(e)}};c(n,e),this.IDBOptions=n,this.idb=new o(n)},n.prototype._get=function(e,t,n){this.idb.get(e,function(o){if(void 0===o)return n(new Error("NotFound"));var i=!0;return t.asBuffer===!1&&(i=!1),t.raw&&(i=!1),i&&(o=o instanceof Uint8Array?f(o):new r(String(o))),n(null,o,e)},n)},n.prototype._del=function(e,t,r){this.idb.remove(e,r,r)},n.prototype._put=function(e,t,n,o){t instanceof ArrayBuffer&&(t=f(new Uint8Array(t)));var i=this.convertEncoding(e,t,n);r.isBuffer(i.value)&&(i.value=new Uint8Array(t.toArrayBuffer())),this.idb.put(i.key,i.value,function(){o()},o)},n.prototype.convertEncoding=function(e,t,r){if(r.raw)return{key:e,value:t};if(t){var n=t.toString();"NaN"===n&&(t="NaN")}var o=r.valueEncoding,i={key:e,value:t};return!t||o&&"binary"===o||"object"!=typeof i.value&&(i.value=n),i},n.prototype.iterator=function(e){return"object"!=typeof e&&(e={}),new a(this.idb,e)},n.prototype._batch=function(e,t,r){var n,o,i,s,a=[];if(0===e.length)return setTimeout(r,0);for(n=0;n<e.length;n++){i={},s=e[n],a[n]=i;var u=this.convertEncoding(s.key,s.value,t);s.key=u.key,s.value=u.value;for(o in s)i[o]="type"===o&&"del"==s[o]?"remove":s[o]}return this.idb.batch(a,function(){r()},r)},n.prototype._close=function(e){this.idb.db.close(),e()},n.prototype._approximateSize=function(e,t,r){var n=new Error("Not implemented");if(r)return r(n);throw n},n.prototype._isBuffer=function(e){return r.isBuffer(e)},n.destroy=function(e,t){if("object"==typeof e)var r=e.IDBOptions.storePrefix||"IDBWrapper-",n=e.location;else var r="IDBWrapper-",n=e;var o=indexedDB.deleteDatabase(r+n);o.onsuccess=function(){t()},o.onerror=function(e){t(e)}};n.prototype._checkKeyValue=function(e,t){return null===e||void 0===e?new Error(t+" cannot be `null` or `undefined`"):null===e||void 0===e?new Error(t+" cannot be `null` or `undefined`"):u(e)&&0===e.byteLength?new Error(t+" cannot be an empty ArrayBuffer"):""===String(e)?new Error(t+" cannot be an empty String"):0===e.length?new Error(t+" cannot be an empty Array"):void 0}}).call(this,e("buffer").Buffer)},{"./iterator":45,"abstract-leveldown":48,buffer:17,"idb-wrapper":50,isbuffer:51,"typedarray-to-buffer":53,util:39,xtend:55}]},{},[11]); \ No newline at end of file
diff --git a/tests/integration/deps/pouchdb-3.0.6-postfixed.js b/dist/pouchdb.js similarity index 70% rename from tests/integration/deps/pouchdb-3.0.6-postfixed.js rename to dist/pouchdb.js index 0ed3dfd..ad5e695 100644 --- a/tests/integration/deps/pouchdb-3.0.6-postfixed.js +++ b/dist/pouchdb.js
@@ -1,10 +1,10 @@ -// PouchDBVersion306 3.0.6 +// PouchDB 3.2.0 // -// (c) 2012-2014 Dale Harvey and the PouchDBVersion306 team -// PouchDBVersion306 may be freely distributed under the Apache license, version 2.0. +// (c) 2012-2014 Dale Harvey and the PouchDB team +// PouchDB may be freely distributed under the Apache license, version 2.0. // For all details and documentation: // http://pouchdb.com -!function(e){if("object"==typeof exports)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.PouchDBVersion306=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);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ +!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.PouchDB=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<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ "use strict"; var utils = _dereq_('./utils'); @@ -33,10 +33,10 @@ // if the first result is an error, return an error function yankError(callback) { return function (err, results) { - if (err || results[0].error) { + if (err || (results[0] && results[0].error)) { callback(err || results[0]); } else { - callback(null, results[0]); + callback(null, results.length ? results[0] : results); } }; } @@ -101,10 +101,10 @@ }); } -utils.inherits(AbstractPouchDBVersion306, EventEmitter); -module.exports = AbstractPouchDBVersion306; +utils.inherits(AbstractPouchDB, EventEmitter); +module.exports = AbstractPouchDB; -function AbstractPouchDBVersion306() { +function AbstractPouchDB() { var self = this; EventEmitter.call(this); self.autoCompact = function (callback) { @@ -129,7 +129,7 @@ res.forEach(function (doc) { if (doc.ok && doc.id) { // if no id, then it was a local doc // TODO: we need better error handling - self.compactDocument(doc.id, 1, decCount); + self.compactDocument(doc.id, 0, decCount); } else { decCount(); } @@ -186,7 +186,7 @@ }); } -AbstractPouchDBVersion306.prototype.post = +AbstractPouchDB.prototype.post = utils.adapterFun('post', function (doc, opts, callback) { if (typeof opts === 'function') { callback = opts; @@ -199,7 +199,7 @@ this.autoCompact(yankError(callback))); }); -AbstractPouchDBVersion306.prototype.put = +AbstractPouchDB.prototype.put = utils.adapterFun('put', utils.getArguments(function (args) { var temp, temptype, opts, callback; var doc = args.shift(); @@ -242,7 +242,7 @@ this.autoCompact(yankError(callback))); })); -AbstractPouchDBVersion306.prototype.putAttachment = +AbstractPouchDB.prototype.putAttachment = utils.adapterFun('putAttachment', function (docId, attachmentId, rev, blob, type, callback) { var api = this; @@ -283,7 +283,7 @@ }); }); -AbstractPouchDBVersion306.prototype.removeAttachment = +AbstractPouchDB.prototype.removeAttachment = utils.adapterFun('removeAttachment', function (docId, attachmentId, rev, callback) { var self = this; @@ -307,7 +307,7 @@ }); }); -AbstractPouchDBVersion306.prototype.remove = +AbstractPouchDB.prototype.remove = utils.adapterFun('remove', function (docOrId, optsOrRev, opts, callback) { var doc; if (typeof optsOrRev === 'string') { @@ -341,7 +341,7 @@ this.bulkDocs({docs: [newDoc]}, opts, yankError(callback)); }); -AbstractPouchDBVersion306.prototype.revsDiff = +AbstractPouchDB.prototype.revsDiff = utils.adapterFun('revsDiff', function (req, opts, callback) { if (typeof opts === 'function') { callback = opts; @@ -413,36 +413,35 @@ // compact one document and fire callback // by compacting we mean removing all revisions which // are further from the leaf in revision tree than max_height -AbstractPouchDBVersion306.prototype.compactDocument = - utils.adapterFun('compactDocument', function (docId, max_height, callback) { +AbstractPouchDB.prototype.compactDocument = + utils.adapterFun('compactDocument', function (docId, maxHeight, callback) { var self = this; - this._getRevisionTree(docId, function (err, rev_tree) { + this._getRevisionTree(docId, function (err, revTree) { if (err) { return callback(err); } - var height = computeHeight(rev_tree); + var height = computeHeight(revTree); var candidates = []; var revs = []; Object.keys(height).forEach(function (rev) { - if (height[rev] > max_height) { + if (height[rev] > maxHeight) { candidates.push(rev); } }); - merge.traverseRevTree(rev_tree, function (isLeaf, pos, revHash, ctx, opts) { + merge.traverseRevTree(revTree, function (isLeaf, pos, revHash, ctx, opts) { var rev = pos + '-' + revHash; if (opts.status === 'available' && candidates.indexOf(rev) !== -1) { - opts.status = 'missing'; revs.push(rev); } }); - self._doCompaction(docId, rev_tree, revs, callback); + self._doCompaction(docId, revs, callback); }); }); // compact the whole database using single document // compaction -AbstractPouchDBVersion306.prototype.compact = +AbstractPouchDB.prototype.compact = utils.adapterFun('compact', function (opts, callback) { if (typeof opts === 'function') { callback = opts; @@ -464,7 +463,7 @@ }); }); -AbstractPouchDBVersion306.prototype._compact = function (opts, callback) { +AbstractPouchDB.prototype._compact = function (opts, callback) { var done = false; var started = 0; var copts = { @@ -473,14 +472,12 @@ var self = this; var lastSeq; function finish() { - self.get('_local/compaction')["catch"](function () { - return false; - }).then(function (doc) { - doc = doc || {_id: '_local/compaction'}; - doc.last_seq = lastSeq; - return self.put(doc); - }).then(function () { - callback(); + upsert(self, '_local/compaction', function (doc) { + if (!doc.last_seq || doc.last_seq < lastSeq) { + doc.last_seq = lastSeq; + return doc; + } + return false; // somebody else got here first, don't update }, callback); } if (opts.last_seq) { @@ -506,7 +503,7 @@ }; /* Begin api wrappers. Specific functionality to storage belongs in the _[method] */ -AbstractPouchDBVersion306.prototype.get = +AbstractPouchDB.prototype.get = utils.adapterFun('get', function (id, opts, callback) { if (typeof opts === 'function') { callback = opts; @@ -646,6 +643,7 @@ var att = doc._attachments[key]; att.data = data; delete att.stub; + delete att.length; if (!--count) { callback(null, doc); } @@ -664,7 +662,7 @@ }); }); -AbstractPouchDBVersion306.prototype.getAttachment = +AbstractPouchDB.prototype.getAttachment = utils.adapterFun('getAttachment', function (docId, attachmentId, opts, callback) { var self = this; @@ -686,7 +684,7 @@ }); }); -AbstractPouchDBVersion306.prototype.allDocs = +AbstractPouchDB.prototype.allDocs = utils.adapterFun('allDocs', function (opts, callback) { if (typeof opts === 'function') { callback = opts; @@ -717,7 +715,7 @@ return this._allDocs(opts, callback); }); -AbstractPouchDBVersion306.prototype.changes = function (opts, callback) { +AbstractPouchDB.prototype.changes = function (opts, callback) { if (typeof opts === 'function') { callback = opts; opts = {}; @@ -725,13 +723,13 @@ return new Changes(this, opts, callback); }; -AbstractPouchDBVersion306.prototype.close = +AbstractPouchDB.prototype.close = utils.adapterFun('close', function (callback) { this._closed = true; return this._close(callback); }); -AbstractPouchDBVersion306.prototype.info = utils.adapterFun('info', function (callback) { +AbstractPouchDB.prototype.info = utils.adapterFun('info', function (callback) { var self = this; this._info(function (err, info) { if (err) { @@ -744,15 +742,15 @@ }); }); -AbstractPouchDBVersion306.prototype.id = utils.adapterFun('id', function (callback) { +AbstractPouchDB.prototype.id = utils.adapterFun('id', function (callback) { return this._id(callback); }); -AbstractPouchDBVersion306.prototype.type = function () { +AbstractPouchDB.prototype.type = function () { return (typeof this._type === 'function') ? this._type() : this.adapter; }; -AbstractPouchDBVersion306.prototype.bulkDocs = +AbstractPouchDB.prototype.bulkDocs = utils.adapterFun('bulkDocs', function (req, opts, callback) { if (typeof opts === 'function') { callback = opts; @@ -786,13 +784,53 @@ } } - return this._bulkDocs(req, opts, this.autoCompact(callback)); + if (!opts.new_edits && this.type() !== 'http') { + // ensure revisions of the same doc are sorted, so that + // the local adapter processes them correctly (#2935) + req.docs.sort(function (a, b) { + var idCompare = utils.compare(a._id, b._id); + if (idCompare !== 0) { + return idCompare; + } + var aStart = a._revisions ? a._revisions.start : 0; + var bStart = b._revisions ? b._revisions.start : 0; + return utils.compare(aStart, bStart); + }); + } + + req.docs.forEach(function (doc) { + if (doc._deleted) { + delete doc._attachments; // ignore atts for deleted docs + } + }); + + return this._bulkDocs(req, opts, this.autoCompact(function (err, res) { + if (err) { + return callback(err); + } + if (!opts.new_edits) { + // this is what couch does when new_edits is false + res = res.filter(function (x) { + return x.error; + }); + } + callback(null, res); + })); }); -AbstractPouchDBVersion306.prototype.registerDependentDatabase = +AbstractPouchDB.prototype.registerDependentDatabase = utils.adapterFun('registerDependentDatabase', function (dependentDb, callback) { - var depDB = new this.constructor(dependentDb, {adapter: this._adapter}); + var opts = {}; + if (this.__opts.db) { + opts.db = this.__opts.db; + } + if (this._adapter) { + opts.adapter = this._adapter; + } + + var depDB = new this.constructor(dependentDb, opts); + function diffFun(doc) { doc.dependentDbs = doc.dependentDbs || {}; if (doc.dependentDbs[dependentDb]) { @@ -809,36 +847,23 @@ }); }); -},{"./changes":6,"./deps/errors":11,"./deps/upsert":13,"./merge":18,"./utils":23,"events":27}],2:[function(_dereq_,module,exports){ -(function (process){ +},{"./changes":6,"./deps/errors":12,"./deps/upsert":16,"./merge":20,"./utils":25,"events":33}],2:[function(_dereq_,module,exports){ +(function (process,Buffer){ "use strict"; var CHANGES_BATCH_SIZE = 25; +// according to http://stackoverflow.com/a/417184/680742, +// the de factor URL length limit is 2000 characters. +// but since most of our measurements don't take the full +// URL into account, we fudge it a bit. +// TODO: we could measure the full URL to enforce exactly 2000 chars +var MAX_URL_LENGTH = 1800; + var utils = _dereq_('../utils'); var errors = _dereq_('../deps/errors'); -// parseUri 1.2.2 -// (c) Steven Levithan <stevenlevithan.com> -// MIT License -function parseUri(str) { - var o = parseUri.options; - var m = o.parser[o.strictMode ? "strict" : "loose"].exec(str); - var uri = {}; - var i = 14; - - while (i--) { - uri[o.key[i]] = m[i] || ""; - } - - uri[o.q.name] = {}; - uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) { - if ($1) { - uri[o.q.name][$1] = $2; - } - }); - - return uri; -} +var log = _dereq_('debug')('pouchdb:http'); +var isBrowser = typeof process === 'undefined' || process.browser; function encodeDocId(id) { if (/^_(design|local)/.test(id)) { @@ -855,15 +880,12 @@ return utils.Promise.all(Object.keys(doc._attachments).map(function (key) { var attachment = doc._attachments[key]; if (attachment.data && typeof attachment.data !== 'string') { - if (typeof process === undefined || process.browser) { + if (isBrowser) { return new utils.Promise(function (resolve) { - var reader = new FileReader(); - reader.onloadend = function (e) { - attachment.data = utils.btoa( - utils.arrayBufferToBinaryString(e.target.result)); + utils.readAsBinaryString(attachment.data, function (binary) { + attachment.data = utils.btoa(binary); resolve(); - }; - reader.readAsArrayBuffer(attachment.data); + }); }); } else { attachment.data = attachment.data.toString('base64'); @@ -872,29 +894,13 @@ })); } -parseUri.options = { - strictMode: false, - key: ["source", "protocol", "authority", "userInfo", "user", "password", - "host", "port", "relative", "path", "directory", "file", "query", - "anchor"], - q: { - name: "queryKey", - parser: /(?:^|&)([^&=]*)=?([^&]*)/g - }, - parser: { - /* jshint maxlen: false */ - strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, - loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ - } -}; - // Get all the information you possibly can about the URI given by name and // return it as a suitable object. function getHost(name, opts) { // If the given name contains "http:" if (/http(s?):/.test(name)) { // Prase the URI into all its little bits - var uri = parseUri(name); + var uri = utils.parseUri(name); // Store the fact that it is a remote URI uri.remote = true; @@ -958,7 +964,7 @@ return '/' + path; } -// Implements the PouchDBVersion306 API for dealing with CouchDB instances over HTTP +// Implements the PouchDB API for dealing with CouchDB instances over HTTP function HttpPouch(opts, callback) { // The functions that will be publicly available for HttpPouch var api = this; @@ -976,7 +982,9 @@ var ajaxOpts = opts.ajax || {}; opts = utils.clone(opts); function ajax(options, callback) { - return utils.ajax(utils.extend({}, ajaxOpts, options), callback); + var reqOpts = utils.extend({}, ajaxOpts, options); + log(reqOpts.method + ' ' + reqOpts.url); + return utils.ajax(reqOpts, callback); } // Create a new CouchDB database based on the given opts @@ -1014,6 +1022,8 @@ //check if the db exists if (err) { if (err.status === 404) { + utils.explain404( + 'PouchDB is just detecting if the remote DB exists.'); //if it doesn't, create it createDB(); } else { @@ -1203,7 +1213,8 @@ }); // Delete the document given by doc from the database given by host. - api.remove = utils.adapterFun('remove', function (docOrId, optsOrRev, opts, callback) { + api.remove = utils.adapterFun('remove', + function (docOrId, optsOrRev, opts, callback) { var doc; if (typeof optsOrRev === 'string') { // id, rev, opts, callback style @@ -1237,6 +1248,10 @@ }, callback); }); + function encodeAttachmentId(attachmentId) { + return attachmentId.split("/").map(encodeURIComponent).join("/"); + } + // Get the attachment api.getAttachment = utils.adapterFun('getAttachment', function (docId, attachmentId, opts, @@ -1253,18 +1268,21 @@ docId = encodeDocId(docId); } opts.auto_encode = false; - api.get(docId + '/' + attachmentId, opts, callback); + api.get(docId + '/' + encodeAttachmentId(attachmentId), opts, callback); }); // Remove the attachment given by the id and rev api.removeAttachment = utils.adapterFun('removeAttachment', function (docId, attachmentId, rev, callback) { + + var url = genDBUrl(host, encodeDocId(docId) + '/' + + encodeAttachmentId(attachmentId)) + '?rev=' + rev; + ajax({ headers: host.headers, method: 'DELETE', - url: genDBUrl(host, encodeDocId(docId) + '/' + attachmentId) + '?rev=' + - rev + url: url }, callback); }); @@ -1285,12 +1303,28 @@ blob = rev; rev = null; } - var id = encodeDocId(docId) + '/' + attachmentId; + var id = encodeDocId(docId) + '/' + encodeAttachmentId(attachmentId); var url = genDBUrl(host, id); if (rev) { url += '?rev=' + rev; } + if (typeof blob === 'string') { + var binary; + try { + binary = utils.atob(blob); + } catch (err) { + // it's not base64-encoded, so throw error + return callback(utils.extend({}, errors.BAD_ARG, + {reason: "Attachments need to be base64 encoded"})); + } + if (isBrowser) { + blob = utils.createBlob([utils.fixBinary(binary)], {type: type}); + } else { + blob = binary ? new Buffer(binary, 'binary') : ''; + } + } + var opts = { headers: utils.clone(host.headers), method: 'PUT', @@ -1461,6 +1495,11 @@ params.push('include_docs=true'); } + if (opts.attachments) { + // added in CouchDB 1.6.0 + params.push('attachments=true'); + } + if (opts.key) { params.push('key=' + encodeURIComponent(JSON.stringify(opts.key))); } @@ -1502,9 +1541,6 @@ if (typeof opts.keys !== 'undefined') { - var MAX_URL_LENGTH = 2000; - // according to http://stackoverflow.com/a/417184/680742, - // the de factor URL length limit is 2000 characters var keysAsString = 'keys=' + encodeURIComponent(JSON.stringify(opts.keys)); @@ -1567,6 +1603,10 @@ params.include_docs = true; } + if (opts.attachments) { + params.attachments = true; + } + if (opts.continuous) { params.feed = 'longpoll'; } @@ -1598,6 +1638,29 @@ } } + var method = 'GET'; + var body; + + if (opts.doc_ids) { + // set this automagically for the user; it's annoying that couchdb + // requires both a "filter" and a "doc_ids" param. + params.filter = '_doc_ids'; + + var docIdsJson = JSON.stringify(opts.doc_ids); + + if (docIdsJson.length < MAX_URL_LENGTH) { + params.doc_ids = docIdsJson; + } else { + // anything greater than ~2000 is unsafe for gets, so + // use POST instead + method = 'POST'; + body = {doc_ids: opts.doc_ids }; + } + } + + if (opts.continuous && api._useSSE) { + return api.sse(opts, params, returnDocs); + } var xhr; var lastFetchedSeq; @@ -1624,10 +1687,11 @@ // Set the options for the ajax call var xhrOpts = { headers: host.headers, - method: 'GET', + method: method, url: genDBUrl(host, '_changes' + paramStr), // _changes can take a long time to generate, especially when filtered - timeout: opts.timeout + timeout: opts.timeout, + body: body }; lastFetchedSeq = since; @@ -1725,6 +1789,63 @@ }; }; + api.sse = function (opts, params, returnDocs) { + params.feed = 'eventsource'; + params.since = opts.since || 0; + params.limit = opts.limit; + delete params.timeout; + var paramStr = '?' + Object.keys(params).map(function (k) { + return k + '=' + params[k]; + }).join('&'); + var url = genDBUrl(host, '_changes' + paramStr); + var source = new EventSource(url); + var results = { + results: [], + last_seq: false + }; + var dispatched = false; + var open = false; + source.addEventListener('message', msgHandler, false); + source.onopen = function () { + open = true; + }; + source.onerror = errHandler; + return { + cancel: function () { + if (dispatched) { + return dispatched.cancel(); + } + source.removeEventListener('message', msgHandler, false); + source.close(); + } + }; + function msgHandler(e) { + var data = JSON.parse(e.data); + if (returnDocs) { + results.results.push(data); + } + results.last_seq = data.seq; + utils.call(opts.onChange, data); + } + function errHandler(err) { + source.removeEventListener('message', msgHandler, false); + if (open === false) { + // errored before it opened + // likely doesn't support EventSource + api._useSSE = false; + dispatched = api._changes(opts); + return; + } + source.close(); + utils.call(opts.complete, err); + } + + }; + + api._useSSE = false; + // Currently disabled due to failing chrome tests in saucelabs + // api._useSSE = typeof global.EventSource === 'function'; + // Given a set of document/revision IDs (given by req), tets the subset of // those that do NOT correspond to revisions stored in the database. // See http://wiki.apache.org/couchdb/HttpPostRevsDiff @@ -1789,8 +1910,8 @@ module.exports = HttpPouch; -}).call(this,_dereq_("/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js")) -},{"../deps/errors":11,"../utils":23,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":28}],3:[function(_dereq_,module,exports){ +}).call(this,_dereq_('_process'),_dereq_("buffer").Buffer) +},{"../deps/errors":12,"../utils":25,"_process":34,"buffer":29,"debug":35}],3:[function(_dereq_,module,exports){ (function (process,global){ 'use strict'; @@ -1799,18 +1920,46 @@ var errors = _dereq_('../deps/errors'); var vuvuzela = _dereq_('vuvuzela'); +// IndexedDB requires a versioned database structure, so we use the +// version here to manage migrations. +var ADAPTER_VERSION = 4; + +// The object stores created for each database +// DOC_STORE stores the document meta data, its revision history and state +// Keyed by document id +var DOC_STORE = 'document-store'; +// BY_SEQ_STORE stores a particular version of a document, keyed by its +// sequence id +var BY_SEQ_STORE = 'by-sequence'; +// Where we store attachments +var ATTACH_STORE = 'attach-store'; +// Where we store many-to-many relations +// between attachment digests and seqs +var ATTACH_AND_SEQ_STORE = 'attach-seq-store'; + +// Where we store database-wide meta data in a single record +// keyed by id: META_STORE +var META_STORE = 'meta-store'; +// Where we store local documents +var LOCAL_STORE = 'local-store'; +// Where we detect blob support +var DETECT_BLOB_SUPPORT_STORE = 'detect-blob-support'; + var cachedDBs = {}; var taskQueue = { running: false, queue: [] }; +var blobSupportPromise; +var blobSupport = null; + function tryCode(fun, that, args) { try { fun.apply(that, args); } catch (err) { // shouldn't happen - if (window.PouchDBVersion306) { - window.PouchDBVersion306.emit('error', err); + if (window.PouchDB) { + window.PouchDB.emit('error', err); } } } @@ -1836,30 +1985,6 @@ }; } -function isModernIdb() { - // check for outdated implementations of IDB - // that rely on the setVersion method instead of onupgradeneeded (issue #1207) - - // cache based on appVersion, in case the browser is updated - var cacheKey = "_pouch__checkModernIdb_" + - (global.navigator && global.navigator.appVersion); - var cached = utils.hasLocalStorage() && global.localStorage[cacheKey]; - if (cached) { - return JSON.parse(cached); - } - - var dbName = '_pouch__checkModernIdb'; - var result = global.indexedDB.open(dbName, 1).onupgradeneeded === null; - - if (global.indexedDB.deleteDatabase) { - global.indexedDB.deleteDatabase(dbName); // db no longer needed - } - if (utils.hasLocalStorage()) { - global.localStorage[cacheKey] = JSON.stringify(result); // cache - } - return result; -} - // Unfortunately, the metadata has to be stringified // when it is put into the database, because otherwise // IndexedDB can throw errors for deeply-nested objects. @@ -1889,6 +2014,93 @@ return metadata; } +// Read a blob from the database, encoding as necessary +// and translating from base64 if the IDB doesn't support +// native Blobs +function readBlobData(body, type, encode, callback) { + if (encode) { + if (!body) { + callback(''); + } else if (typeof body !== 'string') { // we have blob support + utils.readAsBinaryString(body, function (binary) { + callback(utils.btoa(binary)); + }); + } else { // no blob support + callback(body); + } + } else { + if (!body) { + callback(utils.createBlob([''], {type: type})); + } else if (typeof body !== 'string') { // we have blob support + callback(body); + } else { // no blob support + body = utils.fixBinary(atob(body)); + callback(utils.createBlob([body], {type: type})); + } + } +} + +function fetchAttachmentsIfNecessary(doc, opts, txn, cb) { + var attachments = Object.keys(doc._attachments || {}); + if (!attachments.length) { + return cb && cb(); + } + var numDone = 0; + + function checkDone() { + if (++numDone === attachments.length && cb) { + cb(); + } + } + + function fetchAttachment(doc, att) { + var attObj = doc._attachments[att]; + var digest = attObj.digest; + txn.objectStore(ATTACH_STORE).get(digest).onsuccess = function (e) { + attObj.body = e.target.result.body; + checkDone(); + }; + } + + attachments.forEach(function (att) { + if (opts.attachments && opts.include_docs) { + fetchAttachment(doc, att); + } else { + doc._attachments[att].stub = true; + checkDone(); + } + }); +} + +// IDB-specific postprocessing necessary because +// we don't know whether we stored a true Blob or +// a base64-encoded string, and if it's a Blob it +// needs to be read outside of the transaction context +function postProcessAttachments(results) { + return utils.Promise.all(results.map(function (row) { + if (row.doc && row.doc._attachments) { + var attNames = Object.keys(row.doc._attachments); + return utils.Promise.all(attNames.map(function (att) { + var attObj = row.doc._attachments[att]; + if (!('body' in attObj)) { // already processed + return; + } + var body = attObj.body; + var type = attObj.content_type; + return new utils.Promise(function (resolve) { + readBlobData(body, type, true, function (base64) { + row.doc._attachments[att] = utils.extend( + utils.pick(attObj, ['digest', 'content_type']), + { data: base64 } + ); + resolve(); + }); + }); + })); + } + })); +} + function IdbPouch(opts, callback) { var api = this; @@ -1903,51 +2115,41 @@ function init(api, opts, callback) { - // IndexedDB requires a versioned database structure, so we use the - // version here to manage migrations. - var ADAPTER_VERSION = 3; - - // The object stores created for each database - // DOC_STORE stores the document meta data, its revision history and state - // Keyed by document id - var DOC_STORE = 'document-store'; - // BY_SEQ_STORE stores a particular version of a document, keyed by its - // sequence id - var BY_SEQ_STORE = 'by-sequence'; - // Where we store attachments - var ATTACH_STORE = 'attach-store'; - // Where we store database-wide meta data in a single record - // keyed by id: META_STORE - var META_STORE = 'meta-store'; - // Where we store local documents - var LOCAL_STORE = 'local-store'; - // Where we detect blob support - var DETECT_BLOB_SUPPORT_STORE = 'detect-blob-support'; - var name = opts.name; - var blobSupport = null; var instanceId = null; var idStored = false; var idb = null; var docCount = -1; + // called when creating a fresh new database function createSchema(db) { - db.createObjectStore(DOC_STORE, {keyPath : 'id'}) - .createIndex('seq', 'seq', {unique: true}); + var docStore = db.createObjectStore(DOC_STORE, {keyPath : 'id'}); + docStore.createIndex('seq', 'seq', {unique: true}); db.createObjectStore(BY_SEQ_STORE, {autoIncrement: true}) .createIndex('_doc_id_rev', '_doc_id_rev', {unique: true}); db.createObjectStore(ATTACH_STORE, {keyPath: 'digest'}); db.createObjectStore(META_STORE, {keyPath: 'id', autoIncrement: false}); db.createObjectStore(DETECT_BLOB_SUPPORT_STORE); + + // added in v2 + docStore.createIndex('deletedOrLocal', 'deletedOrLocal', {unique : false}); + + // added in v3 + db.createObjectStore(LOCAL_STORE, {keyPath: '_id'}); + + // added in v4 + var attAndSeqStore = db.createObjectStore(ATTACH_AND_SEQ_STORE, + {autoIncrement: true}); + attAndSeqStore.createIndex('seq', 'seq'); + attAndSeqStore.createIndex('digestSeq', 'digestSeq', {unique: true}); } // migration to version 2 // unfortunately "deletedOrLocal" is a misnomer now that we no longer // store local docs in the main doc-store, but whaddyagonnado - function addDeletedOrLocalIndex(e, callback) { - var transaction = e.currentTarget.transaction; - var docStore = transaction.objectStore(DOC_STORE); + function addDeletedOrLocalIndex(txn, callback) { + var docStore = txn.objectStore(DOC_STORE); docStore.createIndex('deletedOrLocal', 'deletedOrLocal', {unique : false}); docStore.openCursor().onsuccess = function (event) { @@ -1959,7 +2161,7 @@ docStore.put(metadata); cursor["continue"](); } else { - callback(transaction); + callback(); } }; } @@ -1971,11 +2173,10 @@ .createIndex('_doc_id_rev', '_doc_id_rev', {unique: true}); } - function migrateLocalStore(e, tx) { - tx = tx || e.currentTarget.transaction; - var localStore = tx.objectStore(LOCAL_STORE); - var docStore = tx.objectStore(DOC_STORE); - var seqStore = tx.objectStore(BY_SEQ_STORE); + function migrateLocalStore(txn, cb) { + var localStore = txn.objectStore(LOCAL_STORE); + var docStore = txn.objectStore(DOC_STORE); + var seqStore = txn.objectStore(BY_SEQ_STORE); var cursor = docStore.openCursor(); cursor.onsuccess = function (event) { @@ -2012,10 +2213,61 @@ } else { cursor["continue"](); } + } else if (cb) { + cb(); } }; } + // migrations to get to version 4 + function addAttachAndSeqStore(db) { + var attAndSeqStore = db.createObjectStore(ATTACH_AND_SEQ_STORE, + {autoIncrement: true}); + attAndSeqStore.createIndex('seq', 'seq'); + attAndSeqStore.createIndex('digestSeq', 'digestSeq', {unique: true}); + } + + function migrateAttsAndSeqs(txn) { + var seqStore = txn.objectStore(BY_SEQ_STORE); + var attStore = txn.objectStore(ATTACH_STORE); + var attAndSeqStore = txn.objectStore(ATTACH_AND_SEQ_STORE); + + // need to actually populate the table. this is the expensive part, + // so as an optimization, check first that this database even + // contains attachments + var req = attStore.count(); + req.onsuccess = function (e) { + var count = e.target.result; + if (!count) { + return; // done + } + + seqStore.openCursor().onsuccess = function (e) { + var cursor = e.target.result; + if (!cursor) { + return; // done + } + var doc = cursor.value; + var seq = cursor.primaryKey; + var atts = Object.keys(doc._attachments || {}); + var digestMap = {}; + for (var j = 0; j < atts.length; j++) { + var att = doc._attachments[atts[j]]; + digestMap[att.digest] = true; // uniq digests, just in case + } + var digests = Object.keys(digestMap); + for (j = 0; j < digests.length; j++) { + var digest = digests[j]; + attAndSeqStore.put({ + seq: seq, + digestSeq: digest + '::' + seq + }); + } + cursor["continue"](); + }; + }; + } + api.type = function () { return 'idb'; }; @@ -2033,7 +2285,6 @@ return doc; } var newDoc = utils.parseDoc(doc, newEdits); - newDoc._bulk_seq = i; return newDoc; }); @@ -2046,74 +2297,11 @@ var results = new Array(docInfos.length); var fetchedDocs = new utils.Map(); - var updateSeq = 0; - var numDocsWritten = 0; - - function writeMetaData(e) { - var meta = e.target.result; - meta.updateSeq = (meta.updateSeq || 0) + updateSeq; - txn.objectStore(META_STORE).put(meta); - } - - function checkDoneWritingDocs() { - if (++numDocsWritten === docInfos.length) { - txn.objectStore(META_STORE).get(META_STORE).onsuccess = writeMetaData; - } - } + var preconditionErrored = false; function processDocs() { - if (!docInfos.length) { - return; - } - - var idsToDocs = new utils.Map(); - - docInfos.forEach(function (currentDoc, resultsIdx) { - if (currentDoc._id && utils.isLocalId(currentDoc._id)) { - api[currentDoc._deleted ? '_removeLocal' : '_putLocal']( - currentDoc, {ctx: txn}, function (err, resp) { - if (err) { - results[resultsIdx] = err; - } else { - results[resultsIdx] = {}; - } - checkDoneWritingDocs(); - }); - return; - } - - var id = currentDoc.metadata.id; - if (idsToDocs.has(id)) { - idsToDocs.get(id).push([currentDoc, resultsIdx]); - } else { - idsToDocs.set(id, [[currentDoc, resultsIdx]]); - } - }); - - // in the case of new_edits, the user can provide multiple docs - // with the same id. these need to be processed sequentially - idsToDocs.forEach(function (docs, id) { - var numDone = 0; - - function docWritten() { - checkDoneWritingDocs(); - if (++numDone < docs.length) { - nextDoc(); - } - } - function nextDoc() { - var value = docs[numDone]; - var currentDoc = value[0]; - var resultsIdx = value[1]; - - if (fetchedDocs.has(id)) { - updateDoc(fetchedDocs.get(id), currentDoc, resultsIdx, docWritten); - } else { - insertDoc(currentDoc, resultsIdx, docWritten); - } - } - nextDoc(); - }); + utils.processDocs(docInfos, api, fetchedDocs, + txn, results, writeDoc, opts); } function fetchExistingDocs(callback) { @@ -2146,10 +2334,11 @@ } function complete() { + if (preconditionErrored) { + return; + } var aresults = results.map(function (result) { - if (result._bulk_seq) { - delete result._bulk_seq; - } else if (!Object.keys(result).length) { + if (!Object.keys(result).length) { return { ok: true }; @@ -2172,87 +2361,58 @@ callback(null, aresults); } - function preprocessAttachment(att, finish) { - if (att.stub) { - return finish(); - } - if (typeof att.data === 'string') { - var data; - try { - data = atob(att.data); - } catch (e) { - var err = errors.error(errors.BAD_ARG, - "Attachments need to be base64 encoded"); - return callback(err); - } - if (blobSupport) { - var type = att.content_type; - data = utils.fixBinary(data); - att.data = utils.createBlob([data], {type: type}); - } - utils.MD5(data).then(function (result) { - att.digest = 'md5-' + result; - finish(); - }); - return; - } - var reader = new FileReader(); - reader.onloadend = function (e) { - var binary = utils.arrayBufferToBinaryString(this.result || ''); - if (!blobSupport) { - att.data = btoa(binary); - } - utils.MD5(binary).then(function (result) { - att.digest = 'md5-' + result; - finish(); - }); - }; - reader.readAsArrayBuffer(att.data); - } - - function preprocessAttachments(callback) { - if (!docInfos.length) { - return callback(); - } - - var docv = 0; - docInfos.forEach(function (docInfo) { - var attachments = docInfo.data && docInfo.data._attachments ? - Object.keys(docInfo.data._attachments) : []; - - if (!attachments.length) { - return done(); - } - - var recv = 0; - function attachmentProcessed() { - recv++; - if (recv === attachments.length) { - done(); - } - } - - for (var key in docInfo.data._attachments) { - if (docInfo.data._attachments.hasOwnProperty(key)) { - preprocessAttachment(docInfo.data._attachments[key], - attachmentProcessed); - } - } - }); - - function done() { - docv++; - if (docInfos.length === docv) { + function verifyAttachment(digest, callback) { + var req = txn.objectStore([ATTACH_STORE]).get(digest); + req.onsuccess = function (e) { + if (!e.target.result) { + var err = new Error('unknown stub attachment with digest ' + digest); + err.status = 412; + callback(err); + } else { callback(); } - } + }; } - function writeDoc(docInfo, winningRev, deleted, callback, resultsIdx) { + function verifyAttachments(finish) { + var digests = []; + docInfos.forEach(function (docInfo) { + if (docInfo.data && docInfo.data._attachments) { + Object.keys(docInfo.data._attachments).forEach(function (filename) { + var att = docInfo.data._attachments[filename]; + if (att.stub) { + digests.push(att.digest); + } + }); + } + }); + if (!digests.length) { + return finish(); + } + var numDone = 0; + var err; + + function checkDone() { + if (++numDone === digests.length) { + finish(err); + } + } + digests.forEach(function (digest) { + verifyAttachment(digest, function (attErr) { + if (attErr && !err) { + err = attErr; + } + checkDone(); + }); + }); + } + + function writeDoc(docInfo, winningRev, deleted, callback, _up, resultsIdx) { var err = null; var recv = 0; - docInfo.data._id = docInfo.metadata.id; - docInfo.data._rev = docInfo.metadata.rev; + var id = docInfo.data._id = docInfo.metadata.id; + var rev = docInfo.data._rev = docInfo.metadata.rev; + var docIdRev = id + "::" + rev; if (deleted) { docInfo.data._deleted = true; @@ -2282,22 +2442,58 @@ var data = docInfo.data._attachments[key].data; delete docInfo.data._attachments[key].data; var digest = docInfo.data._attachments[key].digest; - saveAttachment(docInfo, digest, data, attachmentSaved); + saveAttachment(digest, data, attachmentSaved); } else { recv++; collectResults(); } } + // map seqs to attachment digests, which + // we will need later during compaction + function insertAttachmentMappings(seq, callback) { + var attsAdded = 0; + var attsToAdd = Object.keys(docInfo.data._attachments || {}); + + if (!attsToAdd.length) { + return callback(); + } + function checkDone() { + if (++attsAdded === attsToAdd.length) { + callback(); + } + } + function add(att) { + var digest = docInfo.data._attachments[att].digest; + var req = txn.objectStore(ATTACH_AND_SEQ_STORE).put({ + seq: seq, + digestSeq: digest + '::' + seq + }); + + req.onsuccess = checkDone; + req.onerror = function (e) { + // this callback is for a constaint error, which we ignore + // because this docid/rev has already been associated with + // the digest (e.g. when new_edits == false) + e.preventDefault(); // avoid transaction abort + e.stopPropagation(); // avoid transaction onerror + checkDone(); + }; + } + for (var i = 0; i < attsToAdd.length; i++) { + add(attsToAdd[i]); // do in parallel + } + } + function finish() { - updateSeq++; - docInfo.data._doc_id_rev = docInfo.data._id + "::" + docInfo.data._rev; + docInfo.data._doc_id_rev = docIdRev; var seqStore = txn.objectStore(BY_SEQ_STORE); var index = seqStore.index('_doc_id_rev'); function afterPut(e) { var metadata = docInfo.metadata; - metadata.seq = e.target.result; + var seq = e.target.result; + metadata.seq = seq; // Current _rev is calculated from _rev_tree on read delete metadata.rev; var metadataToStore = encodeMetadata(metadata, winningRev, deleted); @@ -2307,7 +2503,9 @@ delete metadata.winningRev; results[resultsIdx] = docInfo; fetchedDocs.set(docInfo.metadata.id, docInfo.metadata); - utils.call(callback); + insertAttachmentMappings(seq, function () { + utils.call(callback); + }); }; } @@ -2321,7 +2519,6 @@ var getKeyReq = index.getKey(docInfo.data._doc_id_rev); getKeyReq.onsuccess = function (e) { var putReq = seqStore.put(docInfo.data, e.target.result); - updateSeq--; // discount, since it's an update, not a new seq putReq.onsuccess = afterPut; }; }; @@ -2332,73 +2529,48 @@ } } - function updateDoc(oldDoc, docInfo, resultsIdx, callback) { - var merged = - merge.merge(oldDoc.rev_tree, docInfo.metadata.rev_tree[0], 1000); - var wasPreviouslyDeleted = utils.isDeleted(oldDoc); - var deleted = utils.isDeleted(docInfo.metadata); - var inConflict = (wasPreviouslyDeleted && deleted && newEdits) || - (!wasPreviouslyDeleted && newEdits && merged.conflicts !== 'new_leaf'); - - if (inConflict) { - results[resultsIdx] = makeErr(errors.REV_CONFLICT, docInfo._bulk_seq); - return callback(); - } - - docInfo.metadata.rev_tree = merged.tree; - - // recalculate - var winningRev = merge.winningRev(docInfo.metadata); - deleted = utils.isDeleted(docInfo.metadata, winningRev); - - writeDoc(docInfo, winningRev, deleted, callback, resultsIdx); - } - - function insertDoc(docInfo, resultsIdx, callback) { - var winningRev = merge.winningRev(docInfo.metadata); - var deleted = utils.isDeleted(docInfo.metadata, winningRev); - // Cant insert new deleted documents - if ('was_delete' in opts && deleted) { - results[resultsIdx] = errors.MISSING_DOC; - return callback(); - } - - writeDoc(docInfo, winningRev, deleted, callback, resultsIdx); - } - - // Insert sequence number into the error so we can sort later - function makeErr(err, seq) { - err._bulk_seq = seq; - return err; - } - - function saveAttachment(docInfo, digest, data, callback) { + function saveAttachment(digest, data, callback) { var objectStore = txn.objectStore(ATTACH_STORE); objectStore.get(digest).onsuccess = function (e) { - var originalRefs = e.target.result && e.target.result.refs || {}; - var ref = [docInfo.metadata.id, docInfo.metadata.rev].join('@'); + var exists = e.target.result; + if (exists) { + // don't bother re-putting if it already exists + return utils.call(callback); + } var newAtt = { digest: digest, - body: data, - refs: originalRefs + body: data }; - newAtt.refs[ref] = true; - objectStore.put(newAtt).onsuccess = function (e) { + objectStore.put(newAtt).onsuccess = function () { utils.call(callback); }; }; } var txn; - preprocessAttachments(function () { - var stores = [DOC_STORE, BY_SEQ_STORE, ATTACH_STORE, META_STORE, - LOCAL_STORE]; + var blobType = blobSupport ? 'blob' : 'base64'; + utils.preprocessAttachments(docInfos, blobType, function (err) { + if (err) { + return callback(err); + } + + var stores = [ + DOC_STORE, BY_SEQ_STORE, + ATTACH_STORE, META_STORE, + LOCAL_STORE, ATTACH_AND_SEQ_STORE + ]; txn = idb.transaction(stores, 'readwrite'); txn.onerror = idbError(callback); txn.ontimeout = idbError(callback); txn.oncomplete = complete; - fetchExistingDocs(processDocs); + verifyAttachments(function (err) { + if (err) { + preconditionErrored = true; + return callback(err); + } + fetchExistingDocs(processDocs); + }); }); }; @@ -2469,30 +2641,10 @@ var type = attachment.content_type; txn.objectStore(ATTACH_STORE).get(digest).onsuccess = function (e) { - var data = e.target.result.body; - if (opts.encode) { - if (!data) { - callback(null, ''); - } else if (typeof data !== 'string') { // we have blob support - var reader = new FileReader(); - reader.onloadend = function (e) { - var binary = utils.arrayBufferToBinaryString(this.result || ''); - callback(null, btoa(binary)); - }; - reader.readAsArrayBuffer(data); - } else { // no blob support - callback(null, data); - } - } else { - if (!data) { - callback(null, utils.createBlob([''], {type: type})); - } else if (typeof data !== 'string') { // we have blob support - callback(null, data); - } else { // no blob support - data = utils.fixBinary(atob(data)); - callback(null, utils.createBlob([data], {type: type})); - } - } + var body = e.target.result.body; + readBlobData(body, type, opts.encode, function (blobData) { + callback(null, blobData); + }); }; }; @@ -2546,13 +2698,26 @@ } } - var transaction = idb.transaction([DOC_STORE, BY_SEQ_STORE], 'readonly'); - transaction.oncomplete = function () { + var stores = [DOC_STORE, BY_SEQ_STORE]; + if (opts.attachments) { + stores.push(ATTACH_STORE); + } + var transaction = idb.transaction(stores, 'readonly'); + + function onResultsReady() { callback(null, { total_rows: totalRows, offset: opts.skip, rows: results }); + } + + transaction.oncomplete = function () { + if (opts.attachments) { + postProcessAttachments(results).then(onResultsReady); + } else { + onResultsReady(); + } }; var oStore = transaction.objectStore(DOC_STORE); @@ -2585,11 +2750,7 @@ if (opts.conflicts) { doc.doc._conflicts = merge.collectConflicts(metadata); } - for (var att in doc.doc._attachments) { - if (doc.doc._attachments.hasOwnProperty(att)) { - doc.doc._attachments[att].stub = true; - } - } + fetchAttachmentsIfNecessary(doc.doc, opts, transaction); } var deleted = utils.isDeleted(metadata, winningRev); if (opts.deleted === 'ok') { @@ -2675,10 +2836,15 @@ return callback(error); } var updateSeq = 0; - var txn = idb.transaction([META_STORE], 'readonly'); - - txn.objectStore(META_STORE).get(META_STORE).onsuccess = function (e) { - updateSeq = e.target.result && e.target.result.updateSeq || 0; + var txn = idb.transaction([BY_SEQ_STORE], 'readonly'); + txn.objectStore(BY_SEQ_STORE).openCursor(null, "prev").onsuccess = + function (event) { + var cursor = event.target.result; + if (cursor) { + updateSeq = cursor.key; + } else { + updateSeq = 0; + } }; txn.oncomplete = function () { @@ -2704,6 +2870,7 @@ }; } + var docIds = opts.doc_ids && new utils.Set(opts.doc_ids); var descending = opts.descending ? 'prev' : null; var lastSeq = 0; @@ -2728,7 +2895,12 @@ var txn; function fetchChanges() { - txn = idb.transaction([DOC_STORE, BY_SEQ_STORE], 'readonly'); + var objectStores = [DOC_STORE, BY_SEQ_STORE]; + if (opts.attachments) { + objectStores.push(ATTACH_STORE); + } + txn = idb.transaction(objectStores, 'readonly'); + txn.onerror = idbError(opts.complete); txn.oncomplete = onTxnComplete; var req; @@ -2757,7 +2929,7 @@ var doc = cursor.value; - if (opts.doc_ids && opts.doc_ids.indexOf(doc._id) === -1) { + if (docIds && !docIds.has(doc._id)) { return cursor["continue"](); } @@ -2783,7 +2955,17 @@ if (returnDocs) { results.push(change); } - opts.onChange(change); + // process the attachment immediately + // for the benefit of live listeners + if (opts.attachments && opts.include_docs) { + fetchAttachmentsIfNecessary(doc, opts, txn, function () { + postProcessAttachments([change]).then(function () { + opts.onChange(change); + }); + }); + } else { + opts.onChange(change); + } } if (numResults !== limit) { cursor["continue"](); @@ -2792,12 +2974,24 @@ } function onTxnComplete() { - if (!opts.continuous) { + + function finish() { opts.complete(null, { results: results, last_seq: lastSeq }); } + + + if (!opts.continuous) { + if (opts.attachments) { + // cannot guarantee that postProcessing was already done, + // so do it again + postProcessAttachments(results).then(finish); + } else { + finish(); + } + } } }; @@ -2830,39 +3024,89 @@ // This function removes revisions of document docId // which are listed in revs and sets this document // revision to to rev_tree - api._doCompaction = function (docId, rev_tree, revs, callback) { - var txn = idb.transaction([DOC_STORE, BY_SEQ_STORE], 'readwrite'); + api._doCompaction = function (docId, revs, callback) { + var txn = idb.transaction([ + DOC_STORE, + BY_SEQ_STORE, + ATTACH_STORE, + ATTACH_AND_SEQ_STORE + ], 'readwrite'); - var index = txn.objectStore(DOC_STORE); - index.get(docId).onsuccess = function (event) { - var metadata = decodeMetadata(event.target.result); - metadata.rev_tree = rev_tree; + var docStore = txn.objectStore(DOC_STORE); + var seqStore = txn.objectStore(BY_SEQ_STORE); + var attStore = txn.objectStore(ATTACH_STORE); + var attAndSeqStore = txn.objectStore(ATTACH_AND_SEQ_STORE); - var count = revs.length; - revs.forEach(function (rev) { - var index = txn.objectStore(BY_SEQ_STORE).index('_doc_id_rev'); - var key = docId + "::" + rev; - index.getKey(key).onsuccess = function (e) { - var seq = e.target.result; - if (!seq) { - return; - } - txn.objectStore(BY_SEQ_STORE)["delete"](seq); + var possiblyOrphanedDigests = []; - count--; + function deleteOrphanedAttachments() { + if (!possiblyOrphanedDigests.length) { + return; + } + possiblyOrphanedDigests.forEach(function (digest) { + var countReq = attAndSeqStore.index('digestSeq').count( + global.IDBKeyRange.bound( + digest + '::', digest + '::\uffff', false, false)); + countReq.onsuccess = function (e) { + var count = e.target.result; if (!count) { - // winningRev is not guaranteed to be there, since it's - // not formally migrated. deletedOrLocal is a - // now-unfortunate name that really just means "deleted" - var winningRev = metadata.winningRev || - merge.winningRev(metadata); - var deleted = metadata.deletedOrLocal; - txn.objectStore(DOC_STORE).put( - encodeMetadata(metadata, winningRev, deleted)); + // orphaned + attStore["delete"](digest); } }; }); + } + + docStore.get(docId).onsuccess = function (event) { + var metadata = decodeMetadata(event.target.result); + merge.traverseRevTree(metadata.rev_tree, function (isLeaf, pos, + revHash, ctx, opts) { + var rev = pos + '-' + revHash; + if (revs.indexOf(rev) !== -1) { + opts.status = 'missing'; + } + }); + + var count = revs.length; + revs.forEach(function (rev) { + var index = seqStore.index('_doc_id_rev'); + var key = docId + "::" + rev; + index.getKey(key).onsuccess = function (e) { + var seq = e.target.result; + if (typeof seq !== 'number') { + return; + } + seqStore["delete"](seq); + + var cursor = attAndSeqStore.index('seq') + .openCursor(global.IDBKeyRange.only(seq)); + + cursor.onsuccess = function (event) { + var cursor = event.target.result; + if (cursor) { + var digest = cursor.value.digestSeq.split('::')[0]; + possiblyOrphanedDigests.push(digest); + attAndSeqStore["delete"](cursor.primaryKey); + cursor["continue"](); + } else { // done + count--; + if (!count) { // done processing all revs + // winningRev is not guaranteed to be there, since it's + // not formally migrated. deletedOrLocal is a + // now-unfortunate name that really just means "deleted" + var winningRev = metadata.winningRev || + merge.winningRev(metadata); + var deleted = metadata.deletedOrLocal; + txn.objectStore(DOC_STORE).put( + encodeMetadata(metadata, winningRev, deleted)); + deleteOrphanedAttachments(); + } + } + }; + }; + }); }; + txn.onerror = idbError(callback); txn.oncomplete = function () { utils.call(callback); }; @@ -2879,7 +3123,7 @@ if (!doc) { callback(errors.MISSING_DOC); } else { - delete doc['_doc_id_rev']; + delete doc['_doc_id_rev']; // for backwards compat callback(null, doc); } }; @@ -2898,7 +3142,6 @@ } else { doc._rev = '0-' + (parseInt(oldRev.split('-')[1], 10) + 1); } - doc._doc_id_rev = id + '::' + doc._rev; var tx = opts.ctx; var ret; @@ -2915,28 +3158,12 @@ var oStore = tx.objectStore(LOCAL_STORE); var req; if (oldRev) { - var index = oStore.index('_doc_id_rev'); - var docIdRev = id + '::' + oldRev; - req = index.get(docIdRev); - req.onsuccess = function (e) { - if (!e.target.result) { - callback(errors.REV_CONFLICT); - } else { // update - var req = oStore.put(doc); - req.onsuccess = function () { - ret = {ok: true, id: doc._id, rev: doc._rev}; - if (opts.ctx) { // retuthis.immediately - callback(null, ret); - } - }; - } - }; - } else { // new doc req = oStore.get(id); req.onsuccess = function (e) { - if (e.target.result) { // already exists + var oldDoc = e.target.result; + if (!oldDoc || oldDoc._rev !== oldRev) { callback(errors.REV_CONFLICT); - } else { // insert + } else { // update var req = oStore.put(doc); req.onsuccess = function () { ret = {ok: true, id: doc._id, rev: doc._rev}; @@ -2946,6 +3173,20 @@ }; } }; + } else { // new doc + req = oStore.add(doc); + req.onerror = function (e) { + // constraint error, already exists + callback(errors.REV_CONFLICT); + e.preventDefault(); // avoid transaction abort + e.stopPropagation(); // avoid transaction onerror + }; + req.onsuccess = function (e) { + ret = {ok: true, id: doc._id, rev: doc._rev}; + if (opts.ctx) { // return immediately + callback(null, ret); + } + }; } }; @@ -2957,23 +3198,18 @@ callback(null, ret); } }; - var docIdRev = doc._id + '::' + doc._rev; + var id = doc._id; var oStore = tx.objectStore(LOCAL_STORE); - var index = oStore.index('_doc_id_rev'); - var req = index.get(docIdRev); + var req = oStore.get(id); req.onerror = idbError(callback); req.onsuccess = function (e) { - var doc = e.target.result; - if (!doc) { + var oldDoc = e.target.result; + if (!oldDoc || oldDoc._rev !== doc._rev) { callback(errors.MISSING_DOC); } else { - var req = index.getKey(docIdRev); - req.onsuccess = function (e) { - var key = e.target.result; - oStore["delete"](key); - ret = {ok: true, id: doc._id, rev: '0-0'}; - }; + oStore["delete"](id); + ret = {ok: true, id: id, rev: '0-0'}; } }; }; @@ -2982,7 +3218,6 @@ if (cached) { idb = cached.idb; - blobSupport = cached.blobSupport; instanceId = cached.instanceId; idStored = cached.idStored; process.nextTick(function () { @@ -3001,18 +3236,28 @@ req.onupgradeneeded = function (e) { var db = e.target.result; if (e.oldVersion < 1) { - // initial schema - createSchema(db); + createSchema(db); // new db, initial schema + return; } - if (e.oldVersion < 3) { - createLocalStoreSchema(db); - if (e.oldVersion < 2) { - // version 2 adds the deletedOrLocal index - addDeletedOrLocalIndex(e, function (transaction) { - migrateLocalStore(e, transaction); - }); + // promises would be great here, IndexedDB. >_< + var txn = e.currentTarget.transaction; + if (e.oldVersion < 4) { + addAttachAndSeqStore(db); // v4 + if (e.oldVersion < 3) { + createLocalStoreSchema(db); // v3 + if (e.oldVersion < 2) { + addDeletedOrLocalIndex(txn, function () { // v2 + migrateLocalStore(txn, function () { // v3 + migrateAttsAndSeqs(txn); // v4 + }); + }); + } else { + migrateLocalStore(txn, function () { // v3 + migrateAttsAndSeqs(txn); // v4 + }); + } } else { - migrateLocalStore(e); + migrateAttsAndSeqs(txn); // v4 } } }; @@ -3043,7 +3288,6 @@ } else { cachedDBs[name] = { idb: idb, - blobSupport: blobSupport, instanceId: instanceId, idStored: idStored, loaded: true @@ -3069,39 +3313,54 @@ // Detect blob support. Chrome didn't support it until version 38. // in version 37 they had a broken version where PNGs (and possibly // other binary types) aren't stored correctly. - try { - var blob = utils.createBlob([''], {type: 'image/png'}); - txn.objectStore(DETECT_BLOB_SUPPORT_STORE).put(blob, 'key'); - txn.oncomplete = function () { - // have to do it in a separate transaction, else the correct - // content type is always returned - txn = idb.transaction([META_STORE, DETECT_BLOB_SUPPORT_STORE], - 'readwrite'); - var getBlobReq = txn.objectStore( - DETECT_BLOB_SUPPORT_STORE).get('key'); - getBlobReq.onsuccess = function (e) { - var storedBlob = e.target.result; - var url = URL.createObjectURL(storedBlob); - utils.ajax({ - url: url, - cache: true, - binary: true - }, function (err, res) { - if (err && err.status === 405) { - // firefox won't let us do that. but firefox doesn't - // have the blob type bug that Chrome does, so that's ok - blobSupport = true; - } else { - blobSupport = !!(res && res.type === 'image/png'); - } - checkSetupComplete(); - }); + if (!blobSupportPromise) { + + // make sure blob support is only checked one + blobSupportPromise = new utils.Promise(function (resolve) { + var blob = utils.createBlob([''], {type: 'image/png'}); + txn.objectStore(DETECT_BLOB_SUPPORT_STORE).put(blob, 'key'); + txn.oncomplete = function () { + // have to do it in a separate transaction, else the correct + // content type is always returned + txn = idb.transaction([META_STORE, DETECT_BLOB_SUPPORT_STORE], + 'readwrite'); + var getBlobReq = txn.objectStore( + DETECT_BLOB_SUPPORT_STORE).get('key'); + getBlobReq.onsuccess = function (e) { + + var storedBlob = e.target.result; + var url = URL.createObjectURL(storedBlob); + + utils.ajax({ + url: url, + cache: true, + binary: true + }, function (err, res) { + if (err && err.status === 405) { + // firefox won't let us do that. but firefox doesn't + // have the blob type bug that Chrome does, so that's ok + resolve(true); + } else { + resolve(!!(res && res.type === 'image/png')); + if (err && err.status === 404) { + utils.explain404( + 'PouchDB is just detecting blob URL support.'); + } + } + URL.revokeObjectURL(url); + }); + }; }; - }; - } catch (err) { - blobSupport = false; - checkSetupComplete(); + })["catch"](function (err) { + blobSupport = false; + checkSetupComplete(); + }); } + + blobSupportPromise.then(function (val) { + blobSupport = val; + checkSetupComplete(); + }); }; }; @@ -3116,7 +3375,10 @@ var isSafari = typeof openDatabase !== 'undefined' && /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent); - return !isSafari && global.indexedDB && isModernIdb(); + + // some outdated implementations of IDB that appear on Samsung + // and HTC Android devices <4.4 are missing IDBKeyRange + return !isSafari && global.indexedDB && global.IDBKeyRange; }; function destroy(name, opts, callback) { @@ -3160,8 +3422,8 @@ module.exports = IdbPouch; -}).call(this,_dereq_("/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../deps/errors":11,"../merge":18,"../utils":23,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":28,"vuvuzela":58}],4:[function(_dereq_,module,exports){ +}).call(this,_dereq_('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"../deps/errors":12,"../merge":20,"../utils":25,"_process":34,"vuvuzela":67}],4:[function(_dereq_,module,exports){ module.exports = ['idb', 'websql']; },{}],5:[function(_dereq_,module,exports){ (function (global){ @@ -3171,10 +3433,65 @@ var merge = _dereq_('../merge'); var errors = _dereq_('../deps/errors'); var vuvuzela = _dereq_('vuvuzela'); +var parseHexString = _dereq_('../deps/parse-hex'); + function quote(str) { return "'" + str + "'"; } +// escapeBlob and unescapeBlob are workarounds for a websql bug: +// https://code.google.com/p/chromium/issues/detail?id=422690 +// https://bugs.webkit.org/show_bug.cgi?id=137637 +// The goal is to never actually insert the \u0000 character +// in the database. +function escapeBlob(str) { + return str + .replace(/\u0002/g, '\u0002\u0002') + .replace(/\u0001/g, '\u0001\u0002') + .replace(/\u0000/g, '\u0001\u0001'); +} + +function unescapeBlob(str) { + return str + .replace(/\u0001\u0001/g, '\u0000') + .replace(/\u0001\u0002/g, '\u0001') + .replace(/\u0002\u0002/g, '\u0002'); +} +function fetchAttachmentsIfNecessary(doc, opts, api, txn, cb) { + var attachments = Object.keys(doc._attachments || {}); + if (!attachments.length) { + return cb && cb(); + } + var numDone = 0; + + function checkDone() { + if (++numDone === attachments.length && cb) { + cb(); + } + } + + function fetchAttachment(doc, att) { + var attObj = doc._attachments[att]; + var attOpts = {encode: true, ctx: txn}; + api._getAttachment(attObj, attOpts, function (_, base64) { + doc._attachments[att] = utils.extend( + utils.pick(attObj, ['digest', 'content_type']), + { data: base64 } + ); + checkDone(); + }); + } + + attachments.forEach(function (att) { + if (opts.attachments && opts.include_docs) { + fetchAttachment(doc, att); + } else { + doc._attachments[att].stub = true; + checkDone(); + } + }); +} + var cachedDatabases = {}; var openDB = utils.getArguments(function (args) { @@ -3198,7 +3515,7 @@ }); var POUCH_VERSION = 1; -var ADAPTER_VERSION = 4; // used to manage migrations +var ADAPTER_VERSION = 6; // used to manage migrations // The object stores created for each database // DOC_STORE stores the document meta data, its revision history and state @@ -3210,6 +3527,9 @@ var ATTACH_STORE = quote('attach-store'); var LOCAL_STORE = quote('local-store'); var META_STORE = quote('metadata-store'); +// where we store many-to-many relations between attachment +// digests and seqs +var ATTACH_AND_SEQ_STORE = quote('attach-seq-store'); // these indexes cover the ground for most allDocs queries var BY_SEQ_STORE_DELETED_INDEX_SQL = @@ -3221,6 +3541,12 @@ var DOC_STORE_WINNINGSEQ_INDEX_SQL = 'CREATE INDEX IF NOT EXISTS \'doc-winningseq-idx\' ON ' + DOC_STORE + ' (winningseq)'; +var ATTACH_AND_SEQ_STORE_SEQ_INDEX_SQL = + 'CREATE INDEX IF NOT EXISTS \'attach-seq-seq-idx\' ON ' + + ATTACH_AND_SEQ_STORE + ' (seq)'; +var ATTACH_AND_SEQ_STORE_ATTACH_INDEX_SQL = + 'CREATE UNIQUE INDEX IF NOT EXISTS \'attach-seq-digest-idx\' ON ' + + ATTACH_AND_SEQ_STORE + ' (digest, seq)'; var DOC_STORE_AND_BY_SEQ_JOINER = BY_SEQ_STORE + '.seq = ' + DOC_STORE + '.winningseq'; @@ -3250,22 +3576,6 @@ callback(errors.error(errors.WSQ_ERROR, errorReason, errorName)); }; } -function decodeUtf8(str) { - return decodeURIComponent(window.escape(str)); -} -function parseHexString(str, encoding) { - var result = ''; - var charWidth = encoding === 'UTF-8' ? 2 : 4; - for (var i = 0, len = str.length; i < len; i += charWidth) { - var substring = str.substring(i, i + charWidth); - if (charWidth === 4) { // UTF-16, twiddle the bits - substring = substring.substring(2, 4) + substring.substring(0, 2); - } - result += String.fromCharCode(parseInt(substring, 16)); - } - result = encoding === 'UTF-8' ? decodeUtf8(result) : result; - return result; -} function stringifyDoc(doc) { // don't bother storing the id/rev. it uses lots of space, @@ -3295,7 +3605,7 @@ // honest-to-god ceiling for data, so we need to // set it to a decently high number. var isAndroid = /Android/.test(window.navigator.userAgent); - return isAndroid ? 5000000 : 1; + return isAndroid ? 5000000 : 1; // in PhantomJS, if you use 0 it will crash } function WebSqlPouch(opts, callback) { @@ -3391,7 +3701,7 @@ } function doNext() { if (!rows.length) { - return callback(); + return callback(tx); } var row = rows.shift(); var rev = JSON.parse(row.data)._rev; @@ -3415,10 +3725,10 @@ // in this migration, we remove doc_id_rev and just use rev function runMigration4(tx, callback) { - function updateRows(rows, encoding) { + function updateRows(rows) { function doNext() { if (!rows.length) { - return callback(); + return callback(tx); } var row = rows.shift(); var doc_id_rev = parseHexString(row.hex, encoding); @@ -3445,40 +3755,122 @@ for (var i = 0; i < res.rows.length; i++) { rows.push(res.rows.item(i)); } - // it sucks, but we fetch the encoding twice - tx.executeSql( - 'SELECT dbid, hex(dbid) AS hexId FROM ' + META_STORE, [], - function (tx, result) { - var id = result.rows.item(0).dbid; - var hexId = result.rows.item(0).hexId; - var encoding = (hexId.length === id.length * 2) ? - 'UTF-8' : 'UTF-16'; - updateRows(rows, encoding); - } - ); + updateRows(rows); }); }); }); }); } - function onGetInstanceId(tx) { + // in this migration, we add the attach_and_seq table + // for issue #2818 + function runMigration5(tx, callback) { + + function migrateAttsAndSeqs(tx) { + // need to actually populate the table. this is the expensive part, + // so as an optimization, check first that this database even + // contains attachments + var sql = 'SELECT COUNT(*) AS cnt FROM ' + ATTACH_STORE; + tx.executeSql(sql, [], function (tx, res) { + var count = res.rows.item(0).cnt; + if (!count) { + return callback(tx); + } + + var offset = 0; + var pageSize = 10; + function nextPage() { + var sql = select( + SELECT_DOCS + ', ' + DOC_STORE + '.id AS id', + [DOC_STORE, BY_SEQ_STORE], + DOC_STORE_AND_BY_SEQ_JOINER, + null, + DOC_STORE + '.id ' + ); + sql += ' LIMIT ' + pageSize + ' OFFSET ' + offset; + offset += pageSize; + tx.executeSql(sql, [], function (tx, res) { + if (!res.rows.length) { + return callback(tx); + } + var digestSeqs = {}; + function addDigestSeq(digest, seq) { + // uniq digest/seq pairs, just in case there are dups + var seqs = digestSeqs[digest] = (digestSeqs[digest] || []); + if (seqs.indexOf(seq) === -1) { + seqs.push(seq); + } + } + for (var i = 0; i < res.rows.length; i++) { + var row = res.rows.item(i); + var doc = unstringifyDoc(row.data, row.id, row.rev); + var atts = Object.keys(doc._attachments || {}); + for (var j = 0; j < atts.length; j++) { + var att = doc._attachments[atts[j]]; + addDigestSeq(att.digest, row.seq); + } + } + var digestSeqPairs = []; + Object.keys(digestSeqs).forEach(function (digest) { + var seqs = digestSeqs[digest]; + seqs.forEach(function (seq) { + digestSeqPairs.push([digest, seq]); + }); + }); + if (!digestSeqPairs.length) { + return nextPage(); + } + var numDone = 0; + digestSeqPairs.forEach(function (pair) { + var sql = 'INSERT INTO ' + ATTACH_AND_SEQ_STORE + + ' (digest, seq) VALUES (?,?)'; + tx.executeSql(sql, pair, function () { + if (++numDone === digestSeqPairs.length) { + nextPage(); + } + }); + }); + }); + } + nextPage(); + }); + } + + var attachAndRev = 'CREATE TABLE IF NOT EXISTS ' + + ATTACH_AND_SEQ_STORE + ' (digest, seq INTEGER)'; + tx.executeSql(attachAndRev, [], function (tx) { + tx.executeSql( + ATTACH_AND_SEQ_STORE_ATTACH_INDEX_SQL, [], function (tx) { + tx.executeSql( + ATTACH_AND_SEQ_STORE_SEQ_INDEX_SQL, [], + migrateAttsAndSeqs); + }); + }); + } + + // in this migration, we use escapeBlob() and unescapeBlob() + // instead of reading out the binary as HEX, which is slow + function runMigration6(tx, callback) { + var sql = 'ALTER TABLE ' + ATTACH_STORE + + ' ADD COLUMN escaped TINYINT(1) DEFAULT 0'; + tx.executeSql(sql, [], callback); + } + + function checkEncoding(tx, cb) { + // UTF-8 on chrome/android, UTF-16 on safari < 7.1 + tx.executeSql('SELECT HEX("a") AS hex', [], function (tx, res) { + var hex = res.rows.item(0).hex; + encoding = hex.length === 2 ? 'UTF-8' : 'UTF-16'; + cb(); + } + ); + } + + function onGetInstanceId() { while (idRequests.length > 0) { var idCallback = idRequests.pop(); idCallback(null, instanceId); } - checkDbEncoding(tx); - } - - function checkDbEncoding(tx) { - // check db encoding - utf-8 (chrome, opera) or utf-16 (safari)? - tx.executeSql('SELECT dbid, hex(dbid) AS hexId FROM ' + META_STORE, [], - function (tx, result) { - var id = result.rows.item(0).dbid; - var hexId = result.rows.item(0).hexId; - encoding = (hexId.length === id.length * 2) ? 'UTF-8' : 'UTF-16'; - } - ); } function onGetVersion(tx, dbVersion) { @@ -3486,9 +3878,11 @@ // initial schema var meta = 'CREATE TABLE IF NOT EXISTS ' + META_STORE + - ' (update_seq INTEGER, dbid, db_version INTEGER)'; + ' (dbid, db_version INTEGER)'; var attach = 'CREATE TABLE IF NOT EXISTS ' + ATTACH_STORE + - ' (digest, json, body BLOB)'; + ' (digest UNIQUE, escaped TINYINT(1), body BLOB)'; + var attachAndRev = 'CREATE TABLE IF NOT EXISTS ' + + ATTACH_AND_SEQ_STORE + ' (digest, seq INTEGER)'; var doc = 'CREATE TABLE IF NOT EXISTS ' + DOC_STORE + ' (id unique, json, winningseq)'; var seq = 'CREATE TABLE IF NOT EXISTS ' + BY_SEQ_STORE + @@ -3500,19 +3894,23 @@ // creates tx.executeSql(attach); tx.executeSql(local); + tx.executeSql(attachAndRev, [], function () { + tx.executeSql(ATTACH_AND_SEQ_STORE_SEQ_INDEX_SQL); + tx.executeSql(ATTACH_AND_SEQ_STORE_ATTACH_INDEX_SQL); + }); tx.executeSql(doc, [], function () { tx.executeSql(DOC_STORE_WINNINGSEQ_INDEX_SQL); tx.executeSql(seq, [], function () { tx.executeSql(BY_SEQ_STORE_DELETED_INDEX_SQL); tx.executeSql(BY_SEQ_STORE_DOC_ID_REV_INDEX_SQL); tx.executeSql(meta, [], function () { - // mark the update_seq, db version, and new dbid + // mark the db version, and new dbid var initSeq = 'INSERT INTO ' + META_STORE + - ' (update_seq, db_version, dbid) VALUES (?, ?, ?)'; + ' (db_version, dbid) VALUES (?,?)'; instanceId = utils.uuid(); - var initSeqArgs = [0, ADAPTER_VERSION, instanceId]; + var initSeqArgs = [ADAPTER_VERSION, instanceId]; tx.executeSql(initSeq, initSeqArgs, function (tx) { - onGetInstanceId(tx); + onGetInstanceId(); }); }); }); @@ -3530,63 +3928,65 @@ var sql = 'SELECT dbid FROM ' + META_STORE; tx.executeSql(sql, [], function (tx, result) { instanceId = result.rows.item(0).dbid; - onGetInstanceId(tx); + onGetInstanceId(); }); }; // would love to use promises here, but then websql // ends the transaction early - switch (dbVersion) { - case 1: - runMigration2(tx, function () { - runMigration3(tx, function () { - runMigration4(tx, setupDone); - }); - }); - break; - case 2: - runMigration3(tx, function () { - runMigration4(tx, setupDone); - }); - break; - case 3: - runMigration4(tx, setupDone); - break; - default: - setupDone(); - break; - } + var tasks = [ + runMigration2, + runMigration3, + runMigration4, + runMigration5, + runMigration6, + setupDone + ]; + + // run each migration sequentially + var i = dbVersion; + var nextMigration = function (tx) { + tasks[i - 1](tx, nextMigration); + i++; + }; + nextMigration(tx); } } function setup() { - db.transaction(function (tx) { - // first get the version - tx.executeSql('SELECT sql FROM sqlite_master WHERE tbl_name = ' + - META_STORE, [], function (tx, result) { - if (!result.rows.length) { - // database hasn't even been created yet (version 0) - onGetVersion(tx, 0); - } else if (!/db_version/.test(result.rows.item(0).sql)) { - // table was created, but without the new db_version column, - // so add it. - tx.executeSql('ALTER TABLE ' + META_STORE + - ' ADD COLUMN db_version INTEGER', [], function () { - // before version 2, this column didn't even exist - onGetVersion(tx, 1); - }); - } else { // column exists, we can safely get it - tx.executeSql('SELECT db_version FROM ' + META_STORE, [], - function (tx, result) { - var dbVersion = result.rows.item(0).db_version; - onGetVersion(tx, dbVersion); - }); - } + // first check the encoding + checkEncoding(tx, function () { + // then get the version + fetchVersion(tx); }); }, unknownError(callback), dbCreated); } + function fetchVersion(tx) { + var sql = 'SELECT sql FROM sqlite_master WHERE tbl_name = ' + META_STORE; + tx.executeSql(sql, [], function (tx, result) { + if (!result.rows.length) { + // database hasn't even been created yet (version 0) + onGetVersion(tx, 0); + } else if (!/db_version/.test(result.rows.item(0).sql)) { + // table was created, but without the new db_version column, + // so add it. + tx.executeSql('ALTER TABLE ' + META_STORE + + ' ADD COLUMN db_version INTEGER', [], function () { + // before version 2, this column didn't even exist + onGetVersion(tx, 1); + }); + } else { // column exists, we can safely get it + tx.executeSql('SELECT db_version FROM ' + META_STORE, + [], function (tx, result) { + var dbVersion = result.rows.item(0).db_version; + onGetVersion(tx, dbVersion); + }); + } + }); + } + if (utils.isCordova() && typeof global !== 'undefined') { //to wait until custom api is made in pouch.adapters before doing setup global.addEventListener(name + '_pouch', function cordova_init() { @@ -3608,9 +4008,9 @@ api._info = function (callback) { db.readTransaction(function (tx) { countDocs(tx, function (docCount) { - var sql = 'SELECT update_seq FROM ' + META_STORE; - tx.executeSql(sql, [], function (tx, result) { - var updateSeq = result.rows.item(0).update_seq; + var sql = 'SELECT MAX(seq) AS seq FROM ' + BY_SEQ_STORE; + tx.executeSql(sql, [], function (tx, res) { + var updateSeq = res.rows.item(0).seq || 0; callback(null, { doc_count: docCount, update_seq: updateSeq @@ -3631,7 +4031,6 @@ return doc; } var newDoc = utils.parseDoc(doc, newEdits); - newDoc._bulk_seq = i; return newDoc; }); @@ -3644,15 +4043,15 @@ var tx; var results = new Array(docInfos.length); - var updateSeq = 0; var fetchedDocs = new utils.Map(); - var numDocsWritten = 0; + var preconditionErrored; function complete() { + if (preconditionErrored) { + return callback(preconditionErrored); + } var aresults = results.map(function (result) { - if (result._bulk_seq) { - delete result._bulk_seq; - } else if (!Object.keys(result).length) { + if (!Object.keys(result).length) { return { ok: true }; @@ -3671,88 +4070,62 @@ }; }); WebSqlPouch.Changes.notify(name); - - var updateseq = 'SELECT update_seq FROM ' + META_STORE; - tx.executeSql(updateseq, [], function (tx, result) { - var update_seq = result.rows.item(0).update_seq + updateSeq; - var sql = 'UPDATE ' + META_STORE + ' SET update_seq=?'; - tx.executeSql(sql, [update_seq], function () { - callback(null, aresults); - }); - }); + docCount = -1; // invalidate + callback(null, aresults); } - function preprocessAttachment(att, finish) { - if (att.stub) { - return finish(); - } - if (typeof att.data === 'string') { - try { - att.data = atob(att.data); - } catch (e) { - var err = errors.error(errors.BAD_ARG, - "Attachments need to be base64 encoded"); - return callback(err); - } - var data = utils.fixBinary(att.data); - att.data = utils.createBlob([data], {type: att.content_type}); - } - var reader = new FileReader(); - reader.onloadend = function (e) { - var binary = utils.arrayBufferToBinaryString(this.result); - att.data = binary; - utils.MD5(binary).then(function (result) { - att.digest = 'md5-' + result; - finish(); - }); - }; - reader.readAsArrayBuffer(att.data); - } - - function preprocessAttachments(callback) { - if (!docInfos.length) { - return callback(); - } - - var docv = 0; - - docInfos.forEach(function (docInfo) { - var attachments = docInfo.data && docInfo.data._attachments ? - Object.keys(docInfo.data._attachments) : []; - var recv = 0; - - if (!attachments.length) { - return done(); - } - - function processedAttachment() { - recv++; - if (recv === attachments.length) { - done(); - } - } - - for (var key in docInfo.data._attachments) { - if (docInfo.data._attachments.hasOwnProperty(key)) { - preprocessAttachment(docInfo.data._attachments[key], - processedAttachment); - } - } - }); - - function done() { - docv++; - if (docInfos.length === docv) { + function verifyAttachment(digest, callback) { + var sql = 'SELECT count(*) as cnt FROM ' + ATTACH_STORE + + ' WHERE digest=?'; + tx.executeSql(sql, [digest], function (tx, result) { + if (result.rows.item(0).cnt === 0) { + var err = new Error('unknown stub attachment with digest ' + digest); + err.status = 412; + callback(err); + } else { callback(); } - } + }); } + function verifyAttachments(finish) { + var digests = []; + docInfos.forEach(function (docInfo) { + if (docInfo.data && docInfo.data._attachments) { + Object.keys(docInfo.data._attachments).forEach(function (filename) { + var att = docInfo.data._attachments[filename]; + if (att.stub) { + digests.push(att.digest); + } + }); + } + }); + if (!digests.length) { + return finish(); + } + var numDone = 0; + var err; + + function checkDone() { + if (++numDone === digests.length) { + finish(err); + } + } + digests.forEach(function (digest) { + verifyAttachment(digest, function (attErr) { + if (attErr && !err) { + err = attErr; + } + checkDone(); + }); + }); + } + + function writeDoc(docInfo, winningRev, deleted, callback, isUpdate, resultsIdx) { function finish() { - updateSeq++; var data = docInfo.data; var deletedInt = deleted ? 1 : 0; @@ -3763,8 +4136,40 @@ ' (doc_id, rev, json, deleted) VALUES (?, ?, ?, ?);'; var sqlArgs = [id, rev, json, deletedInt]; + // map seqs to attachment digests, which + // we will need later during compaction + function insertAttachmentMappings(seq, callback) { + var attsAdded = 0; + var attsToAdd = Object.keys(data._attachments || {}); + + if (!attsToAdd.length) { + return callback(); + } + function checkDone() { + if (++attsAdded === attsToAdd.length) { + callback(); + } + return false; // ack handling a constraint error + } + function add(att) { + var sql = 'INSERT INTO ' + ATTACH_AND_SEQ_STORE + + ' (digest, seq) VALUES (?,?)'; + var sqlArgs = [data._attachments[att].digest, seq]; + tx.executeSql(sql, sqlArgs, checkDone, checkDone); + // second callback is for a constaint error, which we ignore + // because this docid/rev has already been associated with + // the digest (e.g. when new_edits == false) + } + for (var i = 0; i < attsToAdd.length; i++) { + add(attsToAdd[i]); // do in parallel + } + } + tx.executeSql(sql, sqlArgs, function (tx, result) { - dataWritten(tx, result.insertId); + var seq = result.insertId; + insertAttachmentMappings(seq, function () { + dataWritten(tx, seq); + }); }, function () { // constraint error, recover by updating instead (see #1638) var fetchSql = select('seq', BY_SEQ_STORE, null, @@ -3775,8 +4180,9 @@ ' SET json=?, deleted=? WHERE doc_id=? AND rev=?;'; var sqlArgs = [json, deletedInt, id, rev]; tx.executeSql(sql, sqlArgs, function (tx) { - updateSeq--; // discount, since it's an update, not a new seq - dataWritten(tx, seq); + insertAttachmentMappings(seq, function () { + dataWritten(tx, seq); + }); }); }); return false; // ack that we've handled the error @@ -3817,7 +4223,7 @@ var data = docInfo.data._attachments[key].data; delete docInfo.data._attachments[key].data; var digest = docInfo.data._attachments[key].digest; - saveAttachment(docInfo, digest, data, attachmentSaved); + saveAttachment(digest, data, attachmentSaved); } else { recv++; collectResults(); @@ -3851,98 +4257,9 @@ } } - function updateDoc(oldDoc, docInfo, resultsIdx, callback) { - var merged = - merge.merge(oldDoc.rev_tree, docInfo.metadata.rev_tree[0], 1000); - var deleted = utils.isDeleted(docInfo.metadata); - var oldDocDeleted = utils.isDeleted(oldDoc); - var inConflict = (oldDocDeleted && deleted && newEdits) || - (!oldDocDeleted && newEdits && merged.conflicts !== 'new_leaf'); - if (inConflict) { - results[resultsIdx] = makeErr(errors.REV_CONFLICT, docInfo._bulk_seq); - return callback(); - } - - docInfo.metadata.rev_tree = merged.tree; - - // recalculate - var winningRev = merge.winningRev(docInfo.metadata); - deleted = utils.isDeleted(docInfo.metadata, winningRev); - - writeDoc(docInfo, winningRev, deleted, callback, true, resultsIdx); - } - - function insertDoc(docInfo, resultsIdx, callback) { - // Cant insert new deleted documents - var winningRev = merge.winningRev(docInfo.metadata); - var deleted = utils.isDeleted(docInfo.metadata, winningRev); - if ('was_delete' in opts && deleted) { - results[resultsIdx] = errors.MISSING_DOC; - return callback(); - } - writeDoc(docInfo, winningRev, deleted, callback, false, resultsIdx); - } - - function checkDoneWritingDocs() { - if (++numDocsWritten === docInfos.length) { - complete(); - } - } - function processDocs() { - if (!docInfos.length) { - return complete(); - } - - var idsToDocs = new utils.Map(); - - docInfos.forEach(function (currentDoc, resultsIdx) { - - if (currentDoc._id && utils.isLocalId(currentDoc._id)) { - api[currentDoc._deleted ? '_removeLocal' : '_putLocal']( - currentDoc, {ctx: tx}, function (err, resp) { - if (err) { - results[resultsIdx] = err; - } else { - results[resultsIdx] = {}; - } - checkDoneWritingDocs(); - }); - return; - } - - var id = currentDoc.metadata.id; - if (idsToDocs.has(id)) { - idsToDocs.get(id).push([currentDoc, resultsIdx]); - } else { - idsToDocs.set(id, [[currentDoc, resultsIdx]]); - } - }); - - // in the case of new_edits, the user can provide multiple docs - // with the same id. these need to be processed sequentially - idsToDocs.forEach(function (docs, id) { - var numDone = 0; - - function docWritten() { - checkDoneWritingDocs(); - if (++numDone < docs.length) { - nextDoc(); - } - } - function nextDoc() { - var value = docs[numDone]; - var currentDoc = value[0]; - var resultsIdx = value[1]; - - if (fetchedDocs.has(id)) { - updateDoc(fetchedDocs.get(id), currentDoc, resultsIdx, docWritten); - } else { - insertDoc(currentDoc, resultsIdx, docWritten); - } - } - nextDoc(); - }); + utils.processDocs(docInfos, api, fetchedDocs, + tx, results, writeDoc, opts); } function fetchExistingDocs(callback) { @@ -3974,44 +4291,41 @@ }); } - // Insert sequence number into the error so we can sort later - function makeErr(err, seq) { - err._bulk_seq = seq; - return err; - } - - function saveAttachment(docInfo, digest, data, callback) { - var ref = [docInfo.metadata.id, docInfo.metadata.rev].join('@'); - var newAtt = {digest: digest}; - var sql = 'SELECT digest, json FROM ' + ATTACH_STORE + ' WHERE digest=?'; + function saveAttachment(digest, data, callback) { + var sql = 'SELECT digest FROM ' + ATTACH_STORE + ' WHERE digest=?'; tx.executeSql(sql, [digest], function (tx, result) { - if (!result.rows.length) { - newAtt.refs = {}; - newAtt.refs[ref] = true; - sql = 'INSERT INTO ' + ATTACH_STORE + - '(digest, json, body) VALUES (?, ?, ?)'; - tx.executeSql(sql, [digest, JSON.stringify(newAtt), data], - function () { - callback(); - }); - } else { - newAtt.refs = JSON.parse(result.rows.item(0).json).refs; - sql = 'UPDATE ' + ATTACH_STORE + ' SET json=?, body=? WHERE digest=?'; - tx.executeSql(sql, [JSON.stringify(newAtt), data, digest], - function () { - callback(); - }); + if (result.rows.length) { // attachment already exists + return callback(); } + // we could just insert before selecting and catch the error, + // but my hunch is that it's cheaper not to serialize the blob + // from JS to C if we don't have to (TODO: confirm this) + sql = 'INSERT INTO ' + ATTACH_STORE + + ' (digest, body, escaped) VALUES (?,?,1)'; + tx.executeSql(sql, [digest, escapeBlob(data)], function () { + callback(); + }, function () { + // ignore constaint errors, means it already exists + callback(); + return false; // ack we handled the error + }); }); } - preprocessAttachments(function () { + utils.preprocessAttachments(docInfos, 'binary', function (err) { + if (err) { + return callback(err); + } db.transaction(function (txn) { tx = txn; - fetchExistingDocs(processDocs); - }, unknownError(callback), function () { - docCount = -1; - }); + verifyAttachments(function (err) { + if (err) { + preconditionErrored = err; + } else { + fetchExistingDocs(processDocs); + } + }); + }, unknownError(callback), complete); }); }; @@ -4164,11 +4478,7 @@ if (opts.conflicts) { doc.doc._conflicts = merge.collectConflicts(metadata); } - for (var att in doc.doc._attachments) { - if (doc.doc._attachments.hasOwnProperty(att)) { - doc.doc._attachments[att].stub = true; - } - } + fetchAttachmentsIfNecessary(doc.doc, opts, api, tx); } if (item.deleted) { if (opts.deleted === 'ok') { @@ -4246,9 +4556,14 @@ sql += ' LIMIT ' + limit; } + var lastSeq = 0; db.readTransaction(function (tx) { tx.executeSql(sql, sqlArgs, function (tx, result) { - var lastSeq = 0; + function reportChange(change) { + return function () { + opts.onChange(change); + }; + } for (var i = 0, l = result.rows.length; i < l; i++) { var res = result.rows.item(i); var metadata = vuvuzela.parse(res.metadata); @@ -4263,19 +4578,27 @@ if (returnDocs) { results.push(change); } - opts.onChange(change); + // process the attachment immediately + // for the benefit of live listeners + if (opts.attachments && opts.include_docs) { + fetchAttachmentsIfNecessary(doc, opts, api, tx, + reportChange(change)); + } else { + reportChange(change)(); + } } if (numResults === limit) { break; } } - if (!opts.continuous) { - opts.complete(null, { - results: results, - last_seq: lastSeq - }); - } }); + }, unknownError(opts.complete), function () { + if (!opts.continuous) { + opts.complete(null, { + results: results, + last_seq: lastSeq + }); + } }); } @@ -4292,13 +4615,17 @@ var tx = opts.ctx; var digest = attachment.digest; var type = attachment.content_type; - var sql = 'SELECT hex(body) as body FROM ' + ATTACH_STORE + - ' WHERE digest=?'; + var sql = 'SELECT escaped, ' + + 'CASE WHEN escaped = 1 THEN body ELSE HEX(body) END AS body FROM ' + + ATTACH_STORE + ' WHERE digest=?'; tx.executeSql(sql, [digest], function (tx, result) { - // sqlite normally stores data as utf8, so even the hex() function - // "encodes" the binary data in utf8/16 before returning it. yet hex() - // is the only way to get the full data, so we do this. - var data = parseHexString(result.rows.item(0).body, encoding); + // websql has a bug where \u0000 causes early truncation in strings + // and blobs. to work around this, we used to use the hex() function, + // but that's not performant. after migration 6, we remove \u0000 + // and add it back in afterwards + var item = result.rows.item(0); + var data = item.escaped ? unescapeBlob(item.body) : + parseHexString(item.body, encoding); if (opts.encode) { res = btoa(data); } else { @@ -4323,33 +4650,66 @@ }); }; - api._doCompaction = function (docId, rev_tree, revs, callback) { + api._doCompaction = function (docId, revs, callback) { if (!revs.length) { return callback(); } db.transaction(function (tx) { + + // update doc store var sql = 'SELECT json AS metadata FROM ' + DOC_STORE + ' WHERE id = ?'; tx.executeSql(sql, [docId], function (tx, result) { - if (!result.rows.length) { - return utils.call(callback); - } var metadata = vuvuzela.parse(result.rows.item(0).metadata); - metadata.rev_tree = rev_tree; + merge.traverseRevTree(metadata.rev_tree, function (isLeaf, pos, + revHash, ctx, opts) { + var rev = pos + '-' + revHash; + if (revs.indexOf(rev) !== -1) { + opts.status = 'missing'; + } + }); - var numDone = 0; - revs.forEach(function (rev) { - var sql = 'DELETE FROM ' + BY_SEQ_STORE + ' WHERE doc_id=? AND rev=?'; - tx.executeSql(sql, [docId, rev], function (tx) { - if (++numDone === revs.length) { - var sql = 'UPDATE ' + DOC_STORE + ' SET json = ? WHERE id = ?'; - tx.executeSql(sql, [vuvuzela.stringify(metadata), docId], - function () { - callback(); - }); + var sql = 'UPDATE ' + DOC_STORE + ' SET json = ? WHERE id = ?'; + tx.executeSql(sql, [vuvuzela.stringify(metadata), docId]); + }); + + // update by-seq and attach stores in parallel + revs.forEach(function (rev) { + var sql = 'SELECT seq FROM ' + BY_SEQ_STORE + + ' WHERE doc_id=? AND rev=?'; + tx.executeSql(sql, [docId, rev], function (tx, res) { + if (!res.rows.length) { + return; // already deleted + } + var seq = res.rows.item(0).seq; + + // find orphaned attachment digests + var sql = 'SELECT a1.digest AS digest ' + + 'FROM ' + ATTACH_AND_SEQ_STORE + ' a1 JOIN ' + + ATTACH_AND_SEQ_STORE + ' a2 ON a1.digest=a2.digest ' + + 'WHERE a1.seq=? ' + + 'GROUP BY a1.digest HAVING COUNT(*) = 1'; + tx.executeSql(sql, [seq], function (tx, res) { + var orphanedAttachments = []; + for (var i = 0; i < res.rows.length; i++) { + orphanedAttachments.push(res.rows.item(i).digest); } + + tx.executeSql( + 'DELETE FROM ' + BY_SEQ_STORE + ' WHERE seq=?', [seq]); + tx.executeSql( + 'DELETE FROM ' + ATTACH_AND_SEQ_STORE + ' WHERE seq=?', [seq]); + orphanedAttachments.forEach(function (digest) { + tx.executeSql( + 'DELETE FROM ' + ATTACH_AND_SEQ_STORE + ' WHERE digest=?', + [digest]); + tx.executeSql( + 'DELETE FROM ' + ATTACH_STORE + ' WHERE digest=?', [digest]); + }); }); }); }); + }, unknownError(callback), function () { + callback(); }); }; @@ -4431,12 +4791,14 @@ var params = [doc._id, doc._rev]; tx.executeSql(sql, params, function (tx, res) { if (!res.rowsAffected) { - return callback(errors.REV_CONFLICT); + return callback(errors.MISSING_DOC); } ret = {ok: true, id: doc._id, rev: '0-0'}; }); }, unknownError(callback), function () { - callback(null, ret); + if (ret) { + callback(null, ret); + } }); }; } @@ -4462,7 +4824,7 @@ var db = openDB(name, POUCH_VERSION, name, size); db.transaction(function (tx) { var stores = [DOC_STORE, BY_SEQ_STORE, ATTACH_STORE, META_STORE, - LOCAL_STORE]; + LOCAL_STORE, ATTACH_AND_SEQ_STORE]; stores.forEach(function (store) { tx.executeSql('DROP TABLE IF EXISTS ' + store, []); }); @@ -4479,8 +4841,8 @@ module.exports = WebSqlPouch; -}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../deps/errors":11,"../merge":18,"../utils":23,"vuvuzela":58}],6:[function(_dereq_,module,exports){ +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"../deps/errors":12,"../deps/parse-hex":14,"../merge":20,"../utils":25,"vuvuzela":67}],6:[function(_dereq_,module,exports){ 'use strict'; var utils = _dereq_('./utils'); var merge = _dereq_('./merge'); @@ -4649,7 +5011,8 @@ } if (this.db.type() !== 'http' && - opts.filter && typeof opts.filter === 'string') { + opts.filter && typeof opts.filter === 'string' && + !opts.doc_ids) { return this.filterChanges(opts); } @@ -4743,7 +5106,101 @@ }); } }; -},{"./deps/errors":11,"./evalFilter":15,"./evalView":16,"./merge":18,"./utils":23,"events":27}],7:[function(_dereq_,module,exports){ +},{"./deps/errors":12,"./evalFilter":18,"./evalView":19,"./merge":20,"./utils":25,"events":33}],7:[function(_dereq_,module,exports){ +'use strict'; + +var utils = _dereq_('./utils'); + +function updateCheckpoint(db, id, checkpoint, returnValue) { + return db.get(id)["catch"](function (err) { + if (err.status === 404) { + if (db.type() === 'http') { + utils.explain404( + 'PouchDB is just checking if a remote checkpoint exists.'); + } + return {_id: id}; + } + throw err; + }).then(function (doc) { + if (returnValue.cancelled) { + return; + } + doc.last_seq = checkpoint; + return db.put(doc); + }); +} + +function Checkpointer(src, target, id, returnValue) { + this.src = src; + this.target = target; + this.id = id; + this.returnValue = returnValue; +} + +Checkpointer.prototype.writeCheckpoint = function (checkpoint) { + var self = this; + return this.updateTarget(checkpoint).then(function () { + return self.updateSource(checkpoint); + }); +}; + +Checkpointer.prototype.updateTarget = function (checkpoint) { + return updateCheckpoint(this.target, this.id, checkpoint, this.returnValue); +}; + +Checkpointer.prototype.updateSource = function (checkpoint) { + var self = this; + if (this.readOnlySource) { + return utils.Promise.resolve(true); + } + return updateCheckpoint(this.src, this.id, checkpoint, this.returnValue)[ + "catch"](function (err) { + var isForbidden = typeof err.status === 'number' && + Math.floor(err.status / 100) === 4; + if (isForbidden) { + self.readOnlySource = true; + return true; + } + throw err; + }); +}; + +Checkpointer.prototype.getCheckpoint = function () { + var self = this; + return self.target.get(self.id).then(function (targetDoc) { + return self.src.get(self.id).then(function (sourceDoc) { + if (targetDoc.last_seq === sourceDoc.last_seq) { + return sourceDoc.last_seq; + } + return 0; + }, function (err) { + if (err.status === 404 && targetDoc.last_seq) { + return self.src.put({ + _id: self.id, + last_seq: 0 + }).then(function () { + return 0; + }, function (err) { + if (err.status === 401) { + self.readOnlySource = true; + return targetDoc.last_seq; + } + return 0; + }); + } + throw err; + }); + })["catch"](function (err) { + if (err.status !== 404) { + throw err; + } + return 0; + }); +}; + +module.exports = Checkpointer; + +},{"./utils":25}],8:[function(_dereq_,module,exports){ (function (global){ /*globals cordova */ "use strict"; @@ -4759,11 +5216,11 @@ } } -utils.inherits(PouchDBVersion306, Adapter); -function PouchDBVersion306(name, opts, callback) { +utils.inherits(PouchDB, Adapter); +function PouchDB(name, opts, callback) { - if (!(this instanceof PouchDBVersion306)) { - return new PouchDBVersion306(name, opts, callback); + if (!(this instanceof PouchDB)) { + return new PouchDB(name, opts, callback); } var self = this; if (typeof opts === 'function' || typeof opts === 'undefined') { @@ -4779,9 +5236,10 @@ callback = defaultCallback; } opts = opts || {}; + this.__opts = opts; var oldCB = callback; self.auto_compaction = opts.auto_compaction; - self.prefix = PouchDBVersion306.prefix; + self.prefix = PouchDB.prefix; Adapter.call(self); self.taskqueue = new TaskQueue(); var promise = new Promise(function (fulfill, reject) { @@ -4805,7 +5263,7 @@ throw error; } - backend = PouchDBVersion306.parseAdapter(originalName, opts); + backend = PouchDB.parseAdapter(originalName, opts); opts.originalName = originalName; opts.name = backend.name; @@ -4816,13 +5274,13 @@ opts.adapter = opts.adapter || backend.adapter; self._adapter = opts.adapter; self._db_name = originalName; - if (!PouchDBVersion306.adapters[opts.adapter]) { + if (!PouchDB.adapters[opts.adapter]) { error = new Error('Adapter is missing'); error.code = 404; throw error; } - if (!PouchDBVersion306.adapters[opts.adapter].valid()) { + if (!PouchDB.adapters[opts.adapter].valid()) { error = new Error('Invalid Adapter'); error.code = 404; throw error; @@ -4841,7 +5299,7 @@ } self.adapter = opts.adapter; - // needs access to PouchDBVersion306; + // needs access to PouchDB; self.replicate = {}; self.replicate.from = function (url, opts, callback) { @@ -4868,7 +5326,7 @@ }); }); - PouchDBVersion306.adapters[opts.adapter].call(self, opts, function (err, db) { + PouchDB.adapters[opts.adapter].call(self, opts, function (err, db) { if (err) { if (callback) { self.taskqueue.fail(err); @@ -4879,12 +5337,12 @@ function destructionListener(event) { if (event === 'destroyed') { self.emit('destroyed'); - PouchDBVersion306.removeListener(originalName, destructionListener); + PouchDB.removeListener(originalName, destructionListener); } } - PouchDBVersion306.on(originalName, destructionListener); + PouchDB.on(originalName, destructionListener); self.emit('created', self); - PouchDBVersion306.emit('created', opts.originalName); + PouchDB.emit('created', opts.originalName); self.taskqueue.ready(self); callback(null, self); @@ -4903,13 +5361,14 @@ }, oldCB); self.then = promise.then.bind(promise); self["catch"] = promise["catch"].bind(promise); - } -module.exports = PouchDBVersion306; +PouchDB.debug = _dereq_('debug'); -}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./adapter":1,"./taskqueue":22,"./utils":23}],8:[function(_dereq_,module,exports){ +module.exports = PouchDB; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./adapter":1,"./taskqueue":24,"./utils":25,"debug":35}],9:[function(_dereq_,module,exports){ "use strict"; var createBlob = _dereq_('./blob.js'); @@ -5131,21 +5590,9 @@ } } if (options.body && (options.body instanceof Blob)) { - var reader = new FileReader(); - reader.onloadend = function (e) { - - var binary = ""; - var bytes = new Uint8Array(this.result); - var length = bytes.byteLength; - - for (var i = 0; i < length; i++) { - binary += String.fromCharCode(bytes[i]); - } - - binary = utils.fixBinary(binary); - xhr.send(binary); - }; - reader.readAsArrayBuffer(options.body); + utils.readAsBinaryString(options.body, function (binary) { + xhr.send(utils.fixBinary(binary)); + }); } else { xhr.send(options.body); } @@ -5154,7 +5601,7 @@ module.exports = ajax; -},{"../utils":23,"./blob.js":9,"./errors":11}],9:[function(_dereq_,module,exports){ +},{"../utils":25,"./blob.js":10,"./errors":12}],10:[function(_dereq_,module,exports){ (function (global){ "use strict"; @@ -5185,8 +5632,8 @@ module.exports = createBlob; -}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],10:[function(_dereq_,module,exports){ +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],11:[function(_dereq_,module,exports){ 'use strict'; exports.Map = LazyMap; // TODO: use ES6 map exports.Set = LazySet; // TODO: use ES6 set @@ -5238,8 +5685,15 @@ }); }; -function LazySet() { +function LazySet(array) { this.store = new LazyMap(); + + // init with an array + if (array && Array.isArray(array)) { + for (var i = 0, len = array.length; i < len; i++) { + this.add(array[i]); + } + } } LazySet.prototype.add = function (key) { return this.store.set(key, true); @@ -5250,7 +5704,7 @@ LazySet.prototype["delete"] = function (key) { return this.store["delete"](key); }; -},{}],11:[function(_dereq_,module,exports){ +},{}],12:[function(_dereq_,module,exports){ "use strict"; function PouchError(opts) { @@ -5381,13 +5835,14 @@ return new CustomPouchError(reason); }; -},{}],12:[function(_dereq_,module,exports){ +},{}],13:[function(_dereq_,module,exports){ (function (process,global){ 'use strict'; var crypto = _dereq_('crypto'); var Md5 = _dereq_('spark-md5'); var setImmediateShim = global.setImmediate || global.setTimeout; +var MD5_CHUNK_SIZE = 32768; function sliceShim(arrayBuffer, begin, end) { if (typeof arrayBuffer.slice === 'function') { @@ -5463,7 +5918,7 @@ } var inputIsString = typeof data === 'string'; var len = inputIsString ? data.length : data.byteLength; - var chunkSize = Math.min(524288, len); + var chunkSize = Math.min(MD5_CHUNK_SIZE, len); var chunks = Math.ceil(len / chunkSize); var currentChunk = 0; var buffer = inputIsString ? new Md5() : new Md5.ArrayBuffer(); @@ -5497,8 +5952,122 @@ loadNextChunk(); }; -}).call(this,_dereq_("/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":28,"crypto":26,"spark-md5":57}],13:[function(_dereq_,module,exports){ +}).call(this,_dereq_('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"_process":34,"crypto":28,"spark-md5":66}],14:[function(_dereq_,module,exports){ +'use strict'; + +// +// Parsing hex strings. Yeah. +// +// So basically we need this because of a bug in WebSQL: +// https://code.google.com/p/chromium/issues/detail?id=422690 +// https://bugs.webkit.org/show_bug.cgi?id=137637 +// +// UTF-8 and UTF-16 are provided as separate functions +// for meager performance improvements +// + +function decodeUtf8(str) { + return decodeURIComponent(window.escape(str)); +} + +function hexToInt(charCode) { + // '0'-'9' is 48-57 + // 'A'-'F' is 65-70 + // SQLite will only give us uppercase hex + return charCode < 65 ? (charCode - 48) : (charCode - 55); +} + + +// Example: +// pragma encoding=utf8; +// select hex('A'); +// returns '41' +function parseHexUtf8(str, start, end) { + var result = ''; + while (start < end) { + result += String.fromCharCode( + (hexToInt(str.charCodeAt(start++)) << 4) | + hexToInt(str.charCodeAt(start++))); + } + return result; +} + +// Example: +// pragma encoding=utf16; +// select hex('A'); +// returns '4100' +// notice that the 00 comes after the 41 (i.e. it's swizzled) +function parseHexUtf16(str, start, end) { + var result = ''; + while (start < end) { + // UTF-16, so swizzle the bytes + result += String.fromCharCode( + (hexToInt(str.charCodeAt(start + 2)) << 12) | + (hexToInt(str.charCodeAt(start + 3)) << 8) | + (hexToInt(str.charCodeAt(start)) << 4) | + hexToInt(str.charCodeAt(start + 1))); + start += 4; + } + return result; +} + +function parseHexString(str, encoding) { + if (encoding === 'UTF-8') { + return decodeUtf8(parseHexUtf8(str, 0, str.length)); + } else { + return parseHexUtf16(str, 0, str.length); + } +} + +module.exports = parseHexString; +},{}],15:[function(_dereq_,module,exports){ +'use strict'; + +// originally parseUri 1.2.2, now patched by us +// (c) Steven Levithan <stevenlevithan.com> +// MIT License +var options = { + strictMode: false, + key: ["source", "protocol", "authority", "userInfo", "user", "password", + "host", "port", "relative", "path", "directory", "file", "query", + "anchor"], + q: { + name: "queryKey", + parser: /(?:^|&)([^&=]*)=?([^&]*)/g + }, + parser: { + /* jshint maxlen: false */ + strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, + loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ + } +}; +function parseUri(str) { + var o = options; + var m = o.parser[o.strictMode ? "strict" : "loose"].exec(str); + var uri = {}; + var i = 14; + + while (i--) { + var key = o.key[i]; + var value = m[i] || ""; + var encoded = ['user', 'password'].indexOf(key) !== -1; + uri[key] = encoded ? decodeURIComponent(value) : value; + } + + uri[o.q.name] = {}; + uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) { + if ($1) { + uri[o.q.name][$1] = $2; + } + }); + + return uri; +} + + +module.exports = parseUri; +},{}],16:[function(_dereq_,module,exports){ 'use strict'; var Promise = _dereq_('../utils').Promise; @@ -5549,7 +6118,7 @@ } }; -},{"../utils":23}],14:[function(_dereq_,module,exports){ +},{"../utils":25}],17:[function(_dereq_,module,exports){ "use strict"; // BEGIN Math.uuid.js @@ -5634,7 +6203,7 @@ module.exports = uuid; -},{}],15:[function(_dereq_,module,exports){ +},{}],18:[function(_dereq_,module,exports){ 'use strict'; module.exports = evalFilter; @@ -5646,7 +6215,7 @@ ' })()' ].join('')); } -},{}],16:[function(_dereq_,module,exports){ +},{}],19:[function(_dereq_,module,exports){ 'use strict'; module.exports = evalView; @@ -5668,37 +6237,7 @@ '})()' ].join('\n')); } -},{}],17:[function(_dereq_,module,exports){ -(function (process){ -"use strict"; - -var PouchDBVersion306 = _dereq_('./setup'); - -module.exports = PouchDBVersion306; - -PouchDBVersion306.ajax = _dereq_('./deps/ajax'); -PouchDBVersion306.extend = _dereq_('pouchdb-extend'); -PouchDBVersion306.utils = _dereq_('./utils'); -PouchDBVersion306.Errors = _dereq_('./deps/errors'); -PouchDBVersion306.replicate = _dereq_('./replicate').replicate; -PouchDBVersion306.sync = _dereq_('./sync'); -PouchDBVersion306.version = _dereq_('./version'); -var httpAdapter = _dereq_('./adapters/http'); -PouchDBVersion306.adapter('http', httpAdapter); -PouchDBVersion306.adapter('https', httpAdapter); - -PouchDBVersion306.adapter('idb', _dereq_('./adapters/idb')); -PouchDBVersion306.adapter('websql', _dereq_('./adapters/websql')); -PouchDBVersion306.plugin(_dereq_('pouchdb-mapreduce')); - -if (!process.browser) { - var ldbAdapter = _dereq_('./adapters/leveldb'); - PouchDBVersion306.adapter('ldb', ldbAdapter); - PouchDBVersion306.adapter('leveldb', ldbAdapter); -} - -}).call(this,_dereq_("/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js")) -},{"./adapters/http":2,"./adapters/idb":3,"./adapters/leveldb":26,"./adapters/websql":5,"./deps/ajax":8,"./deps/errors":11,"./replicate":19,"./setup":20,"./sync":21,"./utils":23,"./version":24,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":28,"pouchdb-extend":48,"pouchdb-mapreduce":51}],18:[function(_dereq_,module,exports){ +},{}],20:[function(_dereq_,module,exports){ 'use strict'; var extend = _dereq_('pouchdb-extend'); @@ -5974,20 +6513,80 @@ module.exports = PouchMerge; -},{"pouchdb-extend":48}],19:[function(_dereq_,module,exports){ +},{"pouchdb-extend":57}],21:[function(_dereq_,module,exports){ 'use strict'; var utils = _dereq_('./utils'); var EE = _dereq_('events').EventEmitter; - +var Checkpointer = _dereq_('./checkpointer'); var MAX_SIMULTANEOUS_REVS = 50; +function randomNumber(min, max) { + min = parseInt(min, 10); + max = parseInt(max, 10); + if (min !== min) { + min = 0; + } + if (max !== max || max <= min) { + max = (min || 1) << 1; //doubling + } else { + max = max + 1; + } + var ratio = Math.random(); + var range = max - min; + + return ~~(range * ratio + min); // ~~ coerces to an int, but fast. +} + +function defaultBackOff(min) { + var max = 0; + if (!min) { + max = 2000; + } + return randomNumber(min, max); +} + +function backOff(repId, src, target, opts, returnValue, result, error) { + if (opts.retry === false) { + returnValue.emit('error', error); + returnValue.removeAllListeners(); + return; + } + opts.default_back_off = opts.default_back_off || 0; + opts.retries = opts.retries || 0; + if (typeof opts.back_off_function !== 'function') { + opts.back_off_function = defaultBackOff; + } + opts.retries++; + if (opts.max_retries && opts.retries > opts.max_retries) { + returnValue.emit('error', new Error('tried ' + + opts.retries + ' times but replication failed')); + returnValue.removeAllListeners(); + return; + } + returnValue.emit('requestError', error); + if (returnValue.state === 'active') { + returnValue.emit('syncStopped'); + returnValue.state = 'stopped'; + returnValue.once('syncRestarted', function () { + opts.current_back_off = opts.default_back_off; + }); + } + + opts.current_back_off = opts.current_back_off || opts.default_back_off; + opts.current_back_off = opts.back_off_function(opts.current_back_off); + setTimeout(function () { + replicate(repId, src, target, opts, returnValue); + }, opts.current_back_off); +} + // We create a basic promise so the caller can cancel the replication possibly // before we have actually started listening to changes etc utils.inherits(Replication, EE); function Replication(opts) { EE.call(this); this.cancelled = false; + this.state = 'pending'; var self = this; var promise = new utils.Promise(function (fulfill, reject) { self.once('complete', fulfill); @@ -6002,15 +6601,26 @@ // As we allow error handling via "error" event as well, // put a stub in here so that rejecting never throws UnhandledError. self["catch"](function (err) {}); + } Replication.prototype.cancel = function () { this.cancelled = true; + this.state = 'cancelled'; this.emit('cancel'); }; Replication.prototype.ready = function (src, target) { var self = this; + this.once('change', function () { + if (this.state === 'pending') { + self.state = 'active'; + self.emit('syncStarted'); + } else if (self.state === 'stopped') { + self.state = 'active'; + self.emit('syncRestarted'); + } + }); function onDestroy() { self.cancel(); } @@ -6043,87 +6653,7 @@ }); } - -function updateCheckpoint(db, id, checkpoint, returnValue) { - return db.get(id)["catch"](function (err) { - if (err.status === 404) { - return {_id: id}; - } - throw err; - }).then(function (doc) { - if (returnValue.cancelled) { - return; - } - doc.last_seq = checkpoint; - return db.put(doc); - }); - } - -function Checkpointer(src, target, id, returnValue) { - this.src = src; - this.target = target; - this.id = id; - this.returnValue = returnValue; -} - -Checkpointer.prototype.writeCheckpoint = function (checkpoint) { - var self = this; - return this.updateTarget(checkpoint).then(function () { - return self.updateSource(checkpoint); - }); -}; -Checkpointer.prototype.updateTarget = function (checkpoint) { - return updateCheckpoint(this.target, this.id, checkpoint, this.returnValue); -}; -Checkpointer.prototype.updateSource = function (checkpoint) { - var self = this; - if (this.readOnlySource) { - return utils.Promise.resolve(true); - } - return updateCheckpoint(this.src, this.id, checkpoint, this.returnValue)[ - "catch"](function (err) { - var isForbidden = typeof err.status === 'number' && - Math.floor(err.status / 100) === 4; - if (isForbidden) { - self.readOnlySource = true; - return true; - } - throw err; - }); -}; -Checkpointer.prototype.getCheckpoint = function () { - var self = this; - return self.target.get(self.id).then(function (targetDoc) { - return self.src.get(self.id).then(function (sourceDoc) { - if (targetDoc.last_seq === sourceDoc.last_seq) { - return sourceDoc.last_seq; - } - return 0; - }, function (err) { - if (err.status === 404 && targetDoc.last_seq) { - return self.src.put({ - _id: self.id, - last_seq: 0 - }).then(function () { - return 0; - }, function (err) { - if (err.status === 401) { - self.readOnlySource = true; - return targetDoc.last_seq; - } - return 0; - }); - } - throw err; - }); - })["catch"](function (err) { - if (err.status !== 404) { - throw err; - } - return 0; - }); -}; -function replicate(repId, src, target, opts, returnValue) { +function replicate(repId, src, target, opts, returnValue, result) { var batches = []; // list of batches to be processed var currentBatch; // the batch currently being processed var pendingBatch = { @@ -6140,8 +6670,11 @@ var batches_limit = opts.batches_limit || 10; var changesPending = false; // true while src.changes is running var doc_ids = opts.doc_ids; - var checkpointer = new Checkpointer(src, target, repId, returnValue); - var result = { + var state = { + cancelled: false + }; + var checkpointer = new Checkpointer(src, target, repId, state); + result = result || { ok: true, start_time: new Date(), docs_read: 0, @@ -6152,7 +6685,6 @@ var changesOpts = {}; returnValue.ready(src, target); - function writeDocs() { if (currentBatch.docs.length === 0) { return; @@ -6163,7 +6695,7 @@ }, { new_edits: false }).then(function (res) { - if (returnValue.cancelled) { + if (state.cancelled) { completeReplication(); throw new Error('cancelled'); } @@ -6209,16 +6741,16 @@ return src.get(id, {revs: true, open_revs: missing, attachments: true}) .then(function (docs) { docs.forEach(function (doc) { - if (returnValue.cancelled) { + if (state.cancelled) { return completeReplication(); } if (doc.ok) { result.docs_read++; currentBatch.pendingRevs++; currentBatch.docs.push(doc.ok); - delete diffs[doc.ok._id]; } }); + delete diffs[id]; }); })); } @@ -6243,7 +6775,7 @@ keys: ids, include_docs: true }).then(function (res) { - if (returnValue.cancelled) { + if (state.cancelled) { completeReplication(); throw (new Error('cancelled')); } @@ -6275,7 +6807,7 @@ currentBatch.seq ).then(function (res) { writingCheckpoint = false; - if (returnValue.cancelled) { + if (state.cancelled) { completeReplication(); throw new Error('cancelled'); } @@ -6299,7 +6831,7 @@ }); }); return target.revsDiff(diff).then(function (diffs) { - if (returnValue.cancelled) { + if (state.cancelled) { completeReplication(); throw new Error('cancelled'); } @@ -6311,7 +6843,7 @@ function startNextBatch() { - if (returnValue.cancelled || currentBatch) { + if (state.cancelled || currentBatch) { return; } if (batches.length === 0) { @@ -6363,7 +6895,7 @@ return; } result.ok = false; - result.status = 'aborted'; + result.status = 'aborting'; result.errors.push(err); batches = []; pendingBatch = { @@ -6379,7 +6911,7 @@ if (replicationCompleted) { return; } - if (returnValue.cancelled) { + if (state.cancelled) { result.status = 'cancelled'; if (writingCheckpoint) { return; @@ -6388,7 +6920,7 @@ result.status = result.status || 'complete'; result.end_time = new Date(); result.last_seq = last_seq; - replicationCompleted = returnValue.cancelled = true; + replicationCompleted = state.cancelled = true; var non403s = result.errors.filter(function (error) { return error.name !== 'unauthorized' && error.name !== 'forbidden'; }); @@ -6398,16 +6930,16 @@ error.other_errors = result.errors; } error.result = result; - returnValue.emit('error', error); + backOff(repId, src, target, opts, returnValue, result, error); } else { returnValue.emit('complete', result); + returnValue.removeAllListeners(); } - returnValue.removeAllListeners(); } function onChange(change) { - if (returnValue.cancelled) { + if (state.cancelled) { return completeReplication(); } if ( @@ -6425,7 +6957,7 @@ function onChangesComplete(changes) { changesPending = false; - if (returnValue.cancelled) { + if (state.cancelled) { return completeReplication(); } if (changesOpts.since < changes.last_seq) { @@ -6445,7 +6977,7 @@ function onChangesError(err) { changesPending = false; - if (returnValue.cancelled) { + if (state.cancelled) { return completeReplication(); } abortReplication('changes rejected', err); @@ -6519,7 +7051,7 @@ writingCheckpoint = true; checkpointer.writeCheckpoint(opts.since).then(function (res) { writingCheckpoint = false; - if (returnValue.cancelled) { + if (state.cancelled) { completeReplication(); return; } @@ -6560,6 +7092,7 @@ } opts = utils.clone(opts); opts.continuous = opts.continuous || opts.live; + opts.retry = opts.retry || false; /*jshint validthis:true */ opts.PouchConstructor = opts.PouchConstructor || this; var replicateRet = new Replication(opts); @@ -6576,18 +7109,18 @@ return replicateRet; } -},{"./utils":23,"events":27}],20:[function(_dereq_,module,exports){ +},{"./checkpointer":7,"./utils":25,"events":33}],22:[function(_dereq_,module,exports){ (function (global){ "use strict"; -var PouchDBVersion306 = _dereq_("./constructor"); +var PouchDB = _dereq_("./constructor"); var utils = _dereq_('./utils'); var Promise = utils.Promise; var EventEmitter = _dereq_('events').EventEmitter; -PouchDBVersion306.adapters = {}; -PouchDBVersion306.preferredAdapters = _dereq_('./adapters/preferredAdapters.js'); +PouchDB.adapters = {}; +PouchDB.preferredAdapters = _dereq_('./adapters/preferredAdapters.js'); -PouchDBVersion306.prefix = '_pouch_'; +PouchDB.prefix = '_pouch_'; var eventEmitter = new EventEmitter(); @@ -6603,33 +7136,33 @@ ]; eventEmitterMethods.forEach(function (method) { - PouchDBVersion306[method] = eventEmitter[method].bind(eventEmitter); + PouchDB[method] = eventEmitter[method].bind(eventEmitter); }); -PouchDBVersion306.setMaxListeners(0); -PouchDBVersion306.parseAdapter = function (name, opts) { +PouchDB.setMaxListeners(0); +PouchDB.parseAdapter = function (name, opts) { var match = name.match(/([a-z\-]*):\/\/(.*)/); var adapter, adapterName; if (match) { // the http adapter expects the fully qualified name name = /http(s?)/.test(match[1]) ? match[1] + '://' + match[2] : match[2]; adapter = match[1]; - if (!PouchDBVersion306.adapters[adapter].valid()) { + if (!PouchDB.adapters[adapter].valid()) { throw 'Invalid adapter'; } return {name: name, adapter: match[1]}; } // check for browsers that have been upgraded from websql-only to websql+idb - var skipIdb = 'idb' in PouchDBVersion306.adapters && 'websql' in PouchDBVersion306.adapters && + var skipIdb = 'idb' in PouchDB.adapters && 'websql' in PouchDB.adapters && utils.hasLocalStorage() && - global.localStorage['_pouch__websqldb_' + PouchDBVersion306.prefix + name]; + global.localStorage['_pouch__websqldb_' + PouchDB.prefix + name]; if (typeof opts !== 'undefined' && opts.db) { adapterName = 'leveldb'; } else { - for (var i = 0; i < PouchDBVersion306.preferredAdapters.length; ++i) { - adapterName = PouchDBVersion306.preferredAdapters[i]; - if (adapterName in PouchDBVersion306.adapters) { + for (var i = 0; i < PouchDB.preferredAdapters.length; ++i) { + adapterName = PouchDB.preferredAdapters[i]; + if (adapterName in PouchDB.adapters) { if (skipIdb && adapterName === 'idb') { continue; // keep using websql to avoid user data loss } @@ -6638,12 +7171,12 @@ } } - adapter = PouchDBVersion306.adapters[adapterName]; + adapter = PouchDB.adapters[adapterName]; if (adapterName && adapter) { var use_prefix = 'use_prefix' in adapter ? adapter.use_prefix : true; return { - name: use_prefix ? PouchDBVersion306.prefix + name : name, + name: use_prefix ? PouchDB.prefix + name : name, adapter: adapterName }; } @@ -6651,7 +7184,7 @@ throw 'No valid adapter found'; }; -PouchDBVersion306.destroy = utils.toPromise(function (name, opts, callback) { +PouchDB.destroy = utils.toPromise(function (name, opts, callback) { if (typeof opts === 'function' || typeof opts === 'undefined') { callback = opts; opts = {}; @@ -6662,12 +7195,12 @@ name = undefined; } - var backend = PouchDBVersion306.parseAdapter(opts.name || name, opts); + var backend = PouchDB.parseAdapter(opts.name || name, opts); var dbName = backend.name; - var adapter = PouchDBVersion306.adapters[backend.adapter]; + var adapter = PouchDB.adapters[backend.adapter]; var usePrefix = 'use_prefix' in adapter ? adapter.use_prefix : true; var baseName = usePrefix ? - dbName.replace(new RegExp('^' + PouchDBVersion306.prefix), '') : dbName; + dbName.replace(new RegExp('^' + PouchDB.prefix), '') : dbName; var fullName = (backend.adapter === 'http' || backend.adapter === 'https' ? '' : (opts.prefix || '')) + dbName; function destroyDb() { @@ -6676,16 +7209,16 @@ if (err) { callback(err); } else { - PouchDBVersion306.emit('destroyed', name); + PouchDB.emit('destroyed', name); //so we don't have to sift through all dbnames - PouchDBVersion306.emit(name, 'destroyed'); + PouchDB.emit(name, 'destroyed'); callback(null, resp || { 'ok': true }); } }); } var createOpts = utils.extend(true, {}, opts, {adapter : backend.adapter}); - new PouchDBVersion306(baseName, createOpts, function (err, db) { + new PouchDB(baseName, createOpts, function (err, db) { if (err) { return callback(err); } @@ -6700,9 +7233,9 @@ var dependentDbs = localDoc.dependentDbs; var deletedMap = Object.keys(dependentDbs).map(function (name) { var trueName = usePrefix ? - name.replace(new RegExp('^' + PouchDBVersion306.prefix), '') : name; + name.replace(new RegExp('^' + PouchDB.prefix), '') : name; var subOpts = utils.extend(true, opts, {adapter: backend.adapter}); - return PouchDBVersion306.destroy(trueName, subOpts); + return PouchDB.destroy(trueName, subOpts); }); Promise.all(deletedMap).then(destroyDb, function (error) { callback(error); @@ -6711,24 +7244,24 @@ }); }); -PouchDBVersion306.allDbs = utils.toPromise(function (callback) { +PouchDB.allDbs = utils.toPromise(function (callback) { var err = new Error('allDbs method removed'); err.stats = '400'; callback(err); }); -PouchDBVersion306.adapter = function (id, obj) { +PouchDB.adapter = function (id, obj) { if (obj.valid()) { - PouchDBVersion306.adapters[id] = obj; + PouchDB.adapters[id] = obj; } }; -PouchDBVersion306.plugin = function (obj) { +PouchDB.plugin = function (obj) { Object.keys(obj).forEach(function (id) { - PouchDBVersion306.prototype[id] = obj[id]; + PouchDB.prototype[id] = obj[id]; }); }; -PouchDBVersion306.defaults = function (defaultOpts) { +PouchDB.defaults = function (defaultOpts) { function PouchAlt(name, opts, callback) { if (typeof opts === 'function' || typeof opts === 'undefined') { callback = opts; @@ -6740,10 +7273,10 @@ } opts = utils.extend(true, {}, defaultOpts, opts); - PouchDBVersion306.call(this, name, opts, callback); + PouchDB.call(this, name, opts, callback); } - utils.inherits(PouchAlt, PouchDBVersion306); + utils.inherits(PouchAlt, PouchDB); PouchAlt.destroy = utils.toPromise(function (name, opts, callback) { if (typeof opts === 'function' || typeof opts === 'undefined') { @@ -6756,7 +7289,7 @@ name = undefined; } opts = utils.extend(true, {}, defaultOpts, opts); - return PouchDBVersion306.destroy(name, opts, callback); + return PouchDB.destroy(name, opts, callback); }); eventEmitterMethods.forEach(function (method) { @@ -6764,20 +7297,20 @@ }); PouchAlt.setMaxListeners(0); - PouchAlt.preferredAdapters = PouchDBVersion306.preferredAdapters.slice(); - Object.keys(PouchDBVersion306).forEach(function (key) { + PouchAlt.preferredAdapters = PouchDB.preferredAdapters.slice(); + Object.keys(PouchDB).forEach(function (key) { if (!(key in PouchAlt)) { - PouchAlt[key] = PouchDBVersion306[key]; + PouchAlt[key] = PouchDB[key]; } }); return PouchAlt; }; -module.exports = PouchDBVersion306; +module.exports = PouchDB; -}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./adapters/preferredAdapters.js":4,"./constructor":7,"./utils":23,"events":27}],21:[function(_dereq_,module,exports){ +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./adapters/preferredAdapters.js":4,"./constructor":8,"./utils":25,"events":33}],23:[function(_dereq_,module,exports){ 'use strict'; var utils = _dereq_('./utils'); var replication = _dereq_('./replicate'); @@ -6941,7 +7474,7 @@ } }; -},{"./replicate":19,"./utils":23,"events":27}],22:[function(_dereq_,module,exports){ +},{"./replicate":21,"./utils":25,"events":33}],24:[function(_dereq_,module,exports){ 'use strict'; module.exports = TaskQueue; @@ -7011,7 +7544,7 @@ } }; -},{}],23:[function(_dereq_,module,exports){ +},{}],25:[function(_dereq_,module,exports){ (function (process,global){ /*jshint strict: false */ /*global chrome */ @@ -7071,10 +7604,31 @@ '_replication_stats' ]); +exports.lastIndexOf = function (str, char) { + for (var i = str.length - 1; i >= 0; i--) { + if (str.charAt(i) === char) { + return i; + } + } + return -1; +}; + exports.clone = function (obj) { return exports.extend(true, {}, obj); }; + +// like underscore/lodash _.pick() +exports.pick = function (obj, arr) { + var res = {}; + for (var i = 0, len = arr.length; i < len; i++) { + var prop = arr[i]; + res[prop] = obj[prop]; + } + return res; +}; + exports.inherits = _dereq_('inherits'); + // Determine id an ID is valid // - invalid IDs begin with an underescore that does not begin '_design' or // '_local' @@ -7141,21 +7695,28 @@ return deleted; }; -exports.filterChange = function (opts) { - return function (change) { - var req = {}; - var hasFilter = opts.filter && typeof opts.filter === 'function'; - - req.query = opts.query_params; - if (opts.filter && hasFilter && !opts.filter.call(this, change.doc, req)) { - return false; +exports.revExists = function (metadata, rev) { + var found = false; + merge.traverseRevTree(metadata.rev_tree, function (leaf, pos, id, acc, opts) { + if ((pos + '-' + id) === rev) { + found = true; } - if (opts.doc_ids && opts.doc_ids.indexOf(change.id) === -1) { + }); + return found; +}; + +exports.filterChange = function filterChange(opts) { + var req = {}; + var hasFilter = opts.filter && typeof opts.filter === 'function'; + req.query = opts.query_params; + + return function filter(change) { + if (opts.filter && hasFilter && !opts.filter.call(this, change.doc, req)) { return false; } if (!opts.include_docs) { delete change.doc; - } else { + } else if (!opts.attachments) { for (var att in change.doc._attachments) { if (change.doc._attachments.hasOwnProperty(att)) { change.doc._attachments[att].stub = true; @@ -7169,6 +7730,7 @@ // Preprocess documents, parse their revisions, assign an id and a // revision for new writes that are missing them, etc exports.parseDoc = function (doc, newEdits) { + var nRevNum; var newRevId; var revInfo; @@ -7186,8 +7748,10 @@ if (doc._rev) { revInfo = /^(\d+)-(.+)$/.exec(doc._rev); if (!revInfo) { - var err = new TypeError("invalid value for property '_rev'"); - err.status = 400; + error = new Error('bad_request'); + error.message = 'Invalid rev format'; + error.error = true; + return error; } doc._rev_tree = [{ pos: parseInt(revInfo[1], 10), @@ -7219,9 +7783,10 @@ if (!doc._rev_tree) { revInfo = /^(\d+)-(.+)$/.exec(doc._rev); if (!revInfo) { - error = new TypeError(errors.BAD_ARG.message); - error.status = errors.BAD_ARG.status; - throw error; + error = new Error('bad_request'); + error.message = 'Invalid rev format'; + error.error = true; + return error; } nRevNum = parseInt(revInfo[1], 10); newRevId = revInfo[2]; @@ -7312,10 +7877,12 @@ function eventFunction() { db.changes({ include_docs: opts.include_docs, + attachments: opts.attachments, conflicts: opts.conflicts, continuous: false, descending: false, filter: opts.filter, + doc_ids: opts.doc_ids, view: opts.view, since: opts.since, query_params: opts.query_params, @@ -7398,13 +7965,28 @@ return buf; }; +// shim for browsers that don't support it +exports.readAsBinaryString = function (blob, callback) { + var reader = new FileReader(); + var hasBinaryString = typeof reader.readAsBinaryString === 'function'; + reader.onloadend = function (e) { + var result = e.target.result || ''; + if (hasBinaryString) { + return callback(result); + } + callback(exports.arrayBufferToBinaryString(result)); + }; + if (hasBinaryString) { + reader.readAsBinaryString(blob); + } else { + reader.readAsArrayBuffer(blob); + } +}; + exports.once = function (fun) { var called = false; return exports.getArguments(function (args) { if (called) { - if (typeof console.trace === 'function') { - console.trace(); - } throw new Error('once called more than once'); } else { called = true; @@ -7465,11 +8047,37 @@ }; exports.adapterFun = function (name, callback) { + var log = _dereq_('debug')('pouchdb:api'); + + function logApiCall(self, name, args) { + if (!log.enabled) { + return; + } + var logArgs = [self._db_name, name]; + for (var i = 0; i < args.length - 1; i++) { + logArgs.push(args[i]); + } + log.apply(null, logArgs); + + // override the callback itself to log the response + var origCallback = args[args.length - 1]; + args[args.length - 1] = function (err, res) { + var responseArgs = [self._db_name, name]; + responseArgs = responseArgs.concat( + err ? ['error', err] : ['success', res] + ); + log.apply(null, responseArgs); + origCallback(err, res); + }; + } + + return exports.toPromise(exports.getArguments(function (args) { if (this._closed) { return Promise.reject(new Error('database is closed')); } var self = this; + logApiCall(self, name, args); if (!this.taskqueue.isReady) { return new exports.Promise(function (fulfill, reject) { self.taskqueue.addTask(function (failed) { @@ -7484,6 +8092,7 @@ return callback.apply(this, args); })); }; + //Can't find original post, but this is close //http://stackoverflow.com/questions/6965107/ (continues on next line) //converting-between-strings-and-arraybuffers @@ -7580,11 +8189,232 @@ exports.MD5 = exports.toPromise(_dereq_('./deps/md5')); -}).call(this,_dereq_("/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./deps/ajax":8,"./deps/blob":9,"./deps/buffer":26,"./deps/collections":10,"./deps/errors":11,"./deps/md5":12,"./deps/uuid":14,"./merge":18,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":28,"argsarray":25,"bluebird":33,"events":27,"inherits":29,"pouchdb-extend":48}],24:[function(_dereq_,module,exports){ -module.exports = "3.0.6"; +// designed to give info to browser users, who are disturbed +// when they see 404s in the console +exports.explain404 = function (str) { + if (process.browser && 'console' in global && 'info' in console) { + console.info('The above 404 is totally normal. ' + str); + } +}; -},{}],25:[function(_dereq_,module,exports){ +exports.parseUri = _dereq_('./deps/parse-uri'); + +exports.compare = function (left, right) { + return left < right ? -1 : left > right ? 1 : 0; +}; + +exports.updateDoc = function updateDoc(prev, docInfo, results, + i, cb, write, newEdits) { + + if (exports.revExists(prev, docInfo.metadata.rev)) { + results[i] = docInfo; + return cb(); + } + + var previouslyDeleted = exports.isDeleted(prev); + var deleted = exports.isDeleted(docInfo.metadata); + var isRoot = /^1-/.test(docInfo.metadata.rev); + + if (previouslyDeleted && !deleted && newEdits && isRoot) { + var newDoc = docInfo.data; + newDoc._rev = merge.winningRev(prev); + newDoc._id = docInfo.metadata.id; + docInfo = exports.parseDoc(newDoc, newEdits); + } + + var merged = merge.merge(prev.rev_tree, docInfo.metadata.rev_tree[0], 1000); + + var inConflict = newEdits && (((previouslyDeleted && deleted) || + (!previouslyDeleted && merged.conflicts !== 'new_leaf') || + (previouslyDeleted && !deleted && merged.conflicts === 'new_branch'))); + + if (inConflict) { + var err = errors.REV_CONFLICT; + results[i] = err; + return cb(); + } + + docInfo.metadata.rev_tree = merged.tree; + + // recalculate + var winningRev = merge.winningRev(docInfo.metadata); + deleted = exports.isDeleted(docInfo.metadata, winningRev); + + write(docInfo, winningRev, deleted, cb, true, i); +}; + +exports.processDocs = function processDocs(docInfos, api, fetchedDocs, + tx, results, writeDoc, opts) { + + if (!docInfos.length) { + return; + } + + function insertDoc(docInfo, resultsIdx, callback) { + // Cant insert new deleted documents + var winningRev = merge.winningRev(docInfo.metadata); + var deleted = exports.isDeleted(docInfo.metadata, winningRev); + if ('was_delete' in opts && deleted) { + results[resultsIdx] = errors.MISSING_DOC; + return callback(); + } + writeDoc(docInfo, winningRev, deleted, callback, false, resultsIdx); + } + + var newEdits = opts.new_edits; + var idsToDocs = new exports.Map(); + + docInfos.forEach(function (currentDoc, resultsIdx) { + + if (currentDoc._id && exports.isLocalId(currentDoc._id)) { + api[currentDoc._deleted ? '_removeLocal' : '_putLocal']( + currentDoc, {ctx: tx}, function (err, resp) { + if (err) { + results[resultsIdx] = err; + } else { + results[resultsIdx] = {}; + } + }); + return; + } + + var id = currentDoc.metadata.id; + if (idsToDocs.has(id)) { + idsToDocs.get(id).push([currentDoc, resultsIdx]); + } else { + idsToDocs.set(id, [[currentDoc, resultsIdx]]); + } + }); + + // in the case of new_edits, the user can provide multiple docs + // with the same id. these need to be processed sequentially + idsToDocs.forEach(function (docs, id) { + var numDone = 0; + + function docWritten() { + if (++numDone < docs.length) { + nextDoc(); + } + } + function nextDoc() { + var value = docs[numDone]; + var currentDoc = value[0]; + var resultsIdx = value[1]; + + if (fetchedDocs.has(id)) { + exports.updateDoc(fetchedDocs.get(id), currentDoc, results, + resultsIdx, docWritten, writeDoc, newEdits); + } else { + insertDoc(currentDoc, resultsIdx, docWritten); + } + } + nextDoc(); + }); +}; + +exports.preprocessAttachments = function preprocessAttachments( + docInfos, blobType, callback) { + + if (!docInfos.length) { + return callback(); + } + + var docv = 0; + + function parseBase64(data) { + try { + return exports.atob(data); + } catch (e) { + var err = errors.error(errors.BAD_ARG, + "Attachments need to be base64 encoded"); + return {error: err}; + } + } + + function preprocessAttachment(att, callback) { + if (att.stub) { + return callback(); + } + if (typeof att.data === 'string') { + // input is a base64 string + + var asBinary = parseBase64(att.data); + if (asBinary.error) { + return callback(asBinary.error); + } + + att.length = asBinary.length; + if (blobType === 'blob') { + att.data = exports.createBlob([exports.fixBinary(asBinary)], + {type: att.content_type}); + } else if (blobType === 'base64') { + att.data = exports.btoa(asBinary); + } else { // binary + att.data = asBinary; + } + exports.MD5(asBinary).then(function (result) { + att.digest = 'md5-' + result; + callback(); + }); + } else { // input is a blob + exports.readAsBinaryString(att.data, function (binary) { + if (blobType === 'binary') { + att.data = binary; + } else if (blobType === 'base64') { + att.data = exports.btoa(binary); + } + exports.MD5(binary).then(function (result) { + att.digest = 'md5-' + result; + att.length = binary.length; + callback(); + }); + }); + } + } + + var overallErr; + + docInfos.forEach(function (docInfo) { + var attachments = docInfo.data && docInfo.data._attachments ? + Object.keys(docInfo.data._attachments) : []; + var recv = 0; + + if (!attachments.length) { + return done(); + } + + function processedAttachment(err) { + overallErr = err; + recv++; + if (recv === attachments.length) { + done(); + } + } + + for (var key in docInfo.data._attachments) { + if (docInfo.data._attachments.hasOwnProperty(key)) { + preprocessAttachment(docInfo.data._attachments[key], + processedAttachment); + } + } + }); + + function done() { + docv++; + if (docInfos.length === docv) { + if (overallErr) { + callback(overallErr); + } else { + callback(); + } + } + } +}; +}).call(this,_dereq_('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./deps/ajax":9,"./deps/blob":10,"./deps/buffer":28,"./deps/collections":11,"./deps/errors":12,"./deps/md5":13,"./deps/parse-uri":15,"./deps/uuid":17,"./merge":20,"_process":34,"argsarray":27,"bluebird":42,"debug":35,"events":33,"inherits":38,"pouchdb-extend":57}],26:[function(_dereq_,module,exports){ +module.exports = "3.2.0"; + +},{}],27:[function(_dereq_,module,exports){ 'use strict'; module.exports = argsArray; @@ -7604,9 +8434,1305 @@ } }; } -},{}],26:[function(_dereq_,module,exports){ +},{}],28:[function(_dereq_,module,exports){ -},{}],27:[function(_dereq_,module,exports){ +},{}],29:[function(_dereq_,module,exports){ +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org> + * @license MIT + */ + +var base64 = _dereq_('base64-js') +var ieee754 = _dereq_('ieee754') +var isArray = _dereq_('is-array') + +exports.Buffer = Buffer +exports.SlowBuffer = Buffer +exports.INSPECT_MAX_BYTES = 50 +Buffer.poolSize = 8192 // not used by this implementation + +var kMaxLength = 0x3fffffff + +/** + * If `Buffer.TYPED_ARRAY_SUPPORT`: + * === true Use Uint8Array implementation (fastest) + * === false Use Object implementation (most compatible, even IE6) + * + * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, + * Opera 11.6+, iOS 4.2+. + * + * Note: + * + * - Implementation must support adding new properties to `Uint8Array` instances. + * Firefox 4-29 lacked support, fixed in Firefox 30+. + * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. + * + * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. + * + * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of + * incorrect length in some situations. + * + * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they will + * get the Object implementation, which is slower but will work correctly. + */ +Buffer.TYPED_ARRAY_SUPPORT = (function () { + try { + var buf = new ArrayBuffer(0) + var arr = new Uint8Array(buf) + arr.foo = function () { return 42 } + return 42 === arr.foo() && // typed array instances can be augmented + typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` + new Uint8Array(1).subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` + } catch (e) { + return false + } +})() + +/** + * Class: Buffer + * ============= + * + * The Buffer constructor returns instances of `Uint8Array` that are augmented + * with function properties for all the node `Buffer` API functions. We use + * `Uint8Array` so that square bracket notation works as expected -- it returns + * a single octet. + * + * By augmenting the instances, we can avoid modifying the `Uint8Array` + * prototype. + */ +function Buffer (subject, encoding, noZero) { + if (!(this instanceof Buffer)) + return new Buffer(subject, encoding, noZero) + + var type = typeof subject + + // Find the length + var length + if (type === 'number') + length = subject > 0 ? subject >>> 0 : 0 + else if (type === 'string') { + if (encoding === 'base64') + subject = base64clean(subject) + length = Buffer.byteLength(subject, encoding) + } else if (type === 'object' && subject !== null) { // assume object is array-like + if (subject.type === 'Buffer' && isArray(subject.data)) + subject = subject.data + length = +subject.length > 0 ? Math.floor(+subject.length) : 0 + } else + throw new TypeError('must start with number, buffer, array or string') + + if (this.length > kMaxLength) + throw new RangeError('Attempt to allocate Buffer larger than maximum ' + + 'size: 0x' + kMaxLength.toString(16) + ' bytes') + + var buf + if (Buffer.TYPED_ARRAY_SUPPORT) { + // Preferred: Return an augmented `Uint8Array` instance for best performance + buf = Buffer._augment(new Uint8Array(length)) + } else { + // Fallback: Return THIS instance of Buffer (created by `new`) + buf = this + buf.length = length + buf._isBuffer = true + } + + var i + if (Buffer.TYPED_ARRAY_SUPPORT && typeof subject.byteLength === 'number') { + // Speed optimization -- use set if we're copying from a typed array + buf._set(subject) + } else if (isArrayish(subject)) { + // Treat array-ish objects as a byte array + if (Buffer.isBuffer(subject)) { + for (i = 0; i < length; i++) + buf[i] = subject.readUInt8(i) + } else { + for (i = 0; i < length; i++) + buf[i] = ((subject[i] % 256) + 256) % 256 + } + } else if (type === 'string') { + buf.write(subject, 0, encoding) + } else if (type === 'number' && !Buffer.TYPED_ARRAY_SUPPORT && !noZero) { + for (i = 0; i < length; i++) { + buf[i] = 0 + } + } + + return buf +} + +Buffer.isBuffer = function (b) { + return !!(b != null && b._isBuffer) +} + +Buffer.compare = function (a, b) { + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) + throw new TypeError('Arguments must be Buffers') + + var x = a.length + var y = b.length + for (var i = 0, len = Math.min(x, y); i < len && a[i] === b[i]; i++) {} + if (i !== len) { + x = a[i] + y = b[i] + } + if (x < y) return -1 + if (y < x) return 1 + return 0 +} + +Buffer.isEncoding = function (encoding) { + switch (String(encoding).toLowerCase()) { + case 'hex': + case 'utf8': + case 'utf-8': + case 'ascii': + case 'binary': + case 'base64': + case 'raw': + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return true + default: + return false + } +} + +Buffer.concat = function (list, totalLength) { + if (!isArray(list)) throw new TypeError('Usage: Buffer.concat(list[, length])') + + if (list.length === 0) { + return new Buffer(0) + } else if (list.length === 1) { + return list[0] + } + + var i + if (totalLength === undefined) { + totalLength = 0 + for (i = 0; i < list.length; i++) { + totalLength += list[i].length + } + } + + var buf = new Buffer(totalLength) + var pos = 0 + for (i = 0; i < list.length; i++) { + var item = list[i] + item.copy(buf, pos) + pos += item.length + } + return buf +} + +Buffer.byteLength = function (str, encoding) { + var ret + str = str + '' + switch (encoding || 'utf8') { + case 'ascii': + case 'binary': + case 'raw': + ret = str.length + break + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + ret = str.length * 2 + break + case 'hex': + ret = str.length >>> 1 + break + case 'utf8': + case 'utf-8': + ret = utf8ToBytes(str).length + break + case 'base64': + ret = base64ToBytes(str).length + break + default: + ret = str.length + } + return ret +} + +// pre-set for values that may exist in the future +Buffer.prototype.length = undefined +Buffer.prototype.parent = undefined + +// toString(encoding, start=0, end=buffer.length) +Buffer.prototype.toString = function (encoding, start, end) { + var loweredCase = false + + start = start >>> 0 + end = end === undefined || end === Infinity ? this.length : end >>> 0 + + if (!encoding) encoding = 'utf8' + if (start < 0) start = 0 + if (end > this.length) end = this.length + if (end <= start) return '' + + while (true) { + switch (encoding) { + case 'hex': + return hexSlice(this, start, end) + + case 'utf8': + case 'utf-8': + return utf8Slice(this, start, end) + + case 'ascii': + return asciiSlice(this, start, end) + + case 'binary': + return binarySlice(this, start, end) + + case 'base64': + return base64Slice(this, start, end) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return utf16leSlice(this, start, end) + + default: + if (loweredCase) + throw new TypeError('Unknown encoding: ' + encoding) + encoding = (encoding + '').toLowerCase() + loweredCase = true + } + } +} + +Buffer.prototype.equals = function (b) { + if(!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + return Buffer.compare(this, b) === 0 +} + +Buffer.prototype.inspect = function () { + var str = '' + var max = exports.INSPECT_MAX_BYTES + if (this.length > 0) { + str = this.toString('hex', 0, max).match(/.{2}/g).join(' ') + if (this.length > max) + str += ' ... ' + } + return '<Buffer ' + str + '>' +} + +Buffer.prototype.compare = function (b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + return Buffer.compare(this, b) +} + +// `get` will be removed in Node 0.13+ +Buffer.prototype.get = function (offset) { + console.log('.get() is deprecated. Access using array indexes instead.') + return this.readUInt8(offset) +} + +// `set` will be removed in Node 0.13+ +Buffer.prototype.set = function (v, offset) { + console.log('.set() is deprecated. Access using array indexes instead.') + return this.writeUInt8(v, offset) +} + +function hexWrite (buf, string, offset, length) { + offset = Number(offset) || 0 + var remaining = buf.length - offset + if (!length) { + length = remaining + } else { + length = Number(length) + if (length > remaining) { + length = remaining + } + } + + // must be an even number of digits + var strLen = string.length + if (strLen % 2 !== 0) throw new Error('Invalid hex string') + + if (length > strLen / 2) { + length = strLen / 2 + } + for (var i = 0; i < length; i++) { + var byte = parseInt(string.substr(i * 2, 2), 16) + if (isNaN(byte)) throw new Error('Invalid hex string') + buf[offset + i] = byte + } + return i +} + +function utf8Write (buf, string, offset, length) { + var charsWritten = blitBuffer(utf8ToBytes(string), buf, offset, length) + return charsWritten +} + +function asciiWrite (buf, string, offset, length) { + var charsWritten = blitBuffer(asciiToBytes(string), buf, offset, length) + return charsWritten +} + +function binaryWrite (buf, string, offset, length) { + return asciiWrite(buf, string, offset, length) +} + +function base64Write (buf, string, offset, length) { + var charsWritten = blitBuffer(base64ToBytes(string), buf, offset, length) + return charsWritten +} + +function utf16leWrite (buf, string, offset, length) { + var charsWritten = blitBuffer(utf16leToBytes(string), buf, offset, length) + return charsWritten +} + +Buffer.prototype.write = function (string, offset, length, encoding) { + // Support both (string, offset, length, encoding) + // and the legacy (string, encoding, offset, length) + if (isFinite(offset)) { + if (!isFinite(length)) { + encoding = length + length = undefined + } + } else { // legacy + var swap = encoding + encoding = offset + offset = length + length = swap + } + + offset = Number(offset) || 0 + var remaining = this.length - offset + if (!length) { + length = remaining + } else { + length = Number(length) + if (length > remaining) { + length = remaining + } + } + encoding = String(encoding || 'utf8').toLowerCase() + + var ret + switch (encoding) { + case 'hex': + ret = hexWrite(this, string, offset, length) + break + case 'utf8': + case 'utf-8': + ret = utf8Write(this, string, offset, length) + break + case 'ascii': + ret = asciiWrite(this, string, offset, length) + break + case 'binary': + ret = binaryWrite(this, string, offset, length) + break + case 'base64': + ret = base64Write(this, string, offset, length) + break + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + ret = utf16leWrite(this, string, offset, length) + break + default: + throw new TypeError('Unknown encoding: ' + encoding) + } + return ret +} + +Buffer.prototype.toJSON = function () { + return { + type: 'Buffer', + data: Array.prototype.slice.call(this._arr || this, 0) + } +} + +function base64Slice (buf, start, end) { + if (start === 0 && end === buf.length) { + return base64.fromByteArray(buf) + } else { + return base64.fromByteArray(buf.slice(start, end)) + } +} + +function utf8Slice (buf, start, end) { + var res = '' + var tmp = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; i++) { + if (buf[i] <= 0x7F) { + res += decodeUtf8Char(tmp) + String.fromCharCode(buf[i]) + tmp = '' + } else { + tmp += '%' + buf[i].toString(16) + } + } + + return res + decodeUtf8Char(tmp) +} + +function asciiSlice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; i++) { + ret += String.fromCharCode(buf[i]) + } + return ret +} + +function binarySlice (buf, start, end) { + return asciiSlice(buf, start, end) +} + +function hexSlice (buf, start, end) { + var len = buf.length + + if (!start || start < 0) start = 0 + if (!end || end < 0 || end > len) end = len + + var out = '' + for (var i = start; i < end; i++) { + out += toHex(buf[i]) + } + return out +} + +function utf16leSlice (buf, start, end) { + var bytes = buf.slice(start, end) + var res = '' + for (var i = 0; i < bytes.length; i += 2) { + res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256) + } + return res +} + +Buffer.prototype.slice = function (start, end) { + var len = this.length + start = ~~start + end = end === undefined ? len : ~~end + + if (start < 0) { + start += len; + if (start < 0) + start = 0 + } else if (start > len) { + start = len + } + + if (end < 0) { + end += len + if (end < 0) + end = 0 + } else if (end > len) { + end = len + } + + if (end < start) + end = start + + if (Buffer.TYPED_ARRAY_SUPPORT) { + return Buffer._augment(this.subarray(start, end)) + } else { + var sliceLen = end - start + var newBuf = new Buffer(sliceLen, undefined, true) + for (var i = 0; i < sliceLen; i++) { + newBuf[i] = this[i + start] + } + return newBuf + } +} + +/* + * Need to make sure that buffer isn't trying to write out of bounds. + */ +function checkOffset (offset, ext, length) { + if ((offset % 1) !== 0 || offset < 0) + throw new RangeError('offset is not uint') + if (offset + ext > length) + throw new RangeError('Trying to access beyond buffer length') +} + +Buffer.prototype.readUInt8 = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 1, this.length) + return this[offset] +} + +Buffer.prototype.readUInt16LE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 2, this.length) + return this[offset] | (this[offset + 1] << 8) +} + +Buffer.prototype.readUInt16BE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 2, this.length) + return (this[offset] << 8) | this[offset + 1] +} + +Buffer.prototype.readUInt32LE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length) + + return ((this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16)) + + (this[offset + 3] * 0x1000000) +} + +Buffer.prototype.readUInt32BE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length) + + return (this[offset] * 0x1000000) + + ((this[offset + 1] << 16) | + (this[offset + 2] << 8) | + this[offset + 3]) +} + +Buffer.prototype.readInt8 = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 1, this.length) + if (!(this[offset] & 0x80)) + return (this[offset]) + return ((0xff - this[offset] + 1) * -1) +} + +Buffer.prototype.readInt16LE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 2, this.length) + var val = this[offset] | (this[offset + 1] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt16BE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 2, this.length) + var val = this[offset + 1] | (this[offset] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt32LE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length) + + return (this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16) | + (this[offset + 3] << 24) +} + +Buffer.prototype.readInt32BE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length) + + return (this[offset] << 24) | + (this[offset + 1] << 16) | + (this[offset + 2] << 8) | + (this[offset + 3]) +} + +Buffer.prototype.readFloatLE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, true, 23, 4) +} + +Buffer.prototype.readFloatBE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, false, 23, 4) +} + +Buffer.prototype.readDoubleLE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, true, 52, 8) +} + +Buffer.prototype.readDoubleBE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, false, 52, 8) +} + +function checkInt (buf, value, offset, ext, max, min) { + if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance') + if (value > max || value < min) throw new TypeError('value is out of bounds') + if (offset + ext > buf.length) throw new TypeError('index out of range') +} + +Buffer.prototype.writeUInt8 = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 1, 0xff, 0) + if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) + this[offset] = value + return offset + 1 +} + +function objectWriteUInt16 (buf, value, offset, littleEndian) { + if (value < 0) value = 0xffff + value + 1 + for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) { + buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> + (littleEndian ? i : 1 - i) * 8 + } +} + +Buffer.prototype.writeUInt16LE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 2, 0xffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = value + this[offset + 1] = (value >>> 8) + } else objectWriteUInt16(this, value, offset, true) + return offset + 2 +} + +Buffer.prototype.writeUInt16BE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 2, 0xffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 8) + this[offset + 1] = value + } else objectWriteUInt16(this, value, offset, false) + return offset + 2 +} + +function objectWriteUInt32 (buf, value, offset, littleEndian) { + if (value < 0) value = 0xffffffff + value + 1 + for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) { + buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff + } +} + +Buffer.prototype.writeUInt32LE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 4, 0xffffffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset + 3] = (value >>> 24) + this[offset + 2] = (value >>> 16) + this[offset + 1] = (value >>> 8) + this[offset] = value + } else objectWriteUInt32(this, value, offset, true) + return offset + 4 +} + +Buffer.prototype.writeUInt32BE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 4, 0xffffffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = value + } else objectWriteUInt32(this, value, offset, false) + return offset + 4 +} + +Buffer.prototype.writeInt8 = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 1, 0x7f, -0x80) + if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) + if (value < 0) value = 0xff + value + 1 + this[offset] = value + return offset + 1 +} + +Buffer.prototype.writeInt16LE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 2, 0x7fff, -0x8000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = value + this[offset + 1] = (value >>> 8) + } else objectWriteUInt16(this, value, offset, true) + return offset + 2 +} + +Buffer.prototype.writeInt16BE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 2, 0x7fff, -0x8000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 8) + this[offset + 1] = value + } else objectWriteUInt16(this, value, offset, false) + return offset + 2 +} + +Buffer.prototype.writeInt32LE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = value + this[offset + 1] = (value >>> 8) + this[offset + 2] = (value >>> 16) + this[offset + 3] = (value >>> 24) + } else objectWriteUInt32(this, value, offset, true) + return offset + 4 +} + +Buffer.prototype.writeInt32BE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (value < 0) value = 0xffffffff + value + 1 + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = value + } else objectWriteUInt32(this, value, offset, false) + return offset + 4 +} + +function checkIEEE754 (buf, value, offset, ext, max, min) { + if (value > max || value < min) throw new TypeError('value is out of bounds') + if (offset + ext > buf.length) throw new TypeError('index out of range') +} + +function writeFloat (buf, value, offset, littleEndian, noAssert) { + if (!noAssert) + checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) + ieee754.write(buf, value, offset, littleEndian, 23, 4) + return offset + 4 +} + +Buffer.prototype.writeFloatLE = function (value, offset, noAssert) { + return writeFloat(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeFloatBE = function (value, offset, noAssert) { + return writeFloat(this, value, offset, false, noAssert) +} + +function writeDouble (buf, value, offset, littleEndian, noAssert) { + if (!noAssert) + checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) + ieee754.write(buf, value, offset, littleEndian, 52, 8) + return offset + 8 +} + +Buffer.prototype.writeDoubleLE = function (value, offset, noAssert) { + return writeDouble(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeDoubleBE = function (value, offset, noAssert) { + return writeDouble(this, value, offset, false, noAssert) +} + +// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) +Buffer.prototype.copy = function (target, target_start, start, end) { + var source = this + + if (!start) start = 0 + if (!end && end !== 0) end = this.length + if (!target_start) target_start = 0 + + // Copy 0 bytes; we're done + if (end === start) return + if (target.length === 0 || source.length === 0) return + + // Fatal error conditions + if (end < start) throw new TypeError('sourceEnd < sourceStart') + if (target_start < 0 || target_start >= target.length) + throw new TypeError('targetStart out of bounds') + if (start < 0 || start >= source.length) throw new TypeError('sourceStart out of bounds') + if (end < 0 || end > source.length) throw new TypeError('sourceEnd out of bounds') + + // Are we oob? + if (end > this.length) + end = this.length + if (target.length - target_start < end - start) + end = target.length - target_start + start + + var len = end - start + + if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) { + for (var i = 0; i < len; i++) { + target[i + target_start] = this[i + start] + } + } else { + target._set(this.subarray(start, start + len), target_start) + } +} + +// fill(value, start=0, end=buffer.length) +Buffer.prototype.fill = function (value, start, end) { + if (!value) value = 0 + if (!start) start = 0 + if (!end) end = this.length + + if (end < start) throw new TypeError('end < start') + + // Fill 0 bytes; we're done + if (end === start) return + if (this.length === 0) return + + if (start < 0 || start >= this.length) throw new TypeError('start out of bounds') + if (end < 0 || end > this.length) throw new TypeError('end out of bounds') + + var i + if (typeof value === 'number') { + for (i = start; i < end; i++) { + this[i] = value + } + } else { + var bytes = utf8ToBytes(value.toString()) + var len = bytes.length + for (i = start; i < end; i++) { + this[i] = bytes[i % len] + } + } + + return this +} + +/** + * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance. + * Added in Node 0.12. Only available in browsers that support ArrayBuffer. + */ +Buffer.prototype.toArrayBuffer = function () { + if (typeof Uint8Array !== 'undefined') { + if (Buffer.TYPED_ARRAY_SUPPORT) { + return (new Buffer(this)).buffer + } else { + var buf = new Uint8Array(this.length) + for (var i = 0, len = buf.length; i < len; i += 1) { + buf[i] = this[i] + } + return buf.buffer + } + } else { + throw new TypeError('Buffer.toArrayBuffer not supported in this browser') + } +} + +// HELPER FUNCTIONS +// ================ + +var BP = Buffer.prototype + +/** + * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods + */ +Buffer._augment = function (arr) { + arr.constructor = Buffer + arr._isBuffer = true + + // save reference to original Uint8Array get/set methods before overwriting + arr._get = arr.get + arr._set = arr.set + + // deprecated, will be removed in node 0.13+ + arr.get = BP.get + arr.set = BP.set + + arr.write = BP.write + arr.toString = BP.toString + arr.toLocaleString = BP.toString + arr.toJSON = BP.toJSON + arr.equals = BP.equals + arr.compare = BP.compare + arr.copy = BP.copy + arr.slice = BP.slice + arr.readUInt8 = BP.readUInt8 + arr.readUInt16LE = BP.readUInt16LE + arr.readUInt16BE = BP.readUInt16BE + arr.readUInt32LE = BP.readUInt32LE + arr.readUInt32BE = BP.readUInt32BE + arr.readInt8 = BP.readInt8 + arr.readInt16LE = BP.readInt16LE + arr.readInt16BE = BP.readInt16BE + arr.readInt32LE = BP.readInt32LE + arr.readInt32BE = BP.readInt32BE + arr.readFloatLE = BP.readFloatLE + arr.readFloatBE = BP.readFloatBE + arr.readDoubleLE = BP.readDoubleLE + arr.readDoubleBE = BP.readDoubleBE + arr.writeUInt8 = BP.writeUInt8 + arr.writeUInt16LE = BP.writeUInt16LE + arr.writeUInt16BE = BP.writeUInt16BE + arr.writeUInt32LE = BP.writeUInt32LE + arr.writeUInt32BE = BP.writeUInt32BE + arr.writeInt8 = BP.writeInt8 + arr.writeInt16LE = BP.writeInt16LE + arr.writeInt16BE = BP.writeInt16BE + arr.writeInt32LE = BP.writeInt32LE + arr.writeInt32BE = BP.writeInt32BE + arr.writeFloatLE = BP.writeFloatLE + arr.writeFloatBE = BP.writeFloatBE + arr.writeDoubleLE = BP.writeDoubleLE + arr.writeDoubleBE = BP.writeDoubleBE + arr.fill = BP.fill + arr.inspect = BP.inspect + arr.toArrayBuffer = BP.toArrayBuffer + + return arr +} + +var INVALID_BASE64_RE = /[^+\/0-9A-z]/g + +function base64clean (str) { + // Node strips out invalid characters like \n and \t from the string, base64-js does not + str = stringtrim(str).replace(INVALID_BASE64_RE, '') + // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not + while (str.length % 4 !== 0) { + str = str + '=' + } + return str +} + +function stringtrim (str) { + if (str.trim) return str.trim() + return str.replace(/^\s+|\s+$/g, '') +} + +function isArrayish (subject) { + return isArray(subject) || Buffer.isBuffer(subject) || + subject && typeof subject === 'object' && + typeof subject.length === 'number' +} + +function toHex (n) { + if (n < 16) return '0' + n.toString(16) + return n.toString(16) +} + +function utf8ToBytes (str) { + var byteArray = [] + for (var i = 0; i < str.length; i++) { + var b = str.charCodeAt(i) + if (b <= 0x7F) { + byteArray.push(b) + } else { + var start = i + if (b >= 0xD800 && b <= 0xDFFF) i++ + var h = encodeURIComponent(str.slice(start, i+1)).substr(1).split('%') + for (var j = 0; j < h.length; j++) { + byteArray.push(parseInt(h[j], 16)) + } + } + } + return byteArray +} + +function asciiToBytes (str) { + var byteArray = [] + for (var i = 0; i < str.length; i++) { + // Node's code seems to be doing this and not & 0x7F.. + byteArray.push(str.charCodeAt(i) & 0xFF) + } + return byteArray +} + +function utf16leToBytes (str) { + var c, hi, lo + var byteArray = [] + for (var i = 0; i < str.length; i++) { + c = str.charCodeAt(i) + hi = c >> 8 + lo = c % 256 + byteArray.push(lo) + byteArray.push(hi) + } + + return byteArray +} + +function base64ToBytes (str) { + return base64.toByteArray(str) +} + +function blitBuffer (src, dst, offset, length) { + for (var i = 0; i < length; i++) { + if ((i + offset >= dst.length) || (i >= src.length)) + break + dst[i + offset] = src[i] + } + return i +} + +function decodeUtf8Char (str) { + try { + return decodeURIComponent(str) + } catch (err) { + return String.fromCharCode(0xFFFD) // UTF 8 invalid char + } +} + +},{"base64-js":30,"ieee754":31,"is-array":32}],30:[function(_dereq_,module,exports){ +var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + +;(function (exports) { + 'use strict'; + + var Arr = (typeof Uint8Array !== 'undefined') + ? Uint8Array + : Array + + var PLUS = '+'.charCodeAt(0) + var SLASH = '/'.charCodeAt(0) + var NUMBER = '0'.charCodeAt(0) + var LOWER = 'a'.charCodeAt(0) + var UPPER = 'A'.charCodeAt(0) + + function decode (elt) { + var code = elt.charCodeAt(0) + if (code === PLUS) + return 62 // '+' + if (code === SLASH) + return 63 // '/' + if (code < NUMBER) + return -1 //no match + if (code < NUMBER + 10) + return code - NUMBER + 26 + 26 + if (code < UPPER + 26) + return code - UPPER + if (code < LOWER + 26) + return code - LOWER + 26 + } + + function b64ToByteArray (b64) { + var i, j, l, tmp, placeHolders, arr + + if (b64.length % 4 > 0) { + throw new Error('Invalid string. Length must be a multiple of 4') + } + + // the number of equal signs (place holders) + // if there are two placeholders, than the two characters before it + // represent one byte + // if there is only one, then the three characters before it represent 2 bytes + // this is just a cheap hack to not do indexOf twice + var len = b64.length + placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0 + + // base64 is 4/3 + up to two characters of the original data + arr = new Arr(b64.length * 3 / 4 - placeHolders) + + // if there are placeholders, only get up to the last complete 4 chars + l = placeHolders > 0 ? b64.length - 4 : b64.length + + var L = 0 + + function push (v) { + arr[L++] = v + } + + for (i = 0, j = 0; i < l; i += 4, j += 3) { + tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3)) + push((tmp & 0xFF0000) >> 16) + push((tmp & 0xFF00) >> 8) + push(tmp & 0xFF) + } + + if (placeHolders === 2) { + tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4) + push(tmp & 0xFF) + } else if (placeHolders === 1) { + tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2) + push((tmp >> 8) & 0xFF) + push(tmp & 0xFF) + } + + return arr + } + + function uint8ToBase64 (uint8) { + var i, + extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes + output = "", + temp, length + + function encode (num) { + return lookup.charAt(num) + } + + function tripletToBase64 (num) { + return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F) + } + + // go through the array every three bytes, we'll deal with trailing stuff later + for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) { + temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) + output += tripletToBase64(temp) + } + + // pad the end with zeros, but make sure to not forget the extra bytes + switch (extraBytes) { + case 1: + temp = uint8[uint8.length - 1] + output += encode(temp >> 2) + output += encode((temp << 4) & 0x3F) + output += '==' + break + case 2: + temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]) + output += encode(temp >> 10) + output += encode((temp >> 4) & 0x3F) + output += encode((temp << 2) & 0x3F) + output += '=' + break + } + + return output + } + + exports.toByteArray = b64ToByteArray + exports.fromByteArray = uint8ToBase64 +}(typeof exports === 'undefined' ? (this.base64js = {}) : exports)) + +},{}],31:[function(_dereq_,module,exports){ +exports.read = function(buffer, offset, isLE, mLen, nBytes) { + var e, m, + eLen = nBytes * 8 - mLen - 1, + eMax = (1 << eLen) - 1, + eBias = eMax >> 1, + nBits = -7, + i = isLE ? (nBytes - 1) : 0, + d = isLE ? -1 : 1, + s = buffer[offset + i]; + + i += d; + + e = s & ((1 << (-nBits)) - 1); + s >>= (-nBits); + nBits += eLen; + for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8); + + m = e & ((1 << (-nBits)) - 1); + e >>= (-nBits); + nBits += mLen; + for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8); + + if (e === 0) { + e = 1 - eBias; + } else if (e === eMax) { + return m ? NaN : ((s ? -1 : 1) * Infinity); + } else { + m = m + Math.pow(2, mLen); + e = e - eBias; + } + return (s ? -1 : 1) * m * Math.pow(2, e - mLen); +}; + +exports.write = function(buffer, value, offset, isLE, mLen, nBytes) { + var e, m, c, + eLen = nBytes * 8 - mLen - 1, + eMax = (1 << eLen) - 1, + eBias = eMax >> 1, + rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0), + i = isLE ? 0 : (nBytes - 1), + d = isLE ? 1 : -1, + s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0; + + value = Math.abs(value); + + if (isNaN(value) || value === Infinity) { + m = isNaN(value) ? 1 : 0; + e = eMax; + } else { + e = Math.floor(Math.log(value) / Math.LN2); + if (value * (c = Math.pow(2, -e)) < 1) { + e--; + c *= 2; + } + if (e + eBias >= 1) { + value += rt / c; + } else { + value += rt * Math.pow(2, 1 - eBias); + } + if (value * c >= 2) { + e++; + c /= 2; + } + + if (e + eBias >= eMax) { + m = 0; + e = eMax; + } else if (e + eBias >= 1) { + m = (value * c - 1) * Math.pow(2, mLen); + e = e + eBias; + } else { + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); + e = 0; + } + } + + for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8); + + e = (e << mLen) | m; + eLen += mLen; + for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8); + + buffer[offset + i - d] |= s * 128; +}; + +},{}],32:[function(_dereq_,module,exports){ + +/** + * isArray + */ + +var isArray = Array.isArray; + +/** + * toString + */ + +var str = Object.prototype.toString; + +/** + * Whether or not the given `val` + * is an array. + * + * example: + * + * isArray([]); + * // > true + * isArray(arguments); + * // > false + * isArray(''); + * // > false + * + * @param {mixed} val + * @return {bool} + */ + +module.exports = isArray || function (val) { + return !! val && '[object Array]' == str.call(val); +}; + +},{}],33:[function(_dereq_,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -7909,7 +10035,7 @@ return arg === void 0; } -},{}],28:[function(_dereq_,module,exports){ +},{}],34:[function(_dereq_,module,exports){ // shim for using process in browser var process = module.exports = {}; @@ -7917,6 +10043,8 @@ process.nextTick = (function () { var canSetImmediate = typeof window !== 'undefined' && window.setImmediate; + var canMutationObserver = typeof window !== 'undefined' + && window.MutationObserver; var canPost = typeof window !== 'undefined' && window.postMessage && window.addEventListener ; @@ -7925,8 +10053,29 @@ return function (f) { return window.setImmediate(f) }; } + var queue = []; + + if (canMutationObserver) { + var hiddenDiv = document.createElement("div"); + var observer = new MutationObserver(function () { + var queueList = queue.slice(); + queue.length = 0; + queueList.forEach(function (fn) { + fn(); + }); + }); + + observer.observe(hiddenDiv, { attributes: true }); + + return function nextTick(fn) { + if (!queue.length) { + hiddenDiv.setAttribute('yes', 'no'); + } + queue.push(fn); + }; + } + if (canPost) { - var queue = []; window.addEventListener('message', function (ev) { var source = ev.source; if ((source === window || source === null) && ev.data === 'process-tick') { @@ -7954,9 +10103,19 @@ process.env = {}; process.argv = []; +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; + process.binding = function (name) { throw new Error('process.binding is not supported'); -} +}; // TODO(shtylman) process.cwd = function () { return '/' }; @@ -7964,7 +10123,468 @@ throw new Error('process.chdir is not supported'); }; -},{}],29:[function(_dereq_,module,exports){ +},{}],35:[function(_dereq_,module,exports){ + +/** + * This is the web browser implementation of `debug()`. + * + * Expose `debug()` as the module. + */ + +exports = module.exports = _dereq_('./debug'); +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; + +/** + * Colors. + */ + +exports.colors = [ + 'lightseagreen', + 'forestgreen', + 'goldenrod', + 'dodgerblue', + 'darkorchid', + 'crimson' +]; + +/** + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors + */ + +function useColors() { + // is webkit? http://stackoverflow.com/a/16459606/376773 + return ('WebkitAppearance' in document.documentElement.style) || + // is firebug? http://stackoverflow.com/a/398120/376773 + (window.console && (console.firebug || (console.exception && console.table))) || + // is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + (navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31); +} + +/** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ + +exports.formatters.j = function(v) { + return JSON.stringify(v); +}; + + +/** + * Colorize log arguments if enabled. + * + * @api public + */ + +function formatArgs() { + var args = arguments; + var useColors = this.useColors; + + args[0] = (useColors ? '%c' : '') + + this.namespace + + (useColors ? ' %c' : ' ') + + args[0] + + (useColors ? '%c ' : ' ') + + '+' + exports.humanize(this.diff); + + if (!useColors) return args; + + var c = 'color: ' + this.color; + args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1)); + + // the final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + var index = 0; + var lastC = 0; + args[0].replace(/%[a-z%]/g, function(match) { + if ('%' === match) return; + index++; + if ('%c' === match) { + // we only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); + + args.splice(lastC, 0, c); + return args; +} + +/** + * Invokes `console.log()` when available. + * No-op when `console.log` is not a "function". + * + * @api public + */ + +function log() { + // This hackery is required for IE8, + // where the `console.log` function doesn't have 'apply' + return 'object' == typeof console + && 'function' == typeof console.log + && Function.prototype.apply.call(console.log, console, arguments); +} + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ + +function save(namespaces) { + try { + if (null == namespaces) { + localStorage.removeItem('debug'); + } else { + localStorage.debug = namespaces; + } + } catch(e) {} +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + +function load() { + var r; + try { + r = localStorage.debug; + } catch(e) {} + return r; +} + +/** + * Enable namespaces listed in `localStorage.debug` initially. + */ + +exports.enable(load()); + +},{"./debug":36}],36:[function(_dereq_,module,exports){ + +/** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + * + * Expose `debug()` as the module. + */ + +exports = module.exports = debug; +exports.coerce = coerce; +exports.disable = disable; +exports.enable = enable; +exports.enabled = enabled; +exports.humanize = _dereq_('ms'); + +/** + * The currently active debug mode names, and names to skip. + */ + +exports.names = []; +exports.skips = []; + +/** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lowercased letter, i.e. "n". + */ + +exports.formatters = {}; + +/** + * Previously assigned color. + */ + +var prevColor = 0; + +/** + * Previous log timestamp. + */ + +var prevTime; + +/** + * Select a color. + * + * @return {Number} + * @api private + */ + +function selectColor() { + return exports.colors[prevColor++ % exports.colors.length]; +} + +/** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ + +function debug(namespace) { + + // define the `disabled` version + function disabled() { + } + disabled.enabled = false; + + // define the `enabled` version + function enabled() { + + var self = enabled; + + // set `diff` timestamp + var curr = +new Date(); + var ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; + + // add the `color` if not set + if (null == self.useColors) self.useColors = exports.useColors(); + if (null == self.color && self.useColors) self.color = selectColor(); + + var args = Array.prototype.slice.call(arguments); + + args[0] = exports.coerce(args[0]); + + if ('string' !== typeof args[0]) { + // anything else let's inspect with %o + args = ['%o'].concat(args); + } + + // apply any `formatters` transformations + var index = 0; + args[0] = args[0].replace(/%([a-z%])/g, function(match, format) { + // if we encounter an escaped % then don't increase the array index + if (match === '%') return match; + index++; + var formatter = exports.formatters[format]; + if ('function' === typeof formatter) { + var val = args[index]; + match = formatter.call(self, val); + + // now we need to remove `args[index]` since it's inlined in the `format` + args.splice(index, 1); + index--; + } + return match; + }); + + if ('function' === typeof exports.formatArgs) { + args = exports.formatArgs.apply(self, args); + } + var logFn = enabled.log || exports.log || console.log.bind(console); + logFn.apply(self, args); + } + enabled.enabled = true; + + var fn = exports.enabled(namespace) ? enabled : disabled; + + fn.namespace = namespace; + + return fn; +} + +/** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ + +function enable(namespaces) { + exports.save(namespaces); + + var split = (namespaces || '').split(/[\s,]+/); + var len = split.length; + + for (var i = 0; i < len; i++) { + if (!split[i]) continue; // ignore empty strings + namespaces = split[i].replace(/\*/g, '.*?'); + if (namespaces[0] === '-') { + exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); + } else { + exports.names.push(new RegExp('^' + namespaces + '$')); + } + } +} + +/** + * Disable debug output. + * + * @api public + */ + +function disable() { + exports.enable(''); +} + +/** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + +function enabled(name) { + var i, len; + for (i = 0, len = exports.skips.length; i < len; i++) { + if (exports.skips[i].test(name)) { + return false; + } + } + for (i = 0, len = exports.names.length; i < len; i++) { + if (exports.names[i].test(name)) { + return true; + } + } + return false; +} + +/** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + +function coerce(val) { + if (val instanceof Error) return val.stack || val.message; + return val; +} + +},{"ms":37}],37:[function(_dereq_,module,exports){ +/** + * Helpers. + */ + +var s = 1000; +var m = s * 60; +var h = m * 60; +var d = h * 24; +var y = d * 365.25; + +/** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} options + * @return {String|Number} + * @api public + */ + +module.exports = function(val, options){ + options = options || {}; + if ('string' == typeof val) return parse(val); + return options.long + ? long(val) + : short(val); +}; + +/** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function parse(str) { + var match = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str); + if (!match) return; + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'y': + return n * y; + case 'days': + case 'day': + case 'd': + return n * d; + case 'hours': + case 'hour': + case 'h': + return n * h; + case 'minutes': + case 'minute': + case 'm': + return n * m; + case 'seconds': + case 'second': + case 's': + return n * s; + case 'ms': + return n; + } +} + +/** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function short(ms) { + if (ms >= d) return Math.round(ms / d) + 'd'; + if (ms >= h) return Math.round(ms / h) + 'h'; + if (ms >= m) return Math.round(ms / m) + 'm'; + if (ms >= s) return Math.round(ms / s) + 's'; + return ms + 'ms'; +} + +/** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function long(ms) { + return plural(ms, d, 'day') + || plural(ms, h, 'hour') + || plural(ms, m, 'minute') + || plural(ms, s, 'second') + || ms + ' ms'; +} + +/** + * Pluralization helper. + */ + +function plural(ms, n, name) { + if (ms < n) return; + if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name; + return Math.ceil(ms / n) + ' ' + name + 's'; +} + +},{}],38:[function(_dereq_,module,exports){ if (typeof Object.create === 'function') { // implementation from standard node.js 'util' module module.exports = function inherits(ctor, superCtor) { @@ -7989,13 +10609,13 @@ } } -},{}],30:[function(_dereq_,module,exports){ +},{}],39:[function(_dereq_,module,exports){ 'use strict'; module.exports = INTERNAL; function INTERNAL() {} -},{}],31:[function(_dereq_,module,exports){ +},{}],40:[function(_dereq_,module,exports){ 'use strict'; var Promise = _dereq_('./promise'); var reject = _dereq_('./reject'); @@ -8039,7 +10659,7 @@ } } } -},{"./INTERNAL":30,"./handlers":32,"./promise":34,"./reject":37,"./resolve":38}],32:[function(_dereq_,module,exports){ +},{"./INTERNAL":39,"./handlers":41,"./promise":43,"./reject":46,"./resolve":47}],41:[function(_dereq_,module,exports){ 'use strict'; var tryCatch = _dereq_('./tryCatch'); var resolveThenable = _dereq_('./resolveThenable'); @@ -8085,14 +10705,14 @@ }; } } -},{"./resolveThenable":39,"./states":40,"./tryCatch":41}],33:[function(_dereq_,module,exports){ +},{"./resolveThenable":48,"./states":49,"./tryCatch":50}],42:[function(_dereq_,module,exports){ module.exports = exports = _dereq_('./promise'); exports.resolve = _dereq_('./resolve'); exports.reject = _dereq_('./reject'); exports.all = _dereq_('./all'); exports.race = _dereq_('./race'); -},{"./all":31,"./promise":34,"./race":36,"./reject":37,"./resolve":38}],34:[function(_dereq_,module,exports){ +},{"./all":40,"./promise":43,"./race":45,"./reject":46,"./resolve":47}],43:[function(_dereq_,module,exports){ 'use strict'; var unwrap = _dereq_('./unwrap'); @@ -8138,7 +10758,7 @@ return promise; }; -},{"./INTERNAL":30,"./queueItem":35,"./resolveThenable":39,"./states":40,"./unwrap":42}],35:[function(_dereq_,module,exports){ +},{"./INTERNAL":39,"./queueItem":44,"./resolveThenable":48,"./states":49,"./unwrap":51}],44:[function(_dereq_,module,exports){ 'use strict'; var handlers = _dereq_('./handlers'); var unwrap = _dereq_('./unwrap'); @@ -8167,7 +10787,7 @@ QueueItem.prototype.otherCallRejected = function (value) { unwrap(this.promise, this.onRejected, value); }; -},{"./handlers":32,"./unwrap":42}],36:[function(_dereq_,module,exports){ +},{"./handlers":41,"./unwrap":51}],45:[function(_dereq_,module,exports){ 'use strict'; var Promise = _dereq_('./promise'); var reject = _dereq_('./reject'); @@ -8208,7 +10828,7 @@ }); } } -},{"./INTERNAL":30,"./handlers":32,"./promise":34,"./reject":37,"./resolve":38}],37:[function(_dereq_,module,exports){ +},{"./INTERNAL":39,"./handlers":41,"./promise":43,"./reject":46,"./resolve":47}],46:[function(_dereq_,module,exports){ 'use strict'; var Promise = _dereq_('./promise'); @@ -8220,7 +10840,7 @@ var promise = new Promise(INTERNAL); return handlers.reject(promise, reason); } -},{"./INTERNAL":30,"./handlers":32,"./promise":34}],38:[function(_dereq_,module,exports){ +},{"./INTERNAL":39,"./handlers":41,"./promise":43}],47:[function(_dereq_,module,exports){ 'use strict'; var Promise = _dereq_('./promise'); @@ -8255,7 +10875,7 @@ return EMPTYSTRING; } } -},{"./INTERNAL":30,"./handlers":32,"./promise":34}],39:[function(_dereq_,module,exports){ +},{"./INTERNAL":39,"./handlers":41,"./promise":43}],48:[function(_dereq_,module,exports){ 'use strict'; var handlers = _dereq_('./handlers'); var tryCatch = _dereq_('./tryCatch'); @@ -8288,13 +10908,13 @@ } } exports.safely = safelyResolveThenable; -},{"./handlers":32,"./tryCatch":41}],40:[function(_dereq_,module,exports){ +},{"./handlers":41,"./tryCatch":50}],49:[function(_dereq_,module,exports){ // Lazy man's symbols for states exports.REJECTED = ['REJECTED']; exports.FULFILLED = ['FULFILLED']; exports.PENDING = ['PENDING']; -},{}],41:[function(_dereq_,module,exports){ +},{}],50:[function(_dereq_,module,exports){ 'use strict'; module.exports = tryCatch; @@ -8310,7 +10930,7 @@ } return out; } -},{}],42:[function(_dereq_,module,exports){ +},{}],51:[function(_dereq_,module,exports){ 'use strict'; var immediate = _dereq_('immediate'); @@ -8332,7 +10952,7 @@ } }); } -},{"./handlers":32,"immediate":43}],43:[function(_dereq_,module,exports){ +},{"./handlers":41,"immediate":52}],52:[function(_dereq_,module,exports){ 'use strict'; var types = [ _dereq_('./nextTick'), @@ -8343,7 +10963,8 @@ ]; var draining; var queue = []; -function drainQueue() { +//named nextTick for less confusing stack traces +function nextTick() { draining = true; var i, oldQueue; var len = queue.length; @@ -8363,7 +10984,7 @@ var len = types.length; while (++ i < len) { if (types[i] && types[i].test && types[i].test()) { - scheduleDrain = types[i].install(drainQueue); + scheduleDrain = types[i].install(nextTick); break; } } @@ -8373,7 +10994,7 @@ scheduleDrain(); } } -},{"./messageChannel":44,"./mutation.js":45,"./nextTick":26,"./stateChange":46,"./timeout":47}],44:[function(_dereq_,module,exports){ +},{"./messageChannel":53,"./mutation.js":54,"./nextTick":28,"./stateChange":55,"./timeout":56}],53:[function(_dereq_,module,exports){ (function (global){ 'use strict'; @@ -8393,8 +11014,8 @@ channel.port2.postMessage(0); }; }; -}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],45:[function(_dereq_,module,exports){ +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],54:[function(_dereq_,module,exports){ (function (global){ 'use strict'; //based off rsvp https://github.com/tildeio/rsvp.js @@ -8418,8 +11039,8 @@ element.data = (called = ++called % 2); }; }; -}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],46:[function(_dereq_,module,exports){ +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],55:[function(_dereq_,module,exports){ (function (global){ 'use strict'; @@ -8445,8 +11066,8 @@ return handle; }; }; -}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],47:[function(_dereq_,module,exports){ +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],56:[function(_dereq_,module,exports){ 'use strict'; exports.test = function () { return true; @@ -8457,7 +11078,7 @@ setTimeout(t, 0); }; }; -},{}],48:[function(_dereq_,module,exports){ +},{}],57:[function(_dereq_,module,exports){ "use strict"; // Extends method @@ -8638,7 +11259,7 @@ -},{}],49:[function(_dereq_,module,exports){ +},{}],58:[function(_dereq_,module,exports){ 'use strict'; var upsert = _dereq_('./upsert'); @@ -8668,7 +11289,7 @@ var depDbName = info.db_name + '-mrview-' + (temporary ? 'temp' : utils.MD5(viewSignature)); - // save the view name in the source PouchDBVersion306 so it can be cleaned up if necessary + // save the view name in the source PouchDB so it can be cleaned up if necessary // (e.g. when the _design doc is deleted, remove all associated view data) function diffFunction(doc) { doc.views = doc.views || {}; @@ -8717,7 +11338,7 @@ }); }; -},{"./upsert":55,"./utils":56}],50:[function(_dereq_,module,exports){ +},{"./upsert":64,"./utils":65}],59:[function(_dereq_,module,exports){ 'use strict'; module.exports = function (func, emit, sum, log, isArray, toJSON) { @@ -8725,7 +11346,7 @@ return eval("'use strict'; (" + func.replace(/;\s*$/, "") + ");"); }; -},{}],51:[function(_dereq_,module,exports){ +},{}],60:[function(_dereq_,module,exports){ (function (process){ 'use strict'; @@ -8783,6 +11404,14 @@ return results; } +function rowToDocId(row) { + var val = row.value; + // Users can explicitly specify a joined doc _id, or it + // defaults to the doc _id that emitted the key/value. + var docId = (val && typeof val === 'object' && val._id) || row.id; + return docId; +} + function createBuiltInError(name) { var error = new Error('builtin ' + name + ' function requires map values to be numbers' + @@ -8903,12 +11532,14 @@ // not the final result of map and reduce. addHttpParam('reduce', opts, params); addHttpParam('include_docs', opts, params); + addHttpParam('attachments', opts, params); addHttpParam('limit', opts, params); addHttpParam('descending', opts, params); addHttpParam('group', opts, params); addHttpParam('group_level', opts, params); addHttpParam('skip', opts, params); addHttpParam('stale', opts, params); + addHttpParam('conflicts', opts, params); addHttpParam('startkey', opts, params, true); addHttpParam('endkey', opts, params, true); addHttpParam('inclusive_end', opts, params); @@ -9227,7 +11858,7 @@ totalRows = res.total_rows; return res.rows.map(function (result) { - // implicit migration - in older versions of PouchDBVersion306, + // implicit migration - in older versions of PouchDB, // we explicitly stored the doc as {id: ..., key: ..., value: ...} // this is tested in a migration test /* istanbul ignore next */ @@ -9252,32 +11883,43 @@ }); } - function onMapResultsReady(results) { - var res; + function onMapResultsReady(rows) { + var finalResults; if (shouldReduce) { - res = reduceView(view, results, opts); + finalResults = reduceView(view, rows, opts); } else { - res = { + finalResults = { total_rows: totalRows, offset: skip, - rows: results + rows: rows }; } if (opts.include_docs) { - var getDocsPromises = results.map(function (row) { - var val = row.value; - var docId = (val && typeof val === 'object' && val._id) || row.id; - return view.sourceDB.get(docId).then(function (joinedDoc) { - row.doc = joinedDoc; - }, function () { - // document error = don't join + var docIds = utils.uniq(rows.map(rowToDocId)); + + return view.sourceDB.allDocs({ + keys: docIds, + include_docs: true, + conflicts: opts.conflicts, + attachments: opts.attachments + }).then(function (allDocsRes) { + var docIdsToDocs = {}; + allDocsRes.rows.forEach(function (row) { + if (row.doc) { + docIdsToDocs['$' + row.id] = row.doc; + } }); - }); - return Promise.all(getDocsPromises).then(function () { - return res; + rows.forEach(function (row) { + var docId = rowToDocId(row); + var doc = docIdsToDocs['$' + docId]; + if (doc) { + row.doc = doc; + } + }); + return finalResults; }); } else { - return res; + return finalResults; } } @@ -9364,7 +12006,7 @@ var fullViewName = ddocName + '/' + viewName; /* istanbul ignore if */ if (!metaDoc.views[fullViewName]) { - // new format, without slashes, to support PouchDBVersion306 2.2.0 + // new format, without slashes, to support PouchDB 2.2.0 // migration test in pouchdb's browser.migration.js verifies this fullViewName = viewName; } @@ -9506,8 +12148,8 @@ utils.inherits(NotFoundError, Error); -}).call(this,_dereq_("/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js")) -},{"./create-view":49,"./evalfunc":50,"./taskqueue":54,"./utils":56,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":28,"pouchdb-collate":52}],52:[function(_dereq_,module,exports){ +}).call(this,_dereq_('_process')) +},{"./create-view":58,"./evalfunc":59,"./taskqueue":63,"./utils":65,"_process":34,"pouchdb-collate":61}],61:[function(_dereq_,module,exports){ 'use strict'; var MIN_MAGNITUDE = -324; // verified by -Number.MIN_VALUE @@ -9862,7 +12504,7 @@ return result; } -},{"./utils":53}],53:[function(_dereq_,module,exports){ +},{"./utils":62}],62:[function(_dereq_,module,exports){ 'use strict'; function pad(str, padWith, upToLength) { @@ -9933,7 +12575,7 @@ return result; }; -},{}],54:[function(_dereq_,module,exports){ +},{}],63:[function(_dereq_,module,exports){ 'use strict'; /* * Simple task queue to sequentialize actions. Assumes callbacks will eventually fire (once). @@ -9958,7 +12600,7 @@ module.exports = TaskQueue; -},{"./utils":56}],55:[function(_dereq_,module,exports){ +},{"./utils":65}],64:[function(_dereq_,module,exports){ 'use strict'; var Promise = _dereq_('./utils').Promise; @@ -10001,7 +12643,7 @@ module.exports = upsert; -},{"./utils":56}],56:[function(_dereq_,module,exports){ +},{"./utils":65}],65:[function(_dereq_,module,exports){ (function (process,global){ 'use strict'; /* istanbul ignore if */ @@ -10010,14 +12652,6 @@ } else { exports.Promise = _dereq_('lie'); } -// uniquify a list, similar to underscore's _.uniq -exports.uniq = function (arr) { - var map = {}; - arr.forEach(function (element) { - map[element] = true; - }); - return Object.keys(map); -}; exports.inherits = _dereq_('inherits'); exports.extend = _dereq_('pouchdb-extend'); @@ -10080,6 +12714,24 @@ }; }; +// uniq an array of strings, order not guaranteed +// similar to underscore/lodash _.uniq +exports.uniq = function (arr) { + var map = {}; + + for (var i = 0, len = arr.length; i < len; i++) { + map['$' + arr[i]] = true; + } + + var keys = Object.keys(map); + var output = new Array(keys.length); + + for (i = 0, len = keys.length; i < len; i++) { + output[i] = keys[i].substring(1); + } + return output; +}; + var crypto = _dereq_('crypto'); var Md5 = _dereq_('spark-md5'); @@ -10091,8 +12743,8 @@ return Md5.hash(string); } }; -}).call(this,_dereq_("/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":28,"argsarray":25,"crypto":26,"inherits":29,"lie":33,"pouchdb-extend":48,"spark-md5":57}],57:[function(_dereq_,module,exports){ +}).call(this,_dereq_('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"_process":34,"argsarray":27,"crypto":28,"inherits":38,"lie":42,"pouchdb-extend":57,"spark-md5":66}],66:[function(_dereq_,module,exports){ /*jshint bitwise:false*/ /*global unescape*/ @@ -10693,7 +13345,7 @@ return SparkMD5; })); -},{}],58:[function(_dereq_,module,exports){ +},{}],67:[function(_dereq_,module,exports){ 'use strict'; /** @@ -10868,6 +13520,35 @@ } }; -},{}]},{},[17]) -(17) -}); \ No newline at end of file +},{}],68:[function(_dereq_,module,exports){ +(function (process){ +"use strict"; + +var PouchDB = _dereq_('./setup'); + +module.exports = PouchDB; + +PouchDB.ajax = _dereq_('./deps/ajax'); +PouchDB.extend = _dereq_('pouchdb-extend'); +PouchDB.utils = _dereq_('./utils'); +PouchDB.Errors = _dereq_('./deps/errors'); +PouchDB.replicate = _dereq_('./replicate').replicate; +PouchDB.sync = _dereq_('./sync'); +PouchDB.version = _dereq_('./version'); +var httpAdapter = _dereq_('./adapters/http'); +PouchDB.adapter('http', httpAdapter); +PouchDB.adapter('https', httpAdapter); + +PouchDB.adapter('idb', _dereq_('./adapters/idb')); +PouchDB.adapter('websql', _dereq_('./adapters/websql')); +PouchDB.plugin(_dereq_('pouchdb-mapreduce')); + +if (!process.browser) { + var ldbAdapter = _dereq_('./adapters/leveldb'); + PouchDB.adapter('ldb', ldbAdapter); + PouchDB.adapter('leveldb', ldbAdapter); +} + +}).call(this,_dereq_('_process')) +},{"./adapters/http":2,"./adapters/idb":3,"./adapters/leveldb":28,"./adapters/websql":5,"./deps/ajax":9,"./deps/errors":12,"./replicate":21,"./setup":22,"./sync":23,"./utils":25,"./version":26,"_process":34,"pouchdb-extend":57,"pouchdb-mapreduce":60}]},{},[68])(68) +});
diff --git a/dist/pouchdb.localstorage.js b/dist/pouchdb.localstorage.js new file mode 100644 index 0000000..3f2b1d4 --- /dev/null +++ b/dist/pouchdb.localstorage.js
@@ -0,0 +1,16414 @@ +// PouchDB localStorage plugin 3.2.0 +// Based on localstorage-down: https://github.com/No9/localstorage-down +// +// (c) 2012-2014 Dale Harvey and the PouchDB team +// PouchDB may be freely distributed under the Apache license, version 2.0. +// For all details and documentation: +// http://pouchdb.com +require=(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<r.length;o++)s(r[o]);return s})({"./lib/deps/migrate":[function(_dereq_,module,exports){ +(function (process){ +'use strict'; +// LevelAlt doesn't need the pre-2.2.0 LevelDB-specific migrations +exports.toSublevel = function (name, db, callback) { + process.nextTick(function () { + callback(); + }); +}; + +exports.localAndMetaStores = function (db, stores, callback) { + process.nextTick(function () { + callback(); + }); +}; + +}).call(this,_dereq_('_process')) +},{"_process":24}],1:[function(_dereq_,module,exports){ +(function (process,Buffer){ +'use strict'; + +var levelup = _dereq_('levelup'); +var originalLeveldown = _dereq_('leveldown'); +var sublevel = _dereq_('level-sublevel'); +var through = _dereq_('through2').obj; + +var errors = _dereq_('../deps/errors'); +var merge = _dereq_('../merge'); +var utils = _dereq_('../utils'); +var migrate = _dereq_('../deps/migrate'); +var vuvuzela = _dereq_('vuvuzela'); +var Deque = _dereq_("double-ended-queue"); + +var DOC_STORE = 'document-store'; +var BY_SEQ_STORE = 'by-sequence'; +var ATTACHMENT_STORE = 'attach-store'; +var BINARY_STORE = 'attach-binary-store'; +var LOCAL_STORE = 'local-store'; +var META_STORE = 'meta-store'; +var BATCH_SIZE = 50; + +// leveldb barks if we try to open a db multiple times +// so we cache opened connections here for initstore() +var dbStores = new utils.Map(); + +// store the value of update_seq in the by-sequence store the key name will +// never conflict, since the keys in the by-sequence store are integers +var UPDATE_SEQ_KEY = '_local_last_update_seq'; +var DOC_COUNT_KEY = '_local_doc_count'; +var UUID_KEY = '_local_uuid'; + +var MD5_PREFIX = 'md5-'; + +var vuvuEncoding = { + encode: vuvuzela.stringify, + decode: vuvuzela.parse, + buffer: false, + type: 'cheap-json' +}; + +function fetchAttachments(results, stores) { + return utils.Promise.all(results.map(function (row) { + if (row.doc && row.doc._attachments) { + var attNames = Object.keys(row.doc._attachments); + return utils.Promise.all(attNames.map(function (att) { + var attObj = row.doc._attachments[att]; + if ('data' in attObj) { // already fetched + return; + } + return new utils.Promise(function (resolve, reject) { + stores.binaryStore.get(attObj.digest, function (err, buffer) { + var base64 = ''; + if (err && err.name !== 'NotFoundError') { + return reject(err); + } else if (!err) { + base64 = utils.btoa(buffer); + } + row.doc._attachments[att] = utils.extend( + utils.pick(attObj, ['digest', 'content_type']), + {data: base64} + ); + resolve(); + }); + }); + })); + } + })); +} + +function createChangesFilter(opts) { + var baseFilter = utils.filterChange(opts); + var docIds = opts.doc_ids && new utils.Set(opts.doc_ids); + return function filter(change) { + // It's the responsibility of each adapter to actually do + // the doc_ids filtering, since websql/idb can do it + // more efficiently. + if (docIds && !docIds.has(change.id)) { + return false; + } + return baseFilter(change); + }; +} + +function LevelPouch(opts, callback) { + opts = utils.clone(opts); + var api = this; + var instanceId; + var stores = {}; + var db; + var name = opts.name; + if (typeof opts.createIfMissing === 'undefined') { + opts.createIfMissing = true; + } + + var leveldown = opts.db || originalLeveldown; + if (typeof leveldown.destroy !== 'function') { + leveldown.destroy = function (name, cb) { cb(); }; + } + var dbStore; + if (dbStores.has(leveldown.name)) { + dbStore = dbStores.get(leveldown.name); + } else { + dbStore = new utils.Map(); + dbStores.set(leveldown.name, dbStore); + } + if (dbStore.has(name)) { + db = dbStore.get(name); + afterDBCreated(); + } else { + dbStore.set(name, sublevel(levelup(name, opts, function (err) { + if (err) { + dbStore["delete"](name); + return callback(err); + } + db = dbStore.get(name); + db._docCountQueue = { + queue : [], + running : false, + docCount : -1 + }; + db._writeQueue = new Deque(); + if (opts.db || opts.noMigrate) { + afterDBCreated(); + } else { + migrate.toSublevel(name, db, afterDBCreated); + } + }))); + } + + function afterDBCreated() { + stores.docStore = db.sublevel(DOC_STORE, {valueEncoding: vuvuEncoding}); + stores.bySeqStore = db.sublevel(BY_SEQ_STORE, {valueEncoding: 'json'}); + stores.attachmentStore = + db.sublevel(ATTACHMENT_STORE, {valueEncoding: 'json'}); + stores.binaryStore = db.sublevel(BINARY_STORE, {valueEncoding: 'binary'}); + stores.localStore = db.sublevel(LOCAL_STORE, {valueEncoding: 'json'}); + stores.metaStore = db.sublevel(META_STORE, {valueEncoding: 'json'}); + migrate.localAndMetaStores(db, stores, function () { + stores.metaStore.get(UPDATE_SEQ_KEY, function (err, value) { + if (typeof db._updateSeq === 'undefined') { + db._updateSeq = value || 0; + } + stores.metaStore.get(DOC_COUNT_KEY, function (err, value) { + db._docCountQueue.docCount = !err ? value : 0; + countDocs(function (err) { // notify queue that the docCount is ready + if (err) { + api.emit('error', err); + } + stores.metaStore.get(UUID_KEY, function (err, value) { + instanceId = !err ? value : utils.uuid(); + stores.metaStore.put(UUID_KEY, instanceId, function (err, value) { + process.nextTick(function () { + callback(null, api); + }); + }); + }); + }); + }); + }); + }); + } + + function countDocs(callback) { + if (db._docCountQueue.running || !db._docCountQueue.queue.length || + db._docCountQueue.docCount === -1) { + return incrementDocCount(0, callback); // wait for fresh data + } + return db._docCountQueue.docCount; // use cached value + } + + function applyNextDocCountDelta() { + if (db._docCountQueue.running || !db._docCountQueue.queue.length || + db._docCountQueue.docCount === -1) { + return; + } + db._docCountQueue.running = true; + var item = db._docCountQueue.queue.shift(); + if (db.isClosed()) { + return item.callback(new Error('database is closed')); + } + stores.metaStore.get(DOC_COUNT_KEY, function (err, docCount) { + docCount = !err ? docCount : 0; + + function complete(err) { + db._docCountQueue.docCount = docCount; + item.callback(err, docCount); + db._docCountQueue.running = false; + applyNextDocCountDelta(); + } + + if (item.delta === 0) { + complete(); + } else { + stores.metaStore.put(DOC_COUNT_KEY, docCount + item.delta, complete); + } + }); + } + + function incrementDocCount(delta, callback) { + db._docCountQueue.queue.push({delta : delta, callback : callback}); + applyNextDocCountDelta(); + } + + api.type = function () { + return 'leveldb'; + }; + + api._id = function (callback) { + callback(null, instanceId); + }; + + api._info = function (callback) { + countDocs(function (err, docCount) { + if (err) { + return callback(err); + } + stores.metaStore.get(UPDATE_SEQ_KEY, function (err, otherUpdateSeq) { + if (err) { + otherUpdateSeq = db._updateSeq; + } + + return callback(null, { + doc_count: docCount, + update_seq: otherUpdateSeq + }); + }); + }); + }; + + // all read/write operations to the database are done in a queue, + // similar to how websql/idb works. this avoids problems such + // as e.g. compaction needing to have a lock on the database while + // it updates stuff. in the future we can revisit this. + function writeLock(fun) { + return utils.getArguments(function (args) { + + var callback = args[args.length - 1]; + args[args.length - 1] = utils.getArguments(function (cbArgs) { + callback.apply(null, cbArgs); + process.nextTick(function () { + db._writeQueue.shift(); + if (db._writeQueue.length) { + db._writeQueue.peekFront()(); + } + }); + }); + + db._writeQueue.push(function () { + fun.apply(null, args); + }); + + if (db._writeQueue.length === 1) { + db._writeQueue.peekFront()(); + } + }); + } + + function formatSeq(n) { + return ('0000000000000000' + n).slice(-16); + } + + function parseSeq(s) { + return parseInt(s, 10); + } + + function makeDoc(rawDoc, callback) { + var doc = rawDoc.data; + doc._id = rawDoc.metadata.id; + if ('_rev' in doc) { + if (doc._rev !== rawDoc.metadata.rev) { + return callback(new Error('wrong doc returned')); + } + } else { + // we didn't always store rev + doc._rev = rawDoc.metadata.rev; + } + callback(null, {doc: doc, metadata: rawDoc.metadata}); + } + + api._get = function (id, opts, callback) { + opts = utils.clone(opts); + var docChanged = []; + + function didDocChange(doc) { + docChanged.push(doc); + } + + db.on('pouchdb-id-' + id, didDocChange); + + stores.docStore.get(id, function (err, metadata) { + db.removeListener('pouchdb-id-' + id, didDocChange); + + if (err || !metadata) { + return callback(errors.MISSING_DOC); + } + + if (utils.isDeleted(metadata) && !opts.rev) { + return callback(errors.error(errors.MISSING_DOC, "deleted")); + } + + var updated; + + function ifUpdate(doc) { + updated = doc; + } + + var rev = merge.winningRev(metadata); + rev = opts.rev ? opts.rev : rev; + + var seq = metadata.rev_map[rev]; + + var anyChanged = docChanged.filter(function (doc) { + return doc.metadata.seq === seq; + }); + + if (anyChanged.length) { + return makeDoc(anyChanged.pop(), callback); + } + + db.on('pouchdb-' + seq, ifUpdate); + + stores.bySeqStore.get(formatSeq(seq), function (err, doc) { + db.removeListener('pouchdb-' + seq, ifUpdate); + if (updated) { + return makeDoc(updated, callback); + + } + + if (!doc) { + return callback(errors.MISSING_DOC); + } + if ('_id' in doc && doc._id !== metadata.id) { + // this failing implies something very wrong + return callback(new Error('wrong doc returned')); + } + doc._id = metadata.id; + if ('_rev' in doc) { + if (doc._rev !== rev) { + // this failing implies something very wrong + return callback(new Error('wrong doc returned')); + } + } else { + // we didn't always store this + doc._rev = rev; + } + return callback(null, {doc: doc, metadata: metadata}); + }); + }); + }; + + // not technically part of the spec, but if putAttachment has its own + // method... + api._getAttachment = function (attachment, opts, callback) { + var digest = attachment.digest; + + stores.binaryStore.get(digest, function (err, attach) { + var data; + + if (err && err.name === 'NotFoundError') { + // Empty attachment + data = opts.encode ? '' : process.browser ? + utils.createBlob([''], {type: attachment.content_type}) : + new Buffer(''); + return callback(null, data); + } + + if (err) { + return callback(err); + } + + if (process.browser) { + if (opts.encode) { + data = utils.btoa(attach); + } else { + data = utils.createBlob([utils.fixBinary(attach)], + {type: attachment.content_type}); + } + } else { + data = opts.encode ? utils.btoa(attach) : attach; + } + callback(null, data); + }); + }; + + api._bulkDocs = writeLock(function (req, opts, callback) { + var newEdits = opts.new_edits; + var results = new Array(req.docs.length); + var lock = new utils.Set(); + + // parse the docs and give each a sequence number + var userDocs = req.docs; + var info = userDocs.map(function (doc, i) { + if (doc._id && utils.isLocalId(doc._id)) { + return doc; + } + var newDoc = utils.parseDoc(doc, newEdits); + + if (newDoc.metadata && !newDoc.metadata.rev_map) { + newDoc.metadata.rev_map = {}; + } + + return newDoc; + }); + var current = 0; + var infoErrors = info.filter(function (doc) { + return doc.error; + }); + + if (infoErrors.length) { + return callback(infoErrors[0]); + } + + // verify any stub attachments as a precondition test + + function verifyAttachment(digest, callback) { + stores.attachmentStore.get(digest, function (levelErr) { + if (levelErr) { + var err = new Error('unknown stub attachment with digest ' + digest); + err.status = 412; + callback(err); + } else { + callback(); + } + }); + } + + function verifyAttachments(finish) { + var digests = []; + userDocs.forEach(function (doc) { + if (doc && doc._attachments) { + Object.keys(doc._attachments).forEach(function (filename) { + var att = doc._attachments[filename]; + if (att.stub) { + digests.push(att.digest); + } + }); + } + }); + if (!digests.length) { + return finish(); + } + var numDone = 0; + var err; + + function checkDone() { + if (++numDone === digests.length) { + finish(err); + } + } + digests.forEach(function (digest) { + verifyAttachment(digest, function (attErr) { + if (attErr && !err) { + err = attErr; + } + checkDone(); + }); + }); + } + + var inProgress = 0; + function processDocs() { + var index = current; + if (inProgress > BATCH_SIZE) { + return; + } + if (index >= info.length) { + if (inProgress === 0) { + return complete(); + } else { + return; + } + } + var currentDoc = info[index]; + current++; + inProgress++; + if (currentDoc._id && utils.isLocalId(currentDoc._id)) { + api[currentDoc._deleted ? '_removeLocalNoLock' : '_putLocalNoLock']( + currentDoc, function (err, resp) { + if (err) { + results[index] = err; + } else { + results[index] = {}; + } + inProgress--; + processDocs(); + }); + return; + } + + if (lock.has(currentDoc.metadata.id)) { + results[index] = errors.REV_CONFLICT; + inProgress--; + return processDocs(); + } + lock.add(currentDoc.metadata.id); + + stores.docStore.get(currentDoc.metadata.id, function (err, oldDoc) { + if (err) { + if (err.name === 'NotFoundError') { + insertDoc(currentDoc, index, function () { + lock["delete"](currentDoc.metadata.id); + inProgress--; + processDocs(); + }); + } else { + err.error = true; + results[index] = err; + lock["delete"](currentDoc.metadata.id); + inProgress--; + processDocs(); + } + } else { + updateDoc(oldDoc, currentDoc, index, function () { + lock["delete"](currentDoc.metadata.id); + inProgress--; + processDocs(); + }); + } + }); + + if (newEdits) { + processDocs(); + } + } + + function insertDoc(doc, index, callback) { + // Can't insert new deleted documents + if ('was_delete' in opts && utils.isDeleted(doc.metadata)) { + results[index] = errors.MISSING_DOC; + return callback(); + } + writeDoc(doc, index, function (err) { + if (err) { + return callback(err); + } + if (utils.isDeleted(doc.metadata)) { + return callback(); + } + incrementDocCount(1, callback); + }); + } + + function updateDoc(oldDoc, docInfo, index, callback) { + + if (utils.revExists(oldDoc, docInfo.metadata.rev)) { + results[index] = docInfo; + callback(); + return; + } + + var previouslyDeleted = utils.isDeleted(oldDoc); + var deleted = utils.isDeleted(docInfo.metadata); + var isRoot = /^1-/.test(docInfo.metadata.rev); + + if (previouslyDeleted && !deleted && newEdits && isRoot) { + var newDoc = docInfo.data; + newDoc._rev = oldDoc.rev; + newDoc._id = docInfo.metadata.id; + docInfo = utils.parseDoc(newDoc, newEdits); + } + + var merged = + merge.merge(oldDoc.rev_tree, docInfo.metadata.rev_tree[0], 1000); + + var inConflict = newEdits && ((previouslyDeleted && deleted) || + (!previouslyDeleted && newEdits && merged.conflicts !== 'new_leaf') || + (previouslyDeleted && !deleted && merged.conflicts === 'new_branch')); + + if (inConflict) { + results[index] = errors.REV_CONFLICT; + return callback(); + } + var newRev = docInfo.metadata.rev; + docInfo.metadata.rev_tree = merged.tree; + docInfo.metadata.rev_map = oldDoc.rev_map; + + var delta = 0; + if (newEdits || merge.winningRev(docInfo.metadata) === newRev) { + // if newEdits==false and we're pushing existing revisions, + // then the only thing that matters is whether this revision + // is the winning one, and thus replaces an old one + delta = (previouslyDeleted === deleted) ? 0 : + previouslyDeleted < deleted ? -1 : 1; + } + + incrementDocCount(delta, function (err) { + if (err) { + return callback(err); + } + writeDoc(docInfo, index, callback); + }); + + } + + function writeDoc(doc, index, callback2) { + var err = null; + var recv = 0; + + doc.data._id = doc.metadata.id; + doc.data._rev = doc.metadata.rev; + + if (utils.isDeleted(doc.metadata)) { + doc.data._deleted = true; + } + + var attachments = doc.data._attachments ? + Object.keys(doc.data._attachments) : + []; + + function collectResults(attachmentErr) { + if (!err) { + if (attachmentErr) { + err = attachmentErr; + callback2(err); + } else if (recv === attachments.length) { + finish(); + } + } + } + + function attachmentSaved(err) { + recv++; + collectResults(err); + } + + function onMD5Load(doc, key, data, attachmentSaved) { + return function (result) { + saveAttachment(doc, MD5_PREFIX + result, key, data, attachmentSaved); + }; + } + + function onLoadEnd(doc, key, attachmentSaved) { + return function (data) { + utils.MD5(data).then( + onMD5Load(doc, key, data, attachmentSaved) + ); + }; + } + + for (var i = 0; i < attachments.length; i++) { + var key = attachments[i]; + var att = doc.data._attachments[key]; + + if (att.stub) { + // still need to update the refs mapping + var id = doc.data._id; + var rev = doc.data._rev; + saveAttachmentRefs(id, rev, att.digest, attachmentSaved); + continue; + } + var data; + if (typeof att.data === 'string') { + try { + data = utils.atob(att.data); + } catch (e) { + callback(utils.extend({}, errors.BAD_ARG, + {reason: "Attachments need to be base64 encoded"})); + return; + } + } else if (!process.browser) { + data = att.data; + } else { // browser + utils.readAsBinaryString(att.data, + onLoadEnd(doc, key, attachmentSaved)); + continue; + } + utils.MD5(data).then( + onMD5Load(doc, key, data, attachmentSaved) + ); + } + + function finish() { + var seq = doc.metadata.rev_map[doc.metadata.rev]; + if (!seq) { + // check that there aren't any existing revisions with the same + // reivision id, else we shouldn't increment updateSeq + seq = ++db._updateSeq; + } + doc.metadata.rev_map[doc.metadata.rev] = doc.metadata.seq = seq; + var seqKey = formatSeq(seq); + db.emit('pouchdb-id-' + doc.metadata.id, doc); + db.emit('pouchdb-' + seqKey, doc); + db.batch([{ + key: seqKey, + value: doc.data, + prefix: stores.bySeqStore, + type: 'put', + valueEncoding: 'json' + }, { + key: doc.metadata.id, + value: doc.metadata, + prefix: stores.docStore, + type: 'put', + valueEncoding: vuvuEncoding + }], function (err) { + if (!err) { + db.emit('pouchdb-id-' + doc.metadata.id, doc); + db.emit('pouchdb-' + seqKey, doc); + } + return stores.metaStore.put(UPDATE_SEQ_KEY, db._updateSeq, + function (err) { + if (err) { + results[index] = err; + } else { + results[index] = doc; + } + return callback2(); + }); + }); + } + + if (!attachments.length) { + finish(); + } + } + + // attachments are queued per-digest, otherwise the refs could be + // overwritten by concurrent writes in the same bulkDocs session + var attachmentQueues = {}; + + function saveAttachmentRefs(id, rev, digest, callback) { + + function fetchAtt() { + return new utils.Promise(function (resolve, reject) { + stores.attachmentStore.get(digest, function (err, oldAtt) { + if (err && err.name !== 'NotFoundError') { + return reject(err); + } + resolve(oldAtt); + }); + }); + } + + function saveAtt(oldAtt) { + var ref = [id, rev].join('@'); + var newAtt = {}; + + if (oldAtt) { + if (oldAtt.refs) { + // only update references if this attachment already has them + // since we cannot migrate old style attachments here without + // doing a full db scan for references + newAtt.refs = oldAtt.refs; + newAtt.refs[ref] = true; + } + } else { + newAtt.refs = {}; + newAtt.refs[ref] = true; + } + + return new utils.Promise(function (resolve, reject) { + stores.attachmentStore.put(digest, newAtt, function (err) { + if (err) { + return reject(err); + } + resolve(!oldAtt); + }); + }); + } + + // put attachments in a per-digest queue, to avoid two docs with the same + // attachment overwriting each other + var queue = attachmentQueues[digest] || utils.Promise.resolve(); + attachmentQueues[digest] = queue.then(function () { + return fetchAtt().then(saveAtt).then(function (isNewAttachment) { + callback(null, isNewAttachment); + }, callback); + }); + } + + function saveAttachment(docInfo, digest, key, data, callback) { + var att = docInfo.data._attachments[key]; + delete att.data; + att.digest = digest; + att.length = data.length; + var id = docInfo.metadata.id; + var rev = docInfo.metadata.rev; + + saveAttachmentRefs(id, rev, digest, function (err, isNewAttachment) { + if (err) { + return callback(err); + } + // do not try to store empty attachments + if (data.length === 0) { + return callback(err); + } + if (!isNewAttachment) { + // small optimization - don't bother writing it again + return callback(err); + } + // doing this in batch causes a test to fail, wtf? + stores.binaryStore.put(digest, data, function (err) { + callback(err); + }); + }); + } + + function complete() { + var aresults = results.map(function (result) { + if (!Object.keys(result).length) { + return { + ok: true + }; + } + if (result.error) { + return result; + } + + var metadata = result.metadata; + var rev = merge.winningRev(metadata); + + return { + ok: true, + id: metadata.id, + rev: rev + }; + }); + LevelPouch.Changes.notify(name); + process.nextTick(function () { + callback(null, aresults); + }); + } + + verifyAttachments(function (err) { + if (err) { + return callback(err); + } + processDocs(); + }); + }); + api._allDocs = function (opts, callback) { + opts = utils.clone(opts); + countDocs(function (err, docCount) { + if (err) { + return callback(err); + } + var readstreamOpts = {}; + var skip = opts.skip || 0; + if (opts.startkey) { + readstreamOpts.start = opts.startkey; + } + if (opts.endkey) { + readstreamOpts.end = opts.endkey; + } + if (opts.key) { + readstreamOpts.start = readstreamOpts.end = opts.key; + } + if (opts.descending) { + readstreamOpts.reverse = true; + // switch start and ends + var tmp = readstreamOpts.start; + readstreamOpts.start = readstreamOpts.end; + readstreamOpts.end = tmp; + } + var limit; + if (typeof opts.limit === 'number') { + limit = opts.limit; + } else { + limit = -1; + } + if (limit === 0 || + ('start' in readstreamOpts && 'end' in readstreamOpts && + readstreamOpts.start > readstreamOpts.end)) { + // should return 0 results when start is greater than end. + // normally level would "fix" this for us by reversing the order, + // so short-circuit instead + return callback(null, { + total_rows: docCount, + offset: opts.skip, + rows: [] + }); + } + var results = []; + var docstream = stores.docStore.readStream(readstreamOpts); + + var throughStream = through(function (entry, _, next) { + if (!utils.isDeleted(entry.value)) { + if (skip-- > 0) { + next(); + return; + } else if (limit-- === 0) { + docstream.unpipe(); + docstream.destroy(); + next(); + return; + } + } else if (opts.deleted !== 'ok') { + next(); + return; + } + function allDocsInner(metadata, data) { + var doc = { + id: metadata.id, + key: metadata.id, + value: { + rev: merge.winningRev(metadata) + } + }; + if (opts.include_docs) { + doc.doc = data; + doc.doc._rev = doc.value.rev; + if (opts.conflicts) { + doc.doc._conflicts = merge.collectConflicts(metadata); + } + for (var att in doc.doc._attachments) { + if (doc.doc._attachments.hasOwnProperty(att)) { + doc.doc._attachments[att].stub = true; + } + } + } + if (opts.inclusive_end === false && metadata.id === opts.endkey) { + return next(); + } else if (utils.isDeleted(metadata)) { + if (opts.deleted === 'ok') { + doc.value.deleted = true; + doc.doc = null; + } else { + return next(); + } + } + results.push(doc); + next(); + } + var metadata = entry.value; + if (opts.include_docs) { + var seq = metadata.rev_map[merge.winningRev(metadata)]; + stores.bySeqStore.get(formatSeq(seq), function (err, data) { + allDocsInner(metadata, data); + }); + } + else { + allDocsInner(metadata); + } + }, function (next) { + utils.Promise.resolve().then(function () { + return opts.attachments && fetchAttachments(results, stores); + }).then(function () { + callback(null, { + total_rows: docCount, + offset: opts.skip, + rows: results + }); + }, callback); + next(); + }).on('unpipe', function () { + throughStream.end(); + }); + + docstream.on('error', callback); + + docstream.pipe(throughStream); + }); + }; + + api._changes = function (opts) { + opts = utils.clone(opts); + + if (opts.continuous) { + var id = name + ':' + utils.uuid(); + LevelPouch.Changes.addListener(name, id, api, opts); + LevelPouch.Changes.notify(name); + return { + cancel: function () { + LevelPouch.Changes.removeListener(name, id); + } + }; + } + + var descending = opts.descending; + var results = []; + var last_seq = 0; + var called = 0; + var streamOpts = { + reverse: descending + }; + var limit; + if ('limit' in opts && opts.limit > 0) { + limit = opts.limit; + } + if (!streamOpts.reverse) { + streamOpts.start = formatSeq(opts.since ? opts.since + 1 : 0); + } + + var filter = createChangesFilter(opts); + + var returnDocs; + if ('returnDocs' in opts) { + returnDocs = opts.returnDocs; + } else { + returnDocs = true; + } + + function complete() { + opts.done = true; + if (returnDocs && opts.limit) { + if (opts.limit < results.length) { + results.length = opts.limit; + } + } + changeStream.unpipe(throughStream); + changeStream.destroy(); + if (!opts.continuous && !opts.cancelled) { + utils.Promise.resolve().then(function () { + if (opts.include_docs && opts.attachments) { + return fetchAttachments(results, stores); + } + }).then(function () { + opts.complete(null, {results: results, last_seq: last_seq}); + }); + } + } + var changeStream = stores.bySeqStore.readStream(streamOpts); + var throughStream = through(function (data, _, next) { + if (limit && called >= limit) { + complete(); + return next(); + } + if (opts.cancelled || opts.done) { + return next(); + } + + stores.docStore.get(data.value._id, function (err, metadata) { + if (opts.cancelled || opts.done || db.isClosed() || + utils.isLocalId(metadata.id)) { + return next(); + } + var doc = data.value; + doc._rev = merge.winningRev(metadata); + var change = opts.processChange(doc, metadata, opts); + change.seq = metadata.seq; + + if (last_seq < metadata.seq) { + last_seq = metadata.seq; + } + + // Ensure duplicated dont overwrite winning rev + if (parseSeq(data.key) === metadata.rev_map[change.doc._rev] && + filter(change)) { + called++; + + if (opts.attachments && opts.include_docs) { + // fetch attachment immediately for the benefit + // of live listeners + fetchAttachments([change], stores).then(function () { + opts.onChange(change); + }); + } else { + opts.onChange(change); + } + + if (returnDocs) { + results.push(change); + } + } + next(); + }); + }, function (next) { + if (opts.cancelled) { + return next(); + } + if (returnDocs && opts.limit) { + if (opts.limit < results.length) { + results.length = opts.limit; + } + } + + next(); + }).on('unpipe', function () { + throughStream.end(); + complete(); + }); + changeStream.pipe(throughStream); + return { + cancel: function () { + opts.cancelled = true; + complete(); + } + }; + }; + + api._close = function (callback) { + if (db.isClosed()) { + return callback(errors.NOT_OPEN); + } + db.close(function (err) { + if (err) { + callback(err); + } else { + dbStore["delete"](name); + callback(); + } + }); + }; + + api._getRevisionTree = function (docId, callback) { + stores.docStore.get(docId, function (err, metadata) { + if (err) { + callback(errors.MISSING_DOC); + } else { + callback(null, metadata.rev_tree); + } + }); + }; + + api._doCompaction = writeLock(function (docId, revs, callback) { + if (!revs.length) { + return callback(); + } + stores.docStore.get(docId, function (err, metadata) { + if (err) { + return callback(err); + } + var seqs = metadata.rev_map; // map from rev to seq + merge.traverseRevTree(metadata.rev_tree, function (isLeaf, pos, + revHash, ctx, opts) { + var rev = pos + '-' + revHash; + if (revs.indexOf(rev) !== -1) { + opts.status = 'missing'; + } + }); + var batch = []; + batch.push({ + key: metadata.id, + value: metadata, + type: 'put', + valueEncoding: vuvuEncoding, + prefix: stores.docStore + }); + + var digestMap = {}; + var numDone = 0; + var overallErr; + function checkDone(err) { + if (err) { + overallErr = err; + } + if (++numDone === revs.length) { // done + if (overallErr) { + return callback(err); + } + deleteOrphanedAttachments(); + } + } + + function finish(err) { + if (err) { + return callback(err); + } + db.batch(batch, callback); + } + + function deleteOrphanedAttachments() { + var possiblyOrphanedAttachments = Object.keys(digestMap); + if (!possiblyOrphanedAttachments.length) { + return finish(); + } + var numDone = 0; + var overallErr; + function checkDone(err) { + if (err) { + overallErr = err; + } + if (++numDone === possiblyOrphanedAttachments.length) { + finish(overallErr); + } + } + var refsToDelete = new utils.Map(); + revs.forEach(function (rev) { + refsToDelete.set(docId + '@' + rev, true); + }); + possiblyOrphanedAttachments.forEach(function (digest) { + stores.attachmentStore.get(digest, function (err, attData) { + if (err) { + if (err.name === 'NotFoundError') { + return checkDone(); + } else { + return checkDone(err); + } + } + var refs = Object.keys(attData.refs || {}).filter(function (ref) { + return !refsToDelete.has(ref); + }); + var newRefs = {}; + refs.forEach(function (ref) { + newRefs[ref] = true; + }); + if (refs.length) { // not orphaned + batch.push({ + key: digest, + type: 'put', + valueEncoding: 'json', + value: {refs: newRefs}, + prefix: stores.attachmentStore + }); + } else { // orphaned, can safely delete + batch = batch.concat([{ + key: digest, + type: 'del', + prefix: stores.attachmentStore + }, { + key: digest, + type: 'del', + prefix: stores.binaryStore + }]); + } + checkDone(); + }); + }); + } + + revs.forEach(function (rev) { + var seq = seqs[rev]; + if (!seq) { + return; + } + batch.push({ + key: formatSeq(seq), + type: 'del', + prefix: stores.bySeqStore + }); + stores.bySeqStore.get(formatSeq(seq), function (err, doc) { + if (err) { + if (err.name === 'NotFoundError') { + return checkDone(); + } else { + return checkDone(err); + } + } + var atts = Object.keys(doc._attachments || {}); + atts.forEach(function (attName) { + var digest = doc._attachments[attName].digest; + digestMap[digest] = true; + }); + checkDone(); + }); + }); + }); + }); + + api._getLocal = function (id, callback) { + stores.localStore.get(id, function (err, doc) { + if (err) { + callback(errors.MISSING_DOC); + } else { + callback(null, doc); + } + }); + }; + + api._putLocal = writeLock(function (doc, callback) { + api._putLocalNoLock(doc, callback); + }); + + // the NoLock version is for use by bulkDocs + api._putLocalNoLock = function (doc, callback) { + delete doc._revisions; // ignore this, trust the rev + var oldRev = doc._rev; + var id = doc._id; + stores.localStore.get(id, function (err, resp) { + if (err) { + if (oldRev) { + return callback(errors.REV_CONFLICT); + } + } + if (resp && resp._rev !== oldRev) { + return callback(errors.REV_CONFLICT); + } + if (!oldRev) { + doc._rev = '0-1'; + } else { + doc._rev = '0-' + (parseInt(oldRev.split('-')[1], 10) + 1); + } + stores.localStore.put(id, doc, function (err) { + if (err) { + return callback(err); + } + var ret = {ok: true, id: doc._id, rev: doc._rev}; + callback(null, ret); + }); + }); + }; + + api._removeLocal = writeLock(function (doc, callback) { + api._removeLocalNoLock(doc, callback); + }); + + // the NoLock version is for use by bulkDocs + api._removeLocalNoLock = function (doc, callback) { + stores.localStore.get(doc._id, function (err, resp) { + if (err) { + return callback(err); + } + if (resp._rev !== doc._rev) { + return callback(errors.REV_CONFLICT); + } + stores.localStore.del(doc._id, function (err) { + if (err) { + return callback(err); + } + var ret = {ok: true, id: doc._id, rev: '0-0'}; + callback(null, ret); + }); + }); + }; +} + +LevelPouch.valid = function () { + return process && !process.browser; +}; + +// close and delete open leveldb stores +LevelPouch.destroy = utils.toPromise(function (name, opts, callback) { + opts = utils.clone(opts); + + var leveldown = opts.db || originalLeveldown; + function callDestroy(name, cb) { + if (typeof leveldown.destroy === 'function') { + leveldown.destroy(name, cb); + } else { + process.nextTick(callback); + } + } + + var dbStore; + if (dbStores.has(leveldown.name)) { + dbStore = dbStores.get(leveldown.name); + } else { + return callDestroy(name, callback); + } + + if (dbStore.has(name)) { + + LevelPouch.Changes.removeAllListeners(name); + + dbStore.get(name).close(function () { + dbStore["delete"](name); + callDestroy(name, callback); + }); + } else { + callDestroy(name, callback); + } +}); + +LevelPouch.use_prefix = false; + +LevelPouch.Changes = new utils.Changes(); + +module.exports = LevelPouch; + +}).call(this,_dereq_('_process'),_dereq_("buffer").Buffer) +},{"../deps/errors":5,"../deps/migrate":7,"../merge":10,"../utils":13,"_process":24,"buffer":17,"double-ended-queue":43,"level-sublevel":61,"leveldown":"leveldown","levelup":75,"through2":132,"vuvuzela":133}],2:[function(_dereq_,module,exports){ +"use strict"; + +var createBlob = _dereq_('./blob.js'); +var errors = _dereq_('./errors'); +var utils = _dereq_("../utils"); +var hasUpload; + +function ajax(options, adapterCallback) { + + var requestCompleted = false; + var callback = utils.getArguments(function (args) { + if (requestCompleted) { + return; + } + adapterCallback.apply(this, args); + requestCompleted = true; + }); + + if (typeof options === "function") { + callback = options; + options = {}; + } + + options = utils.clone(options); + + var defaultOptions = { + method : "GET", + headers: {}, + json: true, + processData: true, + timeout: 10000, + cache: false + }; + + options = utils.extend(true, defaultOptions, options); + + // cache-buster, specifically designed to work around IE's aggressive caching + // see http://www.dashbay.com/2011/05/internet-explorer-caches-ajax/ + if (options.method === 'GET' && !options.cache) { + var hasArgs = options.url.indexOf('?') !== -1; + options.url += (hasArgs ? '&' : '?') + '_nonce=' + utils.uuid(16); + } + + function onSuccess(obj, resp, cb) { + if (!options.binary && !options.json && options.processData && + typeof obj !== 'string') { + obj = JSON.stringify(obj); + } else if (!options.binary && options.json && typeof obj === 'string') { + try { + obj = JSON.parse(obj); + } catch (e) { + // Probably a malformed JSON from server + return cb(e); + } + } + if (Array.isArray(obj)) { + obj = obj.map(function (v) { + var obj; + if (v.ok) { + return v; + } else if (v.error && v.error === 'conflict') { + obj = errors.REV_CONFLICT; + obj.id = v.id; + return obj; + } else if (v.error && v.error === 'forbidden') { + obj = errors.FORBIDDEN; + obj.id = v.id; + obj.reason = v.reason; + return obj; + } else if (v.missing) { + obj = errors.MISSING_DOC; + obj.missing = v.missing; + return obj; + } else { + return v; + } + }); + } + cb(null, obj, resp); + } + + function onError(err, cb) { + var errParsed, errObj, errType, key; + try { + errParsed = JSON.parse(err.responseText); + //would prefer not to have a try/catch clause + for (key in errors) { + if (errors.hasOwnProperty(key) && + errors[key].name === errParsed.error) { + errType = errors[key]; + break; + } + } + if (!errType) { + errType = errors.UNKNOWN_ERROR; + if (err.status) { + errType.status = err.status; + } + if (err.statusText) { + err.name = err.statusText; + } + } + errObj = errors.error(errType, errParsed.reason); + } catch (e) { + for (var key in errors) { + if (errors.hasOwnProperty(key) && errors[key].status === err.status) { + errType = errors[key]; + break; + } + } + if (!errType) { + errType = errors.UNKNOWN_ERROR; + if (err.status) { + errType.status = err.status; + } + if (err.statusText) { + err.name = err.statusText; + } + } + errObj = errors.error(errType); + } + if (err.withCredentials && err.status === 0) { + // apparently this is what we get when the method + // is reported as not allowed by CORS. so fudge it + errObj.status = 405; + errObj.statusText = "Method Not Allowed"; + } + cb(errObj); + } + + var timer; + var xhr; + if (options.xhr) { + xhr = new options.xhr(); + } else { + xhr = new XMLHttpRequest(); + } + xhr.open(options.method, options.url); + xhr.withCredentials = true; + + if (options.json) { + options.headers.Accept = 'application/json'; + options.headers['Content-Type'] = options.headers['Content-Type'] || + 'application/json'; + if (options.body && + options.processData && + typeof options.body !== "string") { + options.body = JSON.stringify(options.body); + } + } + + if (options.binary) { + xhr.responseType = 'arraybuffer'; + } + + var createCookie = function (name, value, days) { + var expires = ""; + if (days) { + var date = new Date(); + date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); + expires = "; expires=" + date.toGMTString(); + } + document.cookie = name + "=" + value + expires + "; path=/"; + }; + + for (var key in options.headers) { + if (key === 'Cookie') { + var cookie = options.headers[key].split('='); + createCookie(cookie[0], cookie[1], 10); + } else { + xhr.setRequestHeader(key, options.headers[key]); + } + } + + if (!("body" in options)) { + options.body = null; + } + + var abortReq = function () { + if (requestCompleted) { + return; + } + xhr.abort(); + onError(xhr, callback); + }; + + xhr.onreadystatechange = function () { + if (xhr.readyState !== 4 || requestCompleted) { + return; + } + clearTimeout(timer); + if (xhr.status >= 200 && xhr.status < 300) { + var data; + if (options.binary) { + data = createBlob([xhr.response || ''], { + type: xhr.getResponseHeader('Content-Type') + }); + } else { + data = xhr.responseText; + } + onSuccess(data, xhr, callback); + } else { + onError(xhr, callback); + } + }; + + if (options.timeout > 0) { + timer = setTimeout(abortReq, options.timeout); + xhr.onprogress = function () { + clearTimeout(timer); + timer = setTimeout(abortReq, options.timeout); + }; + if (typeof hasUpload === 'undefined') { + // IE throws an error if you try to access it directly + hasUpload = Object.keys(xhr).indexOf('upload') !== -1; + } + if (hasUpload) { // does not exist in ie9 + xhr.upload.onprogress = xhr.onprogress; + } + } + if (options.body && (options.body instanceof Blob)) { + utils.readAsBinaryString(options.body, function (binary) { + xhr.send(utils.fixBinary(binary)); + }); + } else { + xhr.send(options.body); + } + return {abort: abortReq}; +} + +module.exports = ajax; + +},{"../utils":13,"./blob.js":3,"./errors":5}],3:[function(_dereq_,module,exports){ +(function (global){ +"use strict"; + +//Abstracts constructing a Blob object, so it also works in older +//browsers that don't support the native Blob constructor. (i.e. +//old QtWebKit versions, at least). +function createBlob(parts, properties) { + parts = parts || []; + properties = properties || {}; + try { + return new Blob(parts, properties); + } catch (e) { + if (e.name !== "TypeError") { + throw e; + } + var BlobBuilder = global.BlobBuilder || + global.MSBlobBuilder || + global.MozBlobBuilder || + global.WebKitBlobBuilder; + var builder = new BlobBuilder(); + for (var i = 0; i < parts.length; i += 1) { + builder.append(parts[i]); + } + return builder.getBlob(properties.type); + } +} + +module.exports = createBlob; + + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],4:[function(_dereq_,module,exports){ +'use strict'; +exports.Map = LazyMap; // TODO: use ES6 map +exports.Set = LazySet; // TODO: use ES6 set +// based on https://github.com/montagejs/collections +function LazyMap() { + this.store = {}; +} +LazyMap.prototype.mangle = function (key) { + if (typeof key !== "string") { + throw new TypeError("key must be a string but Got " + key); + } + return '$' + key; +}; +LazyMap.prototype.unmangle = function (key) { + return key.substring(1); +}; +LazyMap.prototype.get = function (key) { + var mangled = this.mangle(key); + if (mangled in this.store) { + return this.store[mangled]; + } else { + return void 0; + } +}; +LazyMap.prototype.set = function (key, value) { + var mangled = this.mangle(key); + this.store[mangled] = value; + return true; +}; +LazyMap.prototype.has = function (key) { + var mangled = this.mangle(key); + return mangled in this.store; +}; +LazyMap.prototype["delete"] = function (key) { + var mangled = this.mangle(key); + if (mangled in this.store) { + delete this.store[mangled]; + return true; + } + return false; +}; +LazyMap.prototype.forEach = function (cb) { + var self = this; + var keys = Object.keys(self.store); + keys.forEach(function (key) { + var value = self.store[key]; + key = self.unmangle(key); + cb(value, key); + }); +}; + +function LazySet(array) { + this.store = new LazyMap(); + + // init with an array + if (array && Array.isArray(array)) { + for (var i = 0, len = array.length; i < len; i++) { + this.add(array[i]); + } + } +} +LazySet.prototype.add = function (key) { + return this.store.set(key, true); +}; +LazySet.prototype.has = function (key) { + return this.store.has(key); +}; +LazySet.prototype["delete"] = function (key) { + return this.store["delete"](key); +}; +},{}],5:[function(_dereq_,module,exports){ +"use strict"; + +function PouchError(opts) { + this.status = opts.status; + this.name = opts.error; + this.message = opts.reason; + this.error = true; +} + +PouchError.prototype__proto__ = Error.prototype; + +PouchError.prototype.toString = function () { + return JSON.stringify({ + status: this.status, + name: this.name, + message: this.message + }); +}; + +exports.UNAUTHORIZED = new PouchError({ + status: 401, + error: 'unauthorized', + reason: "Name or password is incorrect." +}); +exports.MISSING_BULK_DOCS = new PouchError({ + status: 400, + error: 'bad_request', + reason: "Missing JSON list of 'docs'" +}); +exports.MISSING_DOC = new PouchError({ + status: 404, + error: 'not_found', + reason: 'missing' +}); +exports.REV_CONFLICT = new PouchError({ + status: 409, + error: 'conflict', + reason: 'Document update conflict' +}); +exports.INVALID_ID = new PouchError({ + status: 400, + error: 'invalid_id', + reason: '_id field must contain a string' +}); +exports.MISSING_ID = new PouchError({ + status: 412, + error: 'missing_id', + reason: '_id is required for puts' +}); +exports.RESERVED_ID = new PouchError({ + status: 400, + error: 'bad_request', + reason: 'Only reserved document ids may start with underscore.' +}); +exports.NOT_OPEN = new PouchError({ + status: 412, + error: 'precondition_failed', + reason: 'Database not open' +}); +exports.UNKNOWN_ERROR = new PouchError({ + status: 500, + error: 'unknown_error', + reason: 'Database encountered an unknown error' +}); +exports.BAD_ARG = new PouchError({ + status: 500, + error: 'badarg', + reason: 'Some query argument is invalid' +}); +exports.INVALID_REQUEST = new PouchError({ + status: 400, + error: 'invalid_request', + reason: 'Request was invalid' +}); +exports.QUERY_PARSE_ERROR = new PouchError({ + status: 400, + error: 'query_parse_error', + reason: 'Some query parameter is invalid' +}); +exports.DOC_VALIDATION = new PouchError({ + status: 500, + error: 'doc_validation', + reason: 'Bad special document member' +}); +exports.BAD_REQUEST = new PouchError({ + status: 400, + error: 'bad_request', + reason: 'Something wrong with the request' +}); +exports.NOT_AN_OBJECT = new PouchError({ + status: 400, + error: 'bad_request', + reason: 'Document must be a JSON object' +}); +exports.DB_MISSING = new PouchError({ + status: 404, + error: 'not_found', + reason: 'Database not found' +}); +exports.IDB_ERROR = new PouchError({ + status: 500, + error: 'indexed_db_went_bad', + reason: 'unknown' +}); +exports.WSQ_ERROR = new PouchError({ + status: 500, + error: 'web_sql_went_bad', + reason: 'unknown' +}); +exports.LDB_ERROR = new PouchError({ + status: 500, + error: 'levelDB_went_went_bad', + reason: 'unknown' +}); +exports.FORBIDDEN = new PouchError({ + status: 403, + error: 'forbidden', + reason: 'Forbidden by design doc validate_doc_update function' +}); +exports.error = function (error, reason, name) { + function CustomPouchError(msg) { + this.message = reason; + if (name) { + this.name = name; + } + } + CustomPouchError.prototype = error; + return new CustomPouchError(reason); +}; + +},{}],6:[function(_dereq_,module,exports){ +(function (process,global){ +'use strict'; + +var crypto = _dereq_('crypto'); +var Md5 = _dereq_('spark-md5'); +var setImmediateShim = global.setImmediate || global.setTimeout; +var MD5_CHUNK_SIZE = 32768; + +function sliceShim(arrayBuffer, begin, end) { + if (typeof arrayBuffer.slice === 'function') { + if (!begin) { + return arrayBuffer.slice(); + } else if (!end) { + return arrayBuffer.slice(begin); + } else { + return arrayBuffer.slice(begin, end); + } + } + // + // shim for IE courtesy of http://stackoverflow.com/a/21440217 + // + + //If `begin`/`end` is unspecified, Chrome assumes 0, so we do the same + //Chrome also converts the values to integers via flooring + begin = Math.floor(begin || 0); + end = Math.floor(end || 0); + + var len = arrayBuffer.byteLength; + + //If either `begin` or `end` is negative, it refers to an + //index from the end of the array, as opposed to from the beginning. + //The range specified by the `begin` and `end` values is clamped to the + //valid index range for the current array. + begin = begin < 0 ? Math.max(begin + len, 0) : Math.min(len, begin); + end = end < 0 ? Math.max(end + len, 0) : Math.min(len, end); + + //If the computed length of the new ArrayBuffer would be negative, it + //is clamped to zero. + if (end - begin <= 0) { + return new ArrayBuffer(0); + } + + var result = new ArrayBuffer(end - begin); + var resultBytes = new Uint8Array(result); + var sourceBytes = new Uint8Array(arrayBuffer, begin, end - begin); + + resultBytes.set(sourceBytes); + + return result; +} + +// convert a 64-bit int to a binary string +function intToString(int) { + var bytes = [ + (int & 0xff), + ((int >>> 8) & 0xff), + ((int >>> 16) & 0xff), + ((int >>> 24) & 0xff) + ]; + return bytes.map(function (byte) { + return String.fromCharCode(byte); + }).join(''); +} + +// convert an array of 64-bit ints into +// a base64-encoded string +function rawToBase64(raw) { + var res = ''; + for (var i = 0; i < raw.length; i++) { + res += intToString(raw[i]); + } + return global.btoa(res); +} + +module.exports = function (data, callback) { + if (!process.browser) { + var base64 = crypto.createHash('md5').update(data).digest('base64'); + callback(null, base64); + return; + } + var inputIsString = typeof data === 'string'; + var len = inputIsString ? data.length : data.byteLength; + var chunkSize = Math.min(MD5_CHUNK_SIZE, len); + var chunks = Math.ceil(len / chunkSize); + var currentChunk = 0; + var buffer = inputIsString ? new Md5() : new Md5.ArrayBuffer(); + + function append(buffer, data, start, end) { + if (inputIsString) { + buffer.appendBinary(data.substring(start, end)); + } else { + buffer.append(sliceShim(data, start, end)); + } + } + + function loadNextChunk() { + var start = currentChunk * chunkSize; + var end = start + chunkSize; + if ((start + chunkSize) >= data.size) { + end = data.size; + } + currentChunk++; + if (currentChunk < chunks) { + append(buffer, data, start, end); + setImmediateShim(loadNextChunk); + } else { + append(buffer, data, start, end); + var raw = buffer.end(true); + var base64 = rawToBase64(raw); + callback(null, base64); + buffer.destroy(); + } + } + loadNextChunk(); +}; + +}).call(this,_dereq_('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"_process":24,"crypto":16,"spark-md5":117}],7:[function(_dereq_,module,exports){ +'use strict'; + +var fs = _dereq_('fs'); +var path = _dereq_('path'); +var utils = _dereq_('../utils'); +var merge = _dereq_('../merge'); +var levelup = _dereq_('levelup'); +var through = _dereq_('through2').obj; +var leveldown = _dereq_("leveldown"); + +var stores = [ + 'document-store', + 'by-sequence', + 'attach-store', + 'attach-binary-store' +]; +function formatSeq(n) { + return ('0000000000000000' + n).slice(-16); +} +var UPDATE_SEQ_KEY = '_local_last_update_seq'; +var DOC_COUNT_KEY = '_local_doc_count'; +var UUID_KEY = '_local_uuid'; + +exports.toSublevel = function (name, db, callback) { + var base = path.resolve(name); + function move(store, index, cb) { + var storePath = path.join(base, store); + var opts; + if (index === 3) { + opts = { + valueEncoding: 'binary' + }; + } else { + opts = { + valueEncoding: 'json' + }; + } + var sub = db.sublevel(store, opts); + var orig = levelup(storePath, opts); + var from = orig.createReadStream(); + var to = sub.createWriteStream(); + from.on('end', function () { + orig.close(function (err) { + cb(err, storePath); + }); + }); + from.pipe(to); + } + fs.unlink(base + '.uuid', function (err) { + if (err) { + return callback(); + } + var todo = 4; + var done = []; + stores.forEach(function (store, i) { + move(store, i, function (err, storePath) { + if (err) { + return callback(err); + } + done.push(storePath); + if (!(--todo)) { + done.forEach(function (item) { + leveldown.destroy(item, function () { + if (++todo === done.length) { + fs.rmdir(base, callback); + } + }); + }); + } + }); + }); + }); +}; +exports.localAndMetaStores = function (db, stores, callback) { + var batches = []; + stores.bySeqStore.get(UUID_KEY, function (err, value) { + if (err) { + // no uuid key, so don't need to migrate; + return callback(); + } + batches.push({ + key: UUID_KEY, + value: value, + prefix: stores.metaStore, + type: 'put', + valueEncoding: 'json' + }); + batches.push({ + key: UUID_KEY, + prefix: stores.bySeqStore, + type: 'del' + }); + stores.bySeqStore.get(DOC_COUNT_KEY, function (err, value) { + if (value) { + // if no doc count key, + // just skip + // we can live with this + batches.push({ + key: DOC_COUNT_KEY, + value: value, + prefix: stores.metaStore, + type: 'put', + valueEncoding: 'json' + }); + batches.push({ + key: DOC_COUNT_KEY, + prefix: stores.bySeqStore, + type: 'del' + }); + } + stores.bySeqStore.get(UPDATE_SEQ_KEY, function (err, value) { + if (value) { + // if no UPDATE_SEQ_KEY + // just skip + // we've gone to far to stop. + batches.push({ + key: UPDATE_SEQ_KEY, + value: value, + prefix: stores.metaStore, + type: 'put', + valueEncoding: 'json' + }); + batches.push({ + key: UPDATE_SEQ_KEY, + prefix: stores.bySeqStore, + type: 'del' + }); + } + var deletedSeqs = {}; + stores.docStore.createReadStream({ + startKey: '_', + endKey: '_\xFF' + }).pipe(through(function (ch, _, next) { + if (!utils.isLocalId(ch.key)) { + return next(); + } + batches.push({ + key: ch.key, + prefix: stores.docStore, + type: 'del' + }); + var winner = merge.winningRev(ch.value); + Object.keys(ch.value.rev_map).forEach(function (key) { + if (key !== 'winner') { + this.push(formatSeq(ch.value.rev_map[key])); + } + }, this); + var winningSeq = ch.value.rev_map[winner]; + stores.bySeqStore.get(formatSeq(winningSeq), function (err, value) { + if (!err) { + batches.push({ + key: ch.key, + value: value, + prefix: stores.localStore, + type: 'put', + valueEncoding: 'json' + }); + } + next(); + }); + + })).pipe(through(function (seq, _, next) { + if (deletedSeqs[seq]) { + return next(); + } + deletedSeqs[seq] = true; + stores.bySeqStore.get(seq, function (err, resp) { + if (err || !utils.isLocalId(resp._id)) { + return next(); + } + batches.push({ + key: seq, + prefix: stores.bySeqStore, + type: 'del' + }); + next(); + }); + }, function (next) { + db.batch(batches, callback); + })); + }); + }); + }); + +}; +},{"../merge":10,"../utils":13,"fs":15,"leveldown":"leveldown","levelup":75,"path":23,"through2":132}],8:[function(_dereq_,module,exports){ +'use strict'; + +// originally parseUri 1.2.2, now patched by us +// (c) Steven Levithan <stevenlevithan.com> +// MIT License +var options = { + strictMode: false, + key: ["source", "protocol", "authority", "userInfo", "user", "password", + "host", "port", "relative", "path", "directory", "file", "query", + "anchor"], + q: { + name: "queryKey", + parser: /(?:^|&)([^&=]*)=?([^&]*)/g + }, + parser: { + /* jshint maxlen: false */ + strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, + loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ + } +}; +function parseUri(str) { + var o = options; + var m = o.parser[o.strictMode ? "strict" : "loose"].exec(str); + var uri = {}; + var i = 14; + + while (i--) { + var key = o.key[i]; + var value = m[i] || ""; + var encoded = ['user', 'password'].indexOf(key) !== -1; + uri[key] = encoded ? decodeURIComponent(value) : value; + } + + uri[o.q.name] = {}; + uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) { + if ($1) { + uri[o.q.name][$1] = $2; + } + }); + + return uri; +} + + +module.exports = parseUri; +},{}],9:[function(_dereq_,module,exports){ +"use strict"; + +// BEGIN Math.uuid.js + +/*! +Math.uuid.js (v1.4) +http://www.broofa.com +mailto:robert@broofa.com + +Copyright (c) 2010 Robert Kieffer +Dual licensed under the MIT and GPL licenses. +*/ + +/* + * Generate a random uuid. + * + * USAGE: Math.uuid(length, radix) + * length - the desired number of characters + * radix - the number of allowable values for each character. + * + * EXAMPLES: + * // No arguments - returns RFC4122, version 4 ID + * >>> Math.uuid() + * "92329D39-6F5C-4520-ABFC-AAB64544E172" + * + * // One argument - returns ID of the specified length + * >>> Math.uuid(15) // 15 character ID (default base=62) + * "VcydxgltxrVZSTV" + * + * // Two arguments - returns ID of the specified length, and radix. + * // (Radix must be <= 62) + * >>> Math.uuid(8, 2) // 8 character ID (base=2) + * "01001010" + * >>> Math.uuid(8, 10) // 8 character ID (base=10) + * "47473046" + * >>> Math.uuid(8, 16) // 8 character ID (base=16) + * "098F4D35" + */ +var chars = ( + '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' + + 'abcdefghijklmnopqrstuvwxyz' +).split(''); +function getValue(radix) { + return 0 | Math.random() * radix; +} +function uuid(len, radix) { + radix = radix || chars.length; + var out = ''; + var i = -1; + + if (len) { + // Compact form + while (++i < len) { + out += chars[getValue(radix)]; + } + return out; + } + // rfc4122, version 4 form + // Fill in random data. At i==19 set the high bits of clock sequence as + // per rfc4122, sec. 4.1.5 + while (++i < 36) { + switch (i) { + case 8: + case 13: + case 18: + case 23: + out += '-'; + break; + case 19: + out += chars[(getValue(16) & 0x3) | 0x8]; + break; + default: + out += chars[getValue(16)]; + } + } + + return out; +} + + + +module.exports = uuid; + + +},{}],10:[function(_dereq_,module,exports){ +'use strict'; +var extend = _dereq_('pouchdb-extend'); + + +// for a better overview of what this is doing, read: +// https://github.com/apache/couchdb/blob/master/src/couchdb/couch_key_tree.erl +// +// But for a quick intro, CouchDB uses a revision tree to store a documents +// history, A -> B -> C, when a document has conflicts, that is a branch in the +// tree, A -> (B1 | B2 -> C), We store these as a nested array in the format +// +// KeyTree = [Path ... ] +// Path = {pos: position_from_root, ids: Tree} +// Tree = [Key, Opts, [Tree, ...]], in particular single node: [Key, []] + +// Turn a path as a flat array into a tree with a single branch +function pathToTree(path) { + var doc = path.shift(); + var root = [doc.id, doc.opts, []]; + var leaf = root; + var nleaf; + + while (path.length) { + doc = path.shift(); + nleaf = [doc.id, doc.opts, []]; + leaf[2].push(nleaf); + leaf = nleaf; + } + return root; +} + +// Merge two trees together +// The roots of tree1 and tree2 must be the same revision +function mergeTree(in_tree1, in_tree2) { + var queue = [{tree1: in_tree1, tree2: in_tree2}]; + var conflicts = false; + while (queue.length > 0) { + var item = queue.pop(); + var tree1 = item.tree1; + var tree2 = item.tree2; + + if (tree1[1].status || tree2[1].status) { + tree1[1].status = + (tree1[1].status === 'available' || + tree2[1].status === 'available') ? 'available' : 'missing'; + } + + for (var i = 0; i < tree2[2].length; i++) { + if (!tree1[2][0]) { + conflicts = 'new_leaf'; + tree1[2][0] = tree2[2][i]; + continue; + } + + var merged = false; + for (var j = 0; j < tree1[2].length; j++) { + if (tree1[2][j][0] === tree2[2][i][0]) { + queue.push({tree1: tree1[2][j], tree2: tree2[2][i]}); + merged = true; + } + } + if (!merged) { + conflicts = 'new_branch'; + tree1[2].push(tree2[2][i]); + tree1[2].sort(); + } + } + } + return {conflicts: conflicts, tree: in_tree1}; +} + +function doMerge(tree, path, dontExpand) { + var restree = []; + var conflicts = false; + var merged = false; + var res; + + if (!tree.length) { + return {tree: [path], conflicts: 'new_leaf'}; + } + + tree.forEach(function (branch) { + if (branch.pos === path.pos && branch.ids[0] === path.ids[0]) { + // Paths start at the same position and have the same root, so they need + // merged + res = mergeTree(branch.ids, path.ids); + restree.push({pos: branch.pos, ids: res.tree}); + conflicts = conflicts || res.conflicts; + merged = true; + } else if (dontExpand !== true) { + // The paths start at a different position, take the earliest path and + // traverse up until it as at the same point from root as the path we + // want to merge. If the keys match we return the longer path with the + // other merged After stemming we dont want to expand the trees + + var t1 = branch.pos < path.pos ? branch : path; + var t2 = branch.pos < path.pos ? path : branch; + var diff = t2.pos - t1.pos; + + var candidateParents = []; + + var trees = []; + trees.push({ids: t1.ids, diff: diff, parent: null, parentIdx: null}); + while (trees.length > 0) { + var item = trees.pop(); + if (item.diff === 0) { + if (item.ids[0] === t2.ids[0]) { + candidateParents.push(item); + } + continue; + } + if (!item.ids) { + continue; + } + /*jshint loopfunc:true */ + item.ids[2].forEach(function (el, idx) { + trees.push( + {ids: el, diff: item.diff - 1, parent: item.ids, parentIdx: idx}); + }); + } + + var el = candidateParents[0]; + + if (!el) { + restree.push(branch); + } else { + res = mergeTree(el.ids, t2.ids); + el.parent[2][el.parentIdx] = res.tree; + restree.push({pos: t1.pos, ids: t1.ids}); + conflicts = conflicts || res.conflicts; + merged = true; + } + } else { + restree.push(branch); + } + }); + + // We didnt find + if (!merged) { + restree.push(path); + } + + restree.sort(function (a, b) { + return a.pos - b.pos; + }); + + return { + tree: restree, + conflicts: conflicts || 'internal_node' + }; +} + +// To ensure we dont grow the revision tree infinitely, we stem old revisions +function stem(tree, depth) { + // First we break out the tree into a complete list of root to leaf paths, + // we cut off the start of the path and generate a new set of flat trees + var stemmedPaths = PouchMerge.rootToLeaf(tree).map(function (path) { + var stemmed = path.ids.slice(-depth); + return { + pos: path.pos + (path.ids.length - stemmed.length), + ids: pathToTree(stemmed) + }; + }); + // Then we remerge all those flat trees together, ensuring that we dont + // connect trees that would go beyond the depth limit + return stemmedPaths.reduce(function (prev, current, i, arr) { + return doMerge(prev, current, true).tree; + }, [stemmedPaths.shift()]); +} + +var PouchMerge = {}; + +PouchMerge.merge = function (tree, path, depth) { + // Ugh, nicer way to not modify arguments in place? + tree = extend(true, [], tree); + path = extend(true, {}, path); + var newTree = doMerge(tree, path); + return { + tree: stem(newTree.tree, depth), + conflicts: newTree.conflicts + }; +}; + +// We fetch all leafs of the revision tree, and sort them based on tree length +// and whether they were deleted, undeleted documents with the longest revision +// tree (most edits) win +// The final sort algorithm is slightly documented in a sidebar here: +// http://guide.couchdb.org/draft/conflicts.html +PouchMerge.winningRev = function (metadata) { + var leafs = []; + PouchMerge.traverseRevTree(metadata.rev_tree, + function (isLeaf, pos, id, something, opts) { + if (isLeaf) { + leafs.push({pos: pos, id: id, deleted: !!opts.deleted}); + } + }); + leafs.sort(function (a, b) { + if (a.deleted !== b.deleted) { + return a.deleted > b.deleted ? 1 : -1; + } + if (a.pos !== b.pos) { + return b.pos - a.pos; + } + return a.id < b.id ? 1 : -1; + }); + + return leafs[0].pos + '-' + leafs[0].id; +}; + +// Pretty much all below can be combined into a higher order function to +// traverse revisions +// The return value from the callback will be passed as context to all +// children of that node +PouchMerge.traverseRevTree = function (revs, callback) { + var toVisit = revs.slice(); + + var node; + while ((node = toVisit.pop())) { + var pos = node.pos; + var tree = node.ids; + var branches = tree[2]; + var newCtx = + callback(branches.length === 0, pos, tree[0], node.ctx, tree[1]); + for (var i = 0, len = branches.length; i < len; i++) { + toVisit.push({pos: pos + 1, ids: branches[i], ctx: newCtx}); + } + } +}; + +PouchMerge.collectLeaves = function (revs) { + var leaves = []; + PouchMerge.traverseRevTree(revs, function (isLeaf, pos, id, acc, opts) { + if (isLeaf) { + leaves.unshift({rev: pos + "-" + id, pos: pos, opts: opts}); + } + }); + leaves.sort(function (a, b) { + return b.pos - a.pos; + }); + leaves.map(function (leaf) { delete leaf.pos; }); + return leaves; +}; + +// returns revs of all conflicts that is leaves such that +// 1. are not deleted and +// 2. are different than winning revision +PouchMerge.collectConflicts = function (metadata) { + var win = PouchMerge.winningRev(metadata); + var leaves = PouchMerge.collectLeaves(metadata.rev_tree); + var conflicts = []; + leaves.forEach(function (leaf) { + if (leaf.rev !== win && !leaf.opts.deleted) { + conflicts.push(leaf.rev); + } + }); + return conflicts; +}; + +PouchMerge.rootToLeaf = function (tree) { + var paths = []; + PouchMerge.traverseRevTree(tree, function (isLeaf, pos, id, history, opts) { + history = history ? history.slice(0) : []; + history.push({id: id, opts: opts}); + if (isLeaf) { + var rootPos = pos + 1 - history.length; + paths.unshift({pos: rootPos, ids: history}); + } + return history; + }); + return paths; +}; + + +module.exports = PouchMerge; + +},{"pouchdb-extend":116}],11:[function(_dereq_,module,exports){ +(function (global){ +"use strict"; + +var adapterConfig = _dereq_('adapter-config'); +var adapterName = adapterConfig.name; +var adapter = _dereq_('./levelalt')(adapterConfig); +var PouchDB = global.PouchDB || _dereq_('pouchdb'); +PouchDB.adapter(adapterName, adapter); +PouchDB.preferredAdapters.push(adapterName); + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./levelalt":12,"adapter-config":"adapter-config","pouchdb":"pouchdb"}],12:[function(_dereq_,module,exports){ +'use strict'; + +var LevelPouch = _dereq_('../adapters/leveldb'); +var leveldown = _dereq_('leveldown'); +var utils = _dereq_('../utils'); +module.exports = altFactory; +function altFactory(adapterConfig) { + function LevelPouchAlt(opts, callback) { + var _opts = utils.extend({ + db: leveldown + }, opts); + + LevelPouch.call(this, _opts, callback); + } + + // overrides for normal LevelDB behavior on Node + LevelPouchAlt.valid = function () { + return adapterConfig.valid(); + }; + LevelPouchAlt.use_prefix = adapterConfig.use_prefix; + + LevelPouchAlt.destroy = utils.toPromise(function (name, opts, callback) { + if (typeof opts === 'function') { + callback = opts; + opts = {}; + } + var _opts = utils.extend({ + db: leveldown + }, opts); + + return LevelPouch.destroy(name, _opts, callback); + }); + return LevelPouchAlt; + +} +},{"../adapters/leveldb":1,"../utils":13,"leveldown":"leveldown"}],13:[function(_dereq_,module,exports){ +(function (process,global){ +/*jshint strict: false */ +/*global chrome */ +var merge = _dereq_('./merge'); +exports.extend = _dereq_('pouchdb-extend'); +exports.ajax = _dereq_('./deps/ajax'); +exports.createBlob = _dereq_('./deps/blob'); +exports.uuid = _dereq_('./deps/uuid'); +exports.getArguments = _dereq_('argsarray'); +var buffer = _dereq_('./deps/buffer'); +var errors = _dereq_('./deps/errors'); +var EventEmitter = _dereq_('events').EventEmitter; +var collections = _dereq_('./deps/collections'); +exports.Map = collections.Map; +exports.Set = collections.Set; + +if (typeof global.Promise === 'function') { + exports.Promise = global.Promise; +} else { + exports.Promise = _dereq_('bluebird'); +} +var Promise = exports.Promise; + +function toObject(array) { + var obj = {}; + array.forEach(function (item) { obj[item] = true; }); + return obj; +} +// List of top level reserved words for doc +var reservedWords = toObject([ + '_id', + '_rev', + '_attachments', + '_deleted', + '_revisions', + '_revs_info', + '_conflicts', + '_deleted_conflicts', + '_local_seq', + '_rev_tree', + //replication documents + '_replication_id', + '_replication_state', + '_replication_state_time', + '_replication_state_reason', + '_replication_stats' +]); + +// List of reserved words that should end up the document +var dataWords = toObject([ + '_attachments', + //replication documents + '_replication_id', + '_replication_state', + '_replication_state_time', + '_replication_state_reason', + '_replication_stats' +]); + +exports.lastIndexOf = function (str, char) { + for (var i = str.length - 1; i >= 0; i--) { + if (str.charAt(i) === char) { + return i; + } + } + return -1; +}; + +exports.clone = function (obj) { + return exports.extend(true, {}, obj); +}; + +// like underscore/lodash _.pick() +exports.pick = function (obj, arr) { + var res = {}; + for (var i = 0, len = arr.length; i < len; i++) { + var prop = arr[i]; + res[prop] = obj[prop]; + } + return res; +}; + +exports.inherits = _dereq_('inherits'); + +// Determine id an ID is valid +// - invalid IDs begin with an underescore that does not begin '_design' or +// '_local' +// - any other string value is a valid id +// Returns the specific error object for each case +exports.invalidIdError = function (id) { + var err; + if (!id) { + err = new TypeError(errors.MISSING_ID.message); + err.status = 412; + } else if (typeof id !== 'string') { + err = new TypeError(errors.INVALID_ID.message); + err.status = 400; + } else if (/^_/.test(id) && !(/^_(design|local)/).test(id)) { + err = new TypeError(errors.RESERVED_ID.message); + err.status = 400; + } + if (err) { + throw err; + } +}; + +function isChromeApp() { + return (typeof chrome !== "undefined" && + typeof chrome.storage !== "undefined" && + typeof chrome.storage.local !== "undefined"); +} + +// Pretty dumb name for a function, just wraps callback calls so we dont +// to if (callback) callback() everywhere +exports.call = exports.getArguments(function (args) { + if (!args.length) { + return; + } + var fun = args.shift(); + if (typeof fun === 'function') { + fun.apply(this, args); + } +}); + +exports.isLocalId = function (id) { + return (/^_local/).test(id); +}; + +// check if a specific revision of a doc has been deleted +// - metadata: the metadata object from the doc store +// - rev: (optional) the revision to check. defaults to winning revision +exports.isDeleted = function (metadata, rev) { + if (!rev) { + rev = merge.winningRev(metadata); + } + var dashIndex = rev.indexOf('-'); + if (dashIndex !== -1) { + rev = rev.substring(dashIndex + 1); + } + var deleted = false; + merge.traverseRevTree(metadata.rev_tree, + function (isLeaf, pos, id, acc, opts) { + if (id === rev) { + deleted = !!opts.deleted; + } + }); + + return deleted; +}; + +exports.revExists = function (metadata, rev) { + var found = false; + merge.traverseRevTree(metadata.rev_tree, function (leaf, pos, id, acc, opts) { + if ((pos + '-' + id) === rev) { + found = true; + } + }); + return found; +}; + +exports.filterChange = function filterChange(opts) { + var req = {}; + var hasFilter = opts.filter && typeof opts.filter === 'function'; + req.query = opts.query_params; + + return function filter(change) { + if (opts.filter && hasFilter && !opts.filter.call(this, change.doc, req)) { + return false; + } + if (!opts.include_docs) { + delete change.doc; + } else if (!opts.attachments) { + for (var att in change.doc._attachments) { + if (change.doc._attachments.hasOwnProperty(att)) { + change.doc._attachments[att].stub = true; + } + } + } + return true; + }; +}; + +// Preprocess documents, parse their revisions, assign an id and a +// revision for new writes that are missing them, etc +exports.parseDoc = function (doc, newEdits) { + + var nRevNum; + var newRevId; + var revInfo; + var error; + var opts = {status: 'available'}; + if (doc._deleted) { + opts.deleted = true; + } + + if (newEdits) { + if (!doc._id) { + doc._id = exports.uuid(); + } + newRevId = exports.uuid(32, 16).toLowerCase(); + if (doc._rev) { + revInfo = /^(\d+)-(.+)$/.exec(doc._rev); + if (!revInfo) { + error = new Error('bad_request'); + error.message = 'Invalid rev format'; + error.error = true; + return error; + } + doc._rev_tree = [{ + pos: parseInt(revInfo[1], 10), + ids: [revInfo[2], {status: 'missing'}, [[newRevId, opts, []]]] + }]; + nRevNum = parseInt(revInfo[1], 10) + 1; + } else { + doc._rev_tree = [{ + pos: 1, + ids : [newRevId, opts, []] + }]; + nRevNum = 1; + } + } else { + if (doc._revisions) { + doc._rev_tree = [{ + pos: doc._revisions.start - doc._revisions.ids.length + 1, + ids: doc._revisions.ids.reduce(function (acc, x) { + if (acc === null) { + return [x, opts, []]; + } else { + return [x, {status: 'missing'}, [acc]]; + } + }, null) + }]; + nRevNum = doc._revisions.start; + newRevId = doc._revisions.ids[0]; + } + if (!doc._rev_tree) { + revInfo = /^(\d+)-(.+)$/.exec(doc._rev); + if (!revInfo) { + error = new Error('bad_request'); + error.message = 'Invalid rev format'; + error.error = true; + return error; + } + nRevNum = parseInt(revInfo[1], 10); + newRevId = revInfo[2]; + doc._rev_tree = [{ + pos: parseInt(revInfo[1], 10), + ids: [revInfo[2], opts, []] + }]; + } + } + + exports.invalidIdError(doc._id); + + doc._rev = [nRevNum, newRevId].join('-'); + + var result = {metadata : {}, data : {}}; + for (var key in doc) { + if (doc.hasOwnProperty(key)) { + var specialKey = key[0] === '_'; + if (specialKey && !reservedWords[key]) { + error = new Error(errors.DOC_VALIDATION.message + ': ' + key); + error.status = errors.DOC_VALIDATION.status; + throw error; + } else if (specialKey && !dataWords[key]) { + result.metadata[key.slice(1)] = doc[key]; + } else { + result.data[key] = doc[key]; + } + } + } + return result; +}; + +exports.isCordova = function () { + return (typeof cordova !== "undefined" || + typeof PhoneGap !== "undefined" || + typeof phonegap !== "undefined"); +}; + +exports.hasLocalStorage = function () { + if (isChromeApp()) { + return false; + } + try { + return global.localStorage; + } catch (e) { + return false; + } +}; +exports.Changes = Changes; +exports.inherits(Changes, EventEmitter); +function Changes() { + if (!(this instanceof Changes)) { + return new Changes(); + } + var self = this; + EventEmitter.call(this); + this.isChrome = isChromeApp(); + this.listeners = {}; + this.hasLocal = false; + if (!this.isChrome) { + this.hasLocal = exports.hasLocalStorage(); + } + if (this.isChrome) { + chrome.storage.onChanged.addListener(function (e) { + // make sure it's event addressed to us + if (e.db_name != null) { + //object only has oldValue, newValue members + self.emit(e.dbName.newValue); + } + }); + } else if (this.hasLocal) { + if (global.addEventListener) { + global.addEventListener("storage", function (e) { + self.emit(e.key); + }); + } else { + global.attachEvent("storage", function (e) { + self.emit(e.key); + }); + } + } + +} +Changes.prototype.addListener = function (dbName, id, db, opts) { + if (this.listeners[id]) { + return; + } + function eventFunction() { + db.changes({ + include_docs: opts.include_docs, + attachments: opts.attachments, + conflicts: opts.conflicts, + continuous: false, + descending: false, + filter: opts.filter, + doc_ids: opts.doc_ids, + view: opts.view, + since: opts.since, + query_params: opts.query_params, + onChange: function (c) { + if (c.seq > opts.since && !opts.cancelled) { + opts.since = c.seq; + exports.call(opts.onChange, c); + } + } + }); + } + this.listeners[id] = eventFunction; + this.on(dbName, eventFunction); +}; + +Changes.prototype.removeListener = function (dbName, id) { + if (!(id in this.listeners)) { + return; + } + EventEmitter.prototype.removeListener.call(this, dbName, + this.listeners[id]); +}; + + +Changes.prototype.notifyLocalWindows = function (dbName) { + //do a useless change on a storage thing + //in order to get other windows's listeners to activate + if (this.isChrome) { + chrome.storage.local.set({dbName: dbName}); + } else if (this.hasLocal) { + localStorage[dbName] = (localStorage[dbName] === "a") ? "b" : "a"; + } +}; + +Changes.prototype.notify = function (dbName) { + this.emit(dbName); + this.notifyLocalWindows(dbName); +}; + +if (!process.browser || !('atob' in global)) { + exports.atob = function (str) { + var base64 = new buffer(str, 'base64'); + // Node.js will just skip the characters it can't encode instead of + // throwing and exception + if (base64.toString('base64') !== str) { + throw ("Cannot base64 encode full string"); + } + return base64.toString('binary'); + }; +} else { + exports.atob = function (str) { + return atob(str); + }; +} + +if (!process.browser || !('btoa' in global)) { + exports.btoa = function (str) { + return new buffer(str, 'binary').toString('base64'); + }; +} else { + exports.btoa = function (str) { + return btoa(str); + }; +} + +// From http://stackoverflow.com/questions/14967647/ (continues on next line) +// encode-decode-image-with-base64-breaks-image (2013-04-21) +exports.fixBinary = function (bin) { + if (!process.browser) { + // don't need to do this in Node + return bin; + } + + var length = bin.length; + var buf = new ArrayBuffer(length); + var arr = new Uint8Array(buf); + for (var i = 0; i < length; i++) { + arr[i] = bin.charCodeAt(i); + } + return buf; +}; + +// shim for browsers that don't support it +exports.readAsBinaryString = function (blob, callback) { + var reader = new FileReader(); + var hasBinaryString = typeof reader.readAsBinaryString === 'function'; + reader.onloadend = function (e) { + var result = e.target.result || ''; + if (hasBinaryString) { + return callback(result); + } + callback(exports.arrayBufferToBinaryString(result)); + }; + if (hasBinaryString) { + reader.readAsBinaryString(blob); + } else { + reader.readAsArrayBuffer(blob); + } +}; + +exports.once = function (fun) { + var called = false; + return exports.getArguments(function (args) { + if (called) { + throw new Error('once called more than once'); + } else { + called = true; + fun.apply(this, args); + } + }); +}; + +exports.toPromise = function (func) { + //create the function we will be returning + return exports.getArguments(function (args) { + var self = this; + var tempCB = + (typeof args[args.length - 1] === 'function') ? args.pop() : false; + // if the last argument is a function, assume its a callback + var usedCB; + if (tempCB) { + // if it was a callback, create a new callback which calls it, + // but do so async so we don't trap any errors + usedCB = function (err, resp) { + process.nextTick(function () { + tempCB(err, resp); + }); + }; + } + var promise = new Promise(function (fulfill, reject) { + var resp; + try { + var callback = exports.once(function (err, mesg) { + if (err) { + reject(err); + } else { + fulfill(mesg); + } + }); + // create a callback for this invocation + // apply the function in the orig context + args.push(callback); + resp = func.apply(self, args); + if (resp && typeof resp.then === 'function') { + fulfill(resp); + } + } catch (e) { + reject(e); + } + }); + // if there is a callback, call it back + if (usedCB) { + promise.then(function (result) { + usedCB(null, result); + }, usedCB); + } + promise.cancel = function () { + return this; + }; + return promise; + }); +}; + +exports.adapterFun = function (name, callback) { + var log = _dereq_('debug')('pouchdb:api'); + + function logApiCall(self, name, args) { + if (!log.enabled) { + return; + } + var logArgs = [self._db_name, name]; + for (var i = 0; i < args.length - 1; i++) { + logArgs.push(args[i]); + } + log.apply(null, logArgs); + + // override the callback itself to log the response + var origCallback = args[args.length - 1]; + args[args.length - 1] = function (err, res) { + var responseArgs = [self._db_name, name]; + responseArgs = responseArgs.concat( + err ? ['error', err] : ['success', res] + ); + log.apply(null, responseArgs); + origCallback(err, res); + }; + } + + + return exports.toPromise(exports.getArguments(function (args) { + if (this._closed) { + return Promise.reject(new Error('database is closed')); + } + var self = this; + logApiCall(self, name, args); + if (!this.taskqueue.isReady) { + return new exports.Promise(function (fulfill, reject) { + self.taskqueue.addTask(function (failed) { + if (failed) { + reject(failed); + } else { + fulfill(self[name].apply(self, args)); + } + }); + }); + } + return callback.apply(this, args); + })); +}; + +//Can't find original post, but this is close +//http://stackoverflow.com/questions/6965107/ (continues on next line) +//converting-between-strings-and-arraybuffers +exports.arrayBufferToBinaryString = function (buffer) { + var binary = ""; + var bytes = new Uint8Array(buffer); + var length = bytes.byteLength; + for (var i = 0; i < length; i++) { + binary += String.fromCharCode(bytes[i]); + } + return binary; +}; + +exports.cancellableFun = function (fun, self, opts) { + + opts = opts ? exports.clone(true, {}, opts) : {}; + + var emitter = new EventEmitter(); + var oldComplete = opts.complete || function () { }; + var complete = opts.complete = exports.once(function (err, resp) { + if (err) { + oldComplete(err); + } else { + emitter.emit('end', resp); + oldComplete(null, resp); + } + emitter.removeAllListeners(); + }); + var oldOnChange = opts.onChange || function () {}; + var lastChange = 0; + self.on('destroyed', function () { + emitter.removeAllListeners(); + }); + opts.onChange = function (change) { + oldOnChange(change); + if (change.seq <= lastChange) { + return; + } + lastChange = change.seq; + emitter.emit('change', change); + if (change.deleted) { + emitter.emit('delete', change); + } else if (change.changes.length === 1 && + change.changes[0].rev.slice(0, 1) === '1-') { + emitter.emit('create', change); + } else { + emitter.emit('update', change); + } + }; + var promise = new Promise(function (fulfill, reject) { + opts.complete = function (err, res) { + if (err) { + reject(err); + } else { + fulfill(res); + } + }; + }); + + promise.then(function (result) { + complete(null, result); + }, complete); + + // this needs to be overwridden by caller, dont fire complete until + // the task is ready + promise.cancel = function () { + promise.isCancelled = true; + if (self.taskqueue.isReady) { + opts.complete(null, {status: 'cancelled'}); + } + }; + + if (!self.taskqueue.isReady) { + self.taskqueue.addTask(function () { + if (promise.isCancelled) { + opts.complete(null, {status: 'cancelled'}); + } else { + fun(self, opts, promise); + } + }); + } else { + fun(self, opts, promise); + } + promise.on = emitter.on.bind(emitter); + promise.once = emitter.once.bind(emitter); + promise.addListener = emitter.addListener.bind(emitter); + promise.removeListener = emitter.removeListener.bind(emitter); + promise.removeAllListeners = emitter.removeAllListeners.bind(emitter); + promise.setMaxListeners = emitter.setMaxListeners.bind(emitter); + promise.listeners = emitter.listeners.bind(emitter); + promise.emit = emitter.emit.bind(emitter); + return promise; +}; + +exports.MD5 = exports.toPromise(_dereq_('./deps/md5')); + +// designed to give info to browser users, who are disturbed +// when they see 404s in the console +exports.explain404 = function (str) { + if (process.browser && 'console' in global && 'info' in console) { + console.info('The above 404 is totally normal. ' + str); + } +}; + +exports.parseUri = _dereq_('./deps/parse-uri'); + +exports.compare = function (left, right) { + return left < right ? -1 : left > right ? 1 : 0; +}; + +exports.updateDoc = function updateDoc(prev, docInfo, results, + i, cb, write, newEdits) { + + if (exports.revExists(prev, docInfo.metadata.rev)) { + results[i] = docInfo; + return cb(); + } + + var previouslyDeleted = exports.isDeleted(prev); + var deleted = exports.isDeleted(docInfo.metadata); + var isRoot = /^1-/.test(docInfo.metadata.rev); + + if (previouslyDeleted && !deleted && newEdits && isRoot) { + var newDoc = docInfo.data; + newDoc._rev = merge.winningRev(prev); + newDoc._id = docInfo.metadata.id; + docInfo = exports.parseDoc(newDoc, newEdits); + } + + var merged = merge.merge(prev.rev_tree, docInfo.metadata.rev_tree[0], 1000); + + var inConflict = newEdits && (((previouslyDeleted && deleted) || + (!previouslyDeleted && merged.conflicts !== 'new_leaf') || + (previouslyDeleted && !deleted && merged.conflicts === 'new_branch'))); + + if (inConflict) { + var err = errors.REV_CONFLICT; + results[i] = err; + return cb(); + } + + docInfo.metadata.rev_tree = merged.tree; + + // recalculate + var winningRev = merge.winningRev(docInfo.metadata); + deleted = exports.isDeleted(docInfo.metadata, winningRev); + + write(docInfo, winningRev, deleted, cb, true, i); +}; + +exports.processDocs = function processDocs(docInfos, api, fetchedDocs, + tx, results, writeDoc, opts) { + + if (!docInfos.length) { + return; + } + + function insertDoc(docInfo, resultsIdx, callback) { + // Cant insert new deleted documents + var winningRev = merge.winningRev(docInfo.metadata); + var deleted = exports.isDeleted(docInfo.metadata, winningRev); + if ('was_delete' in opts && deleted) { + results[resultsIdx] = errors.MISSING_DOC; + return callback(); + } + writeDoc(docInfo, winningRev, deleted, callback, false, resultsIdx); + } + + var newEdits = opts.new_edits; + var idsToDocs = new exports.Map(); + + docInfos.forEach(function (currentDoc, resultsIdx) { + + if (currentDoc._id && exports.isLocalId(currentDoc._id)) { + api[currentDoc._deleted ? '_removeLocal' : '_putLocal']( + currentDoc, {ctx: tx}, function (err, resp) { + if (err) { + results[resultsIdx] = err; + } else { + results[resultsIdx] = {}; + } + }); + return; + } + + var id = currentDoc.metadata.id; + if (idsToDocs.has(id)) { + idsToDocs.get(id).push([currentDoc, resultsIdx]); + } else { + idsToDocs.set(id, [[currentDoc, resultsIdx]]); + } + }); + + // in the case of new_edits, the user can provide multiple docs + // with the same id. these need to be processed sequentially + idsToDocs.forEach(function (docs, id) { + var numDone = 0; + + function docWritten() { + if (++numDone < docs.length) { + nextDoc(); + } + } + function nextDoc() { + var value = docs[numDone]; + var currentDoc = value[0]; + var resultsIdx = value[1]; + + if (fetchedDocs.has(id)) { + exports.updateDoc(fetchedDocs.get(id), currentDoc, results, + resultsIdx, docWritten, writeDoc, newEdits); + } else { + insertDoc(currentDoc, resultsIdx, docWritten); + } + } + nextDoc(); + }); +}; + +exports.preprocessAttachments = function preprocessAttachments( + docInfos, blobType, callback) { + + if (!docInfos.length) { + return callback(); + } + + var docv = 0; + + function parseBase64(data) { + try { + return exports.atob(data); + } catch (e) { + var err = errors.error(errors.BAD_ARG, + "Attachments need to be base64 encoded"); + return {error: err}; + } + } + + function preprocessAttachment(att, callback) { + if (att.stub) { + return callback(); + } + if (typeof att.data === 'string') { + // input is a base64 string + + var asBinary = parseBase64(att.data); + if (asBinary.error) { + return callback(asBinary.error); + } + + att.length = asBinary.length; + if (blobType === 'blob') { + att.data = exports.createBlob([exports.fixBinary(asBinary)], + {type: att.content_type}); + } else if (blobType === 'base64') { + att.data = exports.btoa(asBinary); + } else { // binary + att.data = asBinary; + } + exports.MD5(asBinary).then(function (result) { + att.digest = 'md5-' + result; + callback(); + }); + } else { // input is a blob + exports.readAsBinaryString(att.data, function (binary) { + if (blobType === 'binary') { + att.data = binary; + } else if (blobType === 'base64') { + att.data = exports.btoa(binary); + } + exports.MD5(binary).then(function (result) { + att.digest = 'md5-' + result; + att.length = binary.length; + callback(); + }); + }); + } + } + + var overallErr; + + docInfos.forEach(function (docInfo) { + var attachments = docInfo.data && docInfo.data._attachments ? + Object.keys(docInfo.data._attachments) : []; + var recv = 0; + + if (!attachments.length) { + return done(); + } + + function processedAttachment(err) { + overallErr = err; + recv++; + if (recv === attachments.length) { + done(); + } + } + + for (var key in docInfo.data._attachments) { + if (docInfo.data._attachments.hasOwnProperty(key)) { + preprocessAttachment(docInfo.data._attachments[key], + processedAttachment); + } + } + }); + + function done() { + docv++; + if (docInfos.length === docv) { + if (overallErr) { + callback(overallErr); + } else { + callback(); + } + } + } +}; +}).call(this,_dereq_('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./deps/ajax":2,"./deps/blob":3,"./deps/buffer":16,"./deps/collections":4,"./deps/errors":5,"./deps/md5":6,"./deps/parse-uri":8,"./deps/uuid":9,"./merge":10,"_process":24,"argsarray":14,"bluebird":101,"debug":40,"events":21,"inherits":44,"pouchdb-extend":116}],14:[function(_dereq_,module,exports){ +'use strict'; + +module.exports = argsArray; + +function argsArray(fun) { + return function () { + var len = arguments.length; + if (len) { + var args = []; + var i = -1; + while (++i < len) { + args[i] = arguments[i]; + } + return fun.call(this, args); + } else { + return fun.call(this, []); + } + }; +} +},{}],15:[function(_dereq_,module,exports){ + +},{}],16:[function(_dereq_,module,exports){ +module.exports=_dereq_(15) +},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/lib/_empty.js":15}],17:[function(_dereq_,module,exports){ +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org> + * @license MIT + */ + +var base64 = _dereq_('base64-js') +var ieee754 = _dereq_('ieee754') +var isArray = _dereq_('is-array') + +exports.Buffer = Buffer +exports.SlowBuffer = Buffer +exports.INSPECT_MAX_BYTES = 50 +Buffer.poolSize = 8192 // not used by this implementation + +var kMaxLength = 0x3fffffff + +/** + * If `Buffer.TYPED_ARRAY_SUPPORT`: + * === true Use Uint8Array implementation (fastest) + * === false Use Object implementation (most compatible, even IE6) + * + * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, + * Opera 11.6+, iOS 4.2+. + * + * Note: + * + * - Implementation must support adding new properties to `Uint8Array` instances. + * Firefox 4-29 lacked support, fixed in Firefox 30+. + * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. + * + * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. + * + * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of + * incorrect length in some situations. + * + * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they will + * get the Object implementation, which is slower but will work correctly. + */ +Buffer.TYPED_ARRAY_SUPPORT = (function () { + try { + var buf = new ArrayBuffer(0) + var arr = new Uint8Array(buf) + arr.foo = function () { return 42 } + return 42 === arr.foo() && // typed array instances can be augmented + typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` + new Uint8Array(1).subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` + } catch (e) { + return false + } +})() + +/** + * Class: Buffer + * ============= + * + * The Buffer constructor returns instances of `Uint8Array` that are augmented + * with function properties for all the node `Buffer` API functions. We use + * `Uint8Array` so that square bracket notation works as expected -- it returns + * a single octet. + * + * By augmenting the instances, we can avoid modifying the `Uint8Array` + * prototype. + */ +function Buffer (subject, encoding, noZero) { + if (!(this instanceof Buffer)) + return new Buffer(subject, encoding, noZero) + + var type = typeof subject + + // Find the length + var length + if (type === 'number') + length = subject > 0 ? subject >>> 0 : 0 + else if (type === 'string') { + if (encoding === 'base64') + subject = base64clean(subject) + length = Buffer.byteLength(subject, encoding) + } else if (type === 'object' && subject !== null) { // assume object is array-like + if (subject.type === 'Buffer' && isArray(subject.data)) + subject = subject.data + length = +subject.length > 0 ? Math.floor(+subject.length) : 0 + } else + throw new TypeError('must start with number, buffer, array or string') + + if (this.length > kMaxLength) + throw new RangeError('Attempt to allocate Buffer larger than maximum ' + + 'size: 0x' + kMaxLength.toString(16) + ' bytes') + + var buf + if (Buffer.TYPED_ARRAY_SUPPORT) { + // Preferred: Return an augmented `Uint8Array` instance for best performance + buf = Buffer._augment(new Uint8Array(length)) + } else { + // Fallback: Return THIS instance of Buffer (created by `new`) + buf = this + buf.length = length + buf._isBuffer = true + } + + var i + if (Buffer.TYPED_ARRAY_SUPPORT && typeof subject.byteLength === 'number') { + // Speed optimization -- use set if we're copying from a typed array + buf._set(subject) + } else if (isArrayish(subject)) { + // Treat array-ish objects as a byte array + if (Buffer.isBuffer(subject)) { + for (i = 0; i < length; i++) + buf[i] = subject.readUInt8(i) + } else { + for (i = 0; i < length; i++) + buf[i] = ((subject[i] % 256) + 256) % 256 + } + } else if (type === 'string') { + buf.write(subject, 0, encoding) + } else if (type === 'number' && !Buffer.TYPED_ARRAY_SUPPORT && !noZero) { + for (i = 0; i < length; i++) { + buf[i] = 0 + } + } + + return buf +} + +Buffer.isBuffer = function (b) { + return !!(b != null && b._isBuffer) +} + +Buffer.compare = function (a, b) { + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) + throw new TypeError('Arguments must be Buffers') + + var x = a.length + var y = b.length + for (var i = 0, len = Math.min(x, y); i < len && a[i] === b[i]; i++) {} + if (i !== len) { + x = a[i] + y = b[i] + } + if (x < y) return -1 + if (y < x) return 1 + return 0 +} + +Buffer.isEncoding = function (encoding) { + switch (String(encoding).toLowerCase()) { + case 'hex': + case 'utf8': + case 'utf-8': + case 'ascii': + case 'binary': + case 'base64': + case 'raw': + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return true + default: + return false + } +} + +Buffer.concat = function (list, totalLength) { + if (!isArray(list)) throw new TypeError('Usage: Buffer.concat(list[, length])') + + if (list.length === 0) { + return new Buffer(0) + } else if (list.length === 1) { + return list[0] + } + + var i + if (totalLength === undefined) { + totalLength = 0 + for (i = 0; i < list.length; i++) { + totalLength += list[i].length + } + } + + var buf = new Buffer(totalLength) + var pos = 0 + for (i = 0; i < list.length; i++) { + var item = list[i] + item.copy(buf, pos) + pos += item.length + } + return buf +} + +Buffer.byteLength = function (str, encoding) { + var ret + str = str + '' + switch (encoding || 'utf8') { + case 'ascii': + case 'binary': + case 'raw': + ret = str.length + break + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + ret = str.length * 2 + break + case 'hex': + ret = str.length >>> 1 + break + case 'utf8': + case 'utf-8': + ret = utf8ToBytes(str).length + break + case 'base64': + ret = base64ToBytes(str).length + break + default: + ret = str.length + } + return ret +} + +// pre-set for values that may exist in the future +Buffer.prototype.length = undefined +Buffer.prototype.parent = undefined + +// toString(encoding, start=0, end=buffer.length) +Buffer.prototype.toString = function (encoding, start, end) { + var loweredCase = false + + start = start >>> 0 + end = end === undefined || end === Infinity ? this.length : end >>> 0 + + if (!encoding) encoding = 'utf8' + if (start < 0) start = 0 + if (end > this.length) end = this.length + if (end <= start) return '' + + while (true) { + switch (encoding) { + case 'hex': + return hexSlice(this, start, end) + + case 'utf8': + case 'utf-8': + return utf8Slice(this, start, end) + + case 'ascii': + return asciiSlice(this, start, end) + + case 'binary': + return binarySlice(this, start, end) + + case 'base64': + return base64Slice(this, start, end) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return utf16leSlice(this, start, end) + + default: + if (loweredCase) + throw new TypeError('Unknown encoding: ' + encoding) + encoding = (encoding + '').toLowerCase() + loweredCase = true + } + } +} + +Buffer.prototype.equals = function (b) { + if(!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + return Buffer.compare(this, b) === 0 +} + +Buffer.prototype.inspect = function () { + var str = '' + var max = exports.INSPECT_MAX_BYTES + if (this.length > 0) { + str = this.toString('hex', 0, max).match(/.{2}/g).join(' ') + if (this.length > max) + str += ' ... ' + } + return '<Buffer ' + str + '>' +} + +Buffer.prototype.compare = function (b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + return Buffer.compare(this, b) +} + +// `get` will be removed in Node 0.13+ +Buffer.prototype.get = function (offset) { + console.log('.get() is deprecated. Access using array indexes instead.') + return this.readUInt8(offset) +} + +// `set` will be removed in Node 0.13+ +Buffer.prototype.set = function (v, offset) { + console.log('.set() is deprecated. Access using array indexes instead.') + return this.writeUInt8(v, offset) +} + +function hexWrite (buf, string, offset, length) { + offset = Number(offset) || 0 + var remaining = buf.length - offset + if (!length) { + length = remaining + } else { + length = Number(length) + if (length > remaining) { + length = remaining + } + } + + // must be an even number of digits + var strLen = string.length + if (strLen % 2 !== 0) throw new Error('Invalid hex string') + + if (length > strLen / 2) { + length = strLen / 2 + } + for (var i = 0; i < length; i++) { + var byte = parseInt(string.substr(i * 2, 2), 16) + if (isNaN(byte)) throw new Error('Invalid hex string') + buf[offset + i] = byte + } + return i +} + +function utf8Write (buf, string, offset, length) { + var charsWritten = blitBuffer(utf8ToBytes(string), buf, offset, length) + return charsWritten +} + +function asciiWrite (buf, string, offset, length) { + var charsWritten = blitBuffer(asciiToBytes(string), buf, offset, length) + return charsWritten +} + +function binaryWrite (buf, string, offset, length) { + return asciiWrite(buf, string, offset, length) +} + +function base64Write (buf, string, offset, length) { + var charsWritten = blitBuffer(base64ToBytes(string), buf, offset, length) + return charsWritten +} + +function utf16leWrite (buf, string, offset, length) { + var charsWritten = blitBuffer(utf16leToBytes(string), buf, offset, length) + return charsWritten +} + +Buffer.prototype.write = function (string, offset, length, encoding) { + // Support both (string, offset, length, encoding) + // and the legacy (string, encoding, offset, length) + if (isFinite(offset)) { + if (!isFinite(length)) { + encoding = length + length = undefined + } + } else { // legacy + var swap = encoding + encoding = offset + offset = length + length = swap + } + + offset = Number(offset) || 0 + var remaining = this.length - offset + if (!length) { + length = remaining + } else { + length = Number(length) + if (length > remaining) { + length = remaining + } + } + encoding = String(encoding || 'utf8').toLowerCase() + + var ret + switch (encoding) { + case 'hex': + ret = hexWrite(this, string, offset, length) + break + case 'utf8': + case 'utf-8': + ret = utf8Write(this, string, offset, length) + break + case 'ascii': + ret = asciiWrite(this, string, offset, length) + break + case 'binary': + ret = binaryWrite(this, string, offset, length) + break + case 'base64': + ret = base64Write(this, string, offset, length) + break + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + ret = utf16leWrite(this, string, offset, length) + break + default: + throw new TypeError('Unknown encoding: ' + encoding) + } + return ret +} + +Buffer.prototype.toJSON = function () { + return { + type: 'Buffer', + data: Array.prototype.slice.call(this._arr || this, 0) + } +} + +function base64Slice (buf, start, end) { + if (start === 0 && end === buf.length) { + return base64.fromByteArray(buf) + } else { + return base64.fromByteArray(buf.slice(start, end)) + } +} + +function utf8Slice (buf, start, end) { + var res = '' + var tmp = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; i++) { + if (buf[i] <= 0x7F) { + res += decodeUtf8Char(tmp) + String.fromCharCode(buf[i]) + tmp = '' + } else { + tmp += '%' + buf[i].toString(16) + } + } + + return res + decodeUtf8Char(tmp) +} + +function asciiSlice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; i++) { + ret += String.fromCharCode(buf[i]) + } + return ret +} + +function binarySlice (buf, start, end) { + return asciiSlice(buf, start, end) +} + +function hexSlice (buf, start, end) { + var len = buf.length + + if (!start || start < 0) start = 0 + if (!end || end < 0 || end > len) end = len + + var out = '' + for (var i = start; i < end; i++) { + out += toHex(buf[i]) + } + return out +} + +function utf16leSlice (buf, start, end) { + var bytes = buf.slice(start, end) + var res = '' + for (var i = 0; i < bytes.length; i += 2) { + res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256) + } + return res +} + +Buffer.prototype.slice = function (start, end) { + var len = this.length + start = ~~start + end = end === undefined ? len : ~~end + + if (start < 0) { + start += len; + if (start < 0) + start = 0 + } else if (start > len) { + start = len + } + + if (end < 0) { + end += len + if (end < 0) + end = 0 + } else if (end > len) { + end = len + } + + if (end < start) + end = start + + if (Buffer.TYPED_ARRAY_SUPPORT) { + return Buffer._augment(this.subarray(start, end)) + } else { + var sliceLen = end - start + var newBuf = new Buffer(sliceLen, undefined, true) + for (var i = 0; i < sliceLen; i++) { + newBuf[i] = this[i + start] + } + return newBuf + } +} + +/* + * Need to make sure that buffer isn't trying to write out of bounds. + */ +function checkOffset (offset, ext, length) { + if ((offset % 1) !== 0 || offset < 0) + throw new RangeError('offset is not uint') + if (offset + ext > length) + throw new RangeError('Trying to access beyond buffer length') +} + +Buffer.prototype.readUInt8 = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 1, this.length) + return this[offset] +} + +Buffer.prototype.readUInt16LE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 2, this.length) + return this[offset] | (this[offset + 1] << 8) +} + +Buffer.prototype.readUInt16BE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 2, this.length) + return (this[offset] << 8) | this[offset + 1] +} + +Buffer.prototype.readUInt32LE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length) + + return ((this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16)) + + (this[offset + 3] * 0x1000000) +} + +Buffer.prototype.readUInt32BE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length) + + return (this[offset] * 0x1000000) + + ((this[offset + 1] << 16) | + (this[offset + 2] << 8) | + this[offset + 3]) +} + +Buffer.prototype.readInt8 = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 1, this.length) + if (!(this[offset] & 0x80)) + return (this[offset]) + return ((0xff - this[offset] + 1) * -1) +} + +Buffer.prototype.readInt16LE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 2, this.length) + var val = this[offset] | (this[offset + 1] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt16BE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 2, this.length) + var val = this[offset + 1] | (this[offset] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt32LE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length) + + return (this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16) | + (this[offset + 3] << 24) +} + +Buffer.prototype.readInt32BE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length) + + return (this[offset] << 24) | + (this[offset + 1] << 16) | + (this[offset + 2] << 8) | + (this[offset + 3]) +} + +Buffer.prototype.readFloatLE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, true, 23, 4) +} + +Buffer.prototype.readFloatBE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, false, 23, 4) +} + +Buffer.prototype.readDoubleLE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, true, 52, 8) +} + +Buffer.prototype.readDoubleBE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, false, 52, 8) +} + +function checkInt (buf, value, offset, ext, max, min) { + if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance') + if (value > max || value < min) throw new TypeError('value is out of bounds') + if (offset + ext > buf.length) throw new TypeError('index out of range') +} + +Buffer.prototype.writeUInt8 = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 1, 0xff, 0) + if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) + this[offset] = value + return offset + 1 +} + +function objectWriteUInt16 (buf, value, offset, littleEndian) { + if (value < 0) value = 0xffff + value + 1 + for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) { + buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> + (littleEndian ? i : 1 - i) * 8 + } +} + +Buffer.prototype.writeUInt16LE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 2, 0xffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = value + this[offset + 1] = (value >>> 8) + } else objectWriteUInt16(this, value, offset, true) + return offset + 2 +} + +Buffer.prototype.writeUInt16BE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 2, 0xffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 8) + this[offset + 1] = value + } else objectWriteUInt16(this, value, offset, false) + return offset + 2 +} + +function objectWriteUInt32 (buf, value, offset, littleEndian) { + if (value < 0) value = 0xffffffff + value + 1 + for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) { + buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff + } +} + +Buffer.prototype.writeUInt32LE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 4, 0xffffffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset + 3] = (value >>> 24) + this[offset + 2] = (value >>> 16) + this[offset + 1] = (value >>> 8) + this[offset] = value + } else objectWriteUInt32(this, value, offset, true) + return offset + 4 +} + +Buffer.prototype.writeUInt32BE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 4, 0xffffffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = value + } else objectWriteUInt32(this, value, offset, false) + return offset + 4 +} + +Buffer.prototype.writeInt8 = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 1, 0x7f, -0x80) + if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) + if (value < 0) value = 0xff + value + 1 + this[offset] = value + return offset + 1 +} + +Buffer.prototype.writeInt16LE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 2, 0x7fff, -0x8000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = value + this[offset + 1] = (value >>> 8) + } else objectWriteUInt16(this, value, offset, true) + return offset + 2 +} + +Buffer.prototype.writeInt16BE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 2, 0x7fff, -0x8000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 8) + this[offset + 1] = value + } else objectWriteUInt16(this, value, offset, false) + return offset + 2 +} + +Buffer.prototype.writeInt32LE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = value + this[offset + 1] = (value >>> 8) + this[offset + 2] = (value >>> 16) + this[offset + 3] = (value >>> 24) + } else objectWriteUInt32(this, value, offset, true) + return offset + 4 +} + +Buffer.prototype.writeInt32BE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (value < 0) value = 0xffffffff + value + 1 + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = value + } else objectWriteUInt32(this, value, offset, false) + return offset + 4 +} + +function checkIEEE754 (buf, value, offset, ext, max, min) { + if (value > max || value < min) throw new TypeError('value is out of bounds') + if (offset + ext > buf.length) throw new TypeError('index out of range') +} + +function writeFloat (buf, value, offset, littleEndian, noAssert) { + if (!noAssert) + checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) + ieee754.write(buf, value, offset, littleEndian, 23, 4) + return offset + 4 +} + +Buffer.prototype.writeFloatLE = function (value, offset, noAssert) { + return writeFloat(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeFloatBE = function (value, offset, noAssert) { + return writeFloat(this, value, offset, false, noAssert) +} + +function writeDouble (buf, value, offset, littleEndian, noAssert) { + if (!noAssert) + checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) + ieee754.write(buf, value, offset, littleEndian, 52, 8) + return offset + 8 +} + +Buffer.prototype.writeDoubleLE = function (value, offset, noAssert) { + return writeDouble(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeDoubleBE = function (value, offset, noAssert) { + return writeDouble(this, value, offset, false, noAssert) +} + +// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) +Buffer.prototype.copy = function (target, target_start, start, end) { + var source = this + + if (!start) start = 0 + if (!end && end !== 0) end = this.length + if (!target_start) target_start = 0 + + // Copy 0 bytes; we're done + if (end === start) return + if (target.length === 0 || source.length === 0) return + + // Fatal error conditions + if (end < start) throw new TypeError('sourceEnd < sourceStart') + if (target_start < 0 || target_start >= target.length) + throw new TypeError('targetStart out of bounds') + if (start < 0 || start >= source.length) throw new TypeError('sourceStart out of bounds') + if (end < 0 || end > source.length) throw new TypeError('sourceEnd out of bounds') + + // Are we oob? + if (end > this.length) + end = this.length + if (target.length - target_start < end - start) + end = target.length - target_start + start + + var len = end - start + + if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) { + for (var i = 0; i < len; i++) { + target[i + target_start] = this[i + start] + } + } else { + target._set(this.subarray(start, start + len), target_start) + } +} + +// fill(value, start=0, end=buffer.length) +Buffer.prototype.fill = function (value, start, end) { + if (!value) value = 0 + if (!start) start = 0 + if (!end) end = this.length + + if (end < start) throw new TypeError('end < start') + + // Fill 0 bytes; we're done + if (end === start) return + if (this.length === 0) return + + if (start < 0 || start >= this.length) throw new TypeError('start out of bounds') + if (end < 0 || end > this.length) throw new TypeError('end out of bounds') + + var i + if (typeof value === 'number') { + for (i = start; i < end; i++) { + this[i] = value + } + } else { + var bytes = utf8ToBytes(value.toString()) + var len = bytes.length + for (i = start; i < end; i++) { + this[i] = bytes[i % len] + } + } + + return this +} + +/** + * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance. + * Added in Node 0.12. Only available in browsers that support ArrayBuffer. + */ +Buffer.prototype.toArrayBuffer = function () { + if (typeof Uint8Array !== 'undefined') { + if (Buffer.TYPED_ARRAY_SUPPORT) { + return (new Buffer(this)).buffer + } else { + var buf = new Uint8Array(this.length) + for (var i = 0, len = buf.length; i < len; i += 1) { + buf[i] = this[i] + } + return buf.buffer + } + } else { + throw new TypeError('Buffer.toArrayBuffer not supported in this browser') + } +} + +// HELPER FUNCTIONS +// ================ + +var BP = Buffer.prototype + +/** + * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods + */ +Buffer._augment = function (arr) { + arr.constructor = Buffer + arr._isBuffer = true + + // save reference to original Uint8Array get/set methods before overwriting + arr._get = arr.get + arr._set = arr.set + + // deprecated, will be removed in node 0.13+ + arr.get = BP.get + arr.set = BP.set + + arr.write = BP.write + arr.toString = BP.toString + arr.toLocaleString = BP.toString + arr.toJSON = BP.toJSON + arr.equals = BP.equals + arr.compare = BP.compare + arr.copy = BP.copy + arr.slice = BP.slice + arr.readUInt8 = BP.readUInt8 + arr.readUInt16LE = BP.readUInt16LE + arr.readUInt16BE = BP.readUInt16BE + arr.readUInt32LE = BP.readUInt32LE + arr.readUInt32BE = BP.readUInt32BE + arr.readInt8 = BP.readInt8 + arr.readInt16LE = BP.readInt16LE + arr.readInt16BE = BP.readInt16BE + arr.readInt32LE = BP.readInt32LE + arr.readInt32BE = BP.readInt32BE + arr.readFloatLE = BP.readFloatLE + arr.readFloatBE = BP.readFloatBE + arr.readDoubleLE = BP.readDoubleLE + arr.readDoubleBE = BP.readDoubleBE + arr.writeUInt8 = BP.writeUInt8 + arr.writeUInt16LE = BP.writeUInt16LE + arr.writeUInt16BE = BP.writeUInt16BE + arr.writeUInt32LE = BP.writeUInt32LE + arr.writeUInt32BE = BP.writeUInt32BE + arr.writeInt8 = BP.writeInt8 + arr.writeInt16LE = BP.writeInt16LE + arr.writeInt16BE = BP.writeInt16BE + arr.writeInt32LE = BP.writeInt32LE + arr.writeInt32BE = BP.writeInt32BE + arr.writeFloatLE = BP.writeFloatLE + arr.writeFloatBE = BP.writeFloatBE + arr.writeDoubleLE = BP.writeDoubleLE + arr.writeDoubleBE = BP.writeDoubleBE + arr.fill = BP.fill + arr.inspect = BP.inspect + arr.toArrayBuffer = BP.toArrayBuffer + + return arr +} + +var INVALID_BASE64_RE = /[^+\/0-9A-z]/g + +function base64clean (str) { + // Node strips out invalid characters like \n and \t from the string, base64-js does not + str = stringtrim(str).replace(INVALID_BASE64_RE, '') + // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not + while (str.length % 4 !== 0) { + str = str + '=' + } + return str +} + +function stringtrim (str) { + if (str.trim) return str.trim() + return str.replace(/^\s+|\s+$/g, '') +} + +function isArrayish (subject) { + return isArray(subject) || Buffer.isBuffer(subject) || + subject && typeof subject === 'object' && + typeof subject.length === 'number' +} + +function toHex (n) { + if (n < 16) return '0' + n.toString(16) + return n.toString(16) +} + +function utf8ToBytes (str) { + var byteArray = [] + for (var i = 0; i < str.length; i++) { + var b = str.charCodeAt(i) + if (b <= 0x7F) { + byteArray.push(b) + } else { + var start = i + if (b >= 0xD800 && b <= 0xDFFF) i++ + var h = encodeURIComponent(str.slice(start, i+1)).substr(1).split('%') + for (var j = 0; j < h.length; j++) { + byteArray.push(parseInt(h[j], 16)) + } + } + } + return byteArray +} + +function asciiToBytes (str) { + var byteArray = [] + for (var i = 0; i < str.length; i++) { + // Node's code seems to be doing this and not & 0x7F.. + byteArray.push(str.charCodeAt(i) & 0xFF) + } + return byteArray +} + +function utf16leToBytes (str) { + var c, hi, lo + var byteArray = [] + for (var i = 0; i < str.length; i++) { + c = str.charCodeAt(i) + hi = c >> 8 + lo = c % 256 + byteArray.push(lo) + byteArray.push(hi) + } + + return byteArray +} + +function base64ToBytes (str) { + return base64.toByteArray(str) +} + +function blitBuffer (src, dst, offset, length) { + for (var i = 0; i < length; i++) { + if ((i + offset >= dst.length) || (i >= src.length)) + break + dst[i + offset] = src[i] + } + return i +} + +function decodeUtf8Char (str) { + try { + return decodeURIComponent(str) + } catch (err) { + return String.fromCharCode(0xFFFD) // UTF 8 invalid char + } +} + +},{"base64-js":18,"ieee754":19,"is-array":20}],18:[function(_dereq_,module,exports){ +var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + +;(function (exports) { + 'use strict'; + + var Arr = (typeof Uint8Array !== 'undefined') + ? Uint8Array + : Array + + var PLUS = '+'.charCodeAt(0) + var SLASH = '/'.charCodeAt(0) + var NUMBER = '0'.charCodeAt(0) + var LOWER = 'a'.charCodeAt(0) + var UPPER = 'A'.charCodeAt(0) + + function decode (elt) { + var code = elt.charCodeAt(0) + if (code === PLUS) + return 62 // '+' + if (code === SLASH) + return 63 // '/' + if (code < NUMBER) + return -1 //no match + if (code < NUMBER + 10) + return code - NUMBER + 26 + 26 + if (code < UPPER + 26) + return code - UPPER + if (code < LOWER + 26) + return code - LOWER + 26 + } + + function b64ToByteArray (b64) { + var i, j, l, tmp, placeHolders, arr + + if (b64.length % 4 > 0) { + throw new Error('Invalid string. Length must be a multiple of 4') + } + + // the number of equal signs (place holders) + // if there are two placeholders, than the two characters before it + // represent one byte + // if there is only one, then the three characters before it represent 2 bytes + // this is just a cheap hack to not do indexOf twice + var len = b64.length + placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0 + + // base64 is 4/3 + up to two characters of the original data + arr = new Arr(b64.length * 3 / 4 - placeHolders) + + // if there are placeholders, only get up to the last complete 4 chars + l = placeHolders > 0 ? b64.length - 4 : b64.length + + var L = 0 + + function push (v) { + arr[L++] = v + } + + for (i = 0, j = 0; i < l; i += 4, j += 3) { + tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3)) + push((tmp & 0xFF0000) >> 16) + push((tmp & 0xFF00) >> 8) + push(tmp & 0xFF) + } + + if (placeHolders === 2) { + tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4) + push(tmp & 0xFF) + } else if (placeHolders === 1) { + tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2) + push((tmp >> 8) & 0xFF) + push(tmp & 0xFF) + } + + return arr + } + + function uint8ToBase64 (uint8) { + var i, + extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes + output = "", + temp, length + + function encode (num) { + return lookup.charAt(num) + } + + function tripletToBase64 (num) { + return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F) + } + + // go through the array every three bytes, we'll deal with trailing stuff later + for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) { + temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) + output += tripletToBase64(temp) + } + + // pad the end with zeros, but make sure to not forget the extra bytes + switch (extraBytes) { + case 1: + temp = uint8[uint8.length - 1] + output += encode(temp >> 2) + output += encode((temp << 4) & 0x3F) + output += '==' + break + case 2: + temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]) + output += encode(temp >> 10) + output += encode((temp >> 4) & 0x3F) + output += encode((temp << 2) & 0x3F) + output += '=' + break + } + + return output + } + + exports.toByteArray = b64ToByteArray + exports.fromByteArray = uint8ToBase64 +}(typeof exports === 'undefined' ? (this.base64js = {}) : exports)) + +},{}],19:[function(_dereq_,module,exports){ +exports.read = function(buffer, offset, isLE, mLen, nBytes) { + var e, m, + eLen = nBytes * 8 - mLen - 1, + eMax = (1 << eLen) - 1, + eBias = eMax >> 1, + nBits = -7, + i = isLE ? (nBytes - 1) : 0, + d = isLE ? -1 : 1, + s = buffer[offset + i]; + + i += d; + + e = s & ((1 << (-nBits)) - 1); + s >>= (-nBits); + nBits += eLen; + for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8); + + m = e & ((1 << (-nBits)) - 1); + e >>= (-nBits); + nBits += mLen; + for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8); + + if (e === 0) { + e = 1 - eBias; + } else if (e === eMax) { + return m ? NaN : ((s ? -1 : 1) * Infinity); + } else { + m = m + Math.pow(2, mLen); + e = e - eBias; + } + return (s ? -1 : 1) * m * Math.pow(2, e - mLen); +}; + +exports.write = function(buffer, value, offset, isLE, mLen, nBytes) { + var e, m, c, + eLen = nBytes * 8 - mLen - 1, + eMax = (1 << eLen) - 1, + eBias = eMax >> 1, + rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0), + i = isLE ? 0 : (nBytes - 1), + d = isLE ? 1 : -1, + s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0; + + value = Math.abs(value); + + if (isNaN(value) || value === Infinity) { + m = isNaN(value) ? 1 : 0; + e = eMax; + } else { + e = Math.floor(Math.log(value) / Math.LN2); + if (value * (c = Math.pow(2, -e)) < 1) { + e--; + c *= 2; + } + if (e + eBias >= 1) { + value += rt / c; + } else { + value += rt * Math.pow(2, 1 - eBias); + } + if (value * c >= 2) { + e++; + c /= 2; + } + + if (e + eBias >= eMax) { + m = 0; + e = eMax; + } else if (e + eBias >= 1) { + m = (value * c - 1) * Math.pow(2, mLen); + e = e + eBias; + } else { + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); + e = 0; + } + } + + for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8); + + e = (e << mLen) | m; + eLen += mLen; + for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8); + + buffer[offset + i - d] |= s * 128; +}; + +},{}],20:[function(_dereq_,module,exports){ + +/** + * isArray + */ + +var isArray = Array.isArray; + +/** + * toString + */ + +var str = Object.prototype.toString; + +/** + * Whether or not the given `val` + * is an array. + * + * example: + * + * isArray([]); + * // > true + * isArray(arguments); + * // > false + * isArray(''); + * // > false + * + * @param {mixed} val + * @return {bool} + */ + +module.exports = isArray || function (val) { + return !! val && '[object Array]' == str.call(val); +}; + +},{}],21:[function(_dereq_,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +function EventEmitter() { + this._events = this._events || {}; + this._maxListeners = this._maxListeners || undefined; +} +module.exports = EventEmitter; + +// Backwards-compat with node 0.10.x +EventEmitter.EventEmitter = EventEmitter; + +EventEmitter.prototype._events = undefined; +EventEmitter.prototype._maxListeners = undefined; + +// By default EventEmitters will print a warning if more than 10 listeners are +// added to it. This is a useful default which helps finding memory leaks. +EventEmitter.defaultMaxListeners = 10; + +// Obviously not all Emitters should be limited to 10. This function allows +// that to be increased. Set to zero for unlimited. +EventEmitter.prototype.setMaxListeners = function(n) { + if (!isNumber(n) || n < 0 || isNaN(n)) + throw TypeError('n must be a positive number'); + this._maxListeners = n; + return this; +}; + +EventEmitter.prototype.emit = function(type) { + var er, handler, len, args, i, listeners; + + if (!this._events) + this._events = {}; + + // If there is no 'error' event listener then throw. + if (type === 'error') { + if (!this._events.error || + (isObject(this._events.error) && !this._events.error.length)) { + er = arguments[1]; + if (er instanceof Error) { + throw er; // Unhandled 'error' event + } + throw TypeError('Uncaught, unspecified "error" event.'); + } + } + + handler = this._events[type]; + + if (isUndefined(handler)) + return false; + + if (isFunction(handler)) { + switch (arguments.length) { + // fast cases + case 1: + handler.call(this); + break; + case 2: + handler.call(this, arguments[1]); + break; + case 3: + handler.call(this, arguments[1], arguments[2]); + break; + // slower + default: + len = arguments.length; + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + handler.apply(this, args); + } + } else if (isObject(handler)) { + len = arguments.length; + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + + listeners = handler.slice(); + len = listeners.length; + for (i = 0; i < len; i++) + listeners[i].apply(this, args); + } + + return true; +}; + +EventEmitter.prototype.addListener = function(type, listener) { + var m; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events) + this._events = {}; + + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (this._events.newListener) + this.emit('newListener', type, + isFunction(listener.listener) ? + listener.listener : listener); + + if (!this._events[type]) + // Optimize the case of one listener. Don't need the extra array object. + this._events[type] = listener; + else if (isObject(this._events[type])) + // If we've already got an array, just append. + this._events[type].push(listener); + else + // Adding the second element, need to change to array. + this._events[type] = [this._events[type], listener]; + + // Check for listener leak + if (isObject(this._events[type]) && !this._events[type].warned) { + var m; + if (!isUndefined(this._maxListeners)) { + m = this._maxListeners; + } else { + m = EventEmitter.defaultMaxListeners; + } + + if (m && m > 0 && this._events[type].length > m) { + this._events[type].warned = true; + console.error('(node) warning: possible EventEmitter memory ' + + 'leak detected. %d listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.', + this._events[type].length); + if (typeof console.trace === 'function') { + // not supported in IE 10 + console.trace(); + } + } + } + + return this; +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.once = function(type, listener) { + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + var fired = false; + + function g() { + this.removeListener(type, g); + + if (!fired) { + fired = true; + listener.apply(this, arguments); + } + } + + g.listener = listener; + this.on(type, g); + + return this; +}; + +// emits a 'removeListener' event iff the listener was removed +EventEmitter.prototype.removeListener = function(type, listener) { + var list, position, length, i; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events || !this._events[type]) + return this; + + list = this._events[type]; + length = list.length; + position = -1; + + if (list === listener || + (isFunction(list.listener) && list.listener === listener)) { + delete this._events[type]; + if (this._events.removeListener) + this.emit('removeListener', type, listener); + + } else if (isObject(list)) { + for (i = length; i-- > 0;) { + if (list[i] === listener || + (list[i].listener && list[i].listener === listener)) { + position = i; + break; + } + } + + if (position < 0) + return this; + + if (list.length === 1) { + list.length = 0; + delete this._events[type]; + } else { + list.splice(position, 1); + } + + if (this._events.removeListener) + this.emit('removeListener', type, listener); + } + + return this; +}; + +EventEmitter.prototype.removeAllListeners = function(type) { + var key, listeners; + + if (!this._events) + return this; + + // not listening for removeListener, no need to emit + if (!this._events.removeListener) { + if (arguments.length === 0) + this._events = {}; + else if (this._events[type]) + delete this._events[type]; + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + for (key in this._events) { + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = {}; + return this; + } + + listeners = this._events[type]; + + if (isFunction(listeners)) { + this.removeListener(type, listeners); + } else { + // LIFO order + while (listeners.length) + this.removeListener(type, listeners[listeners.length - 1]); + } + delete this._events[type]; + + return this; +}; + +EventEmitter.prototype.listeners = function(type) { + var ret; + if (!this._events || !this._events[type]) + ret = []; + else if (isFunction(this._events[type])) + ret = [this._events[type]]; + else + ret = this._events[type].slice(); + return ret; +}; + +EventEmitter.listenerCount = function(emitter, type) { + var ret; + if (!emitter._events || !emitter._events[type]) + ret = 0; + else if (isFunction(emitter._events[type])) + ret = 1; + else + ret = emitter._events[type].length; + return ret; +}; + +function isFunction(arg) { + return typeof arg === 'function'; +} + +function isNumber(arg) { + return typeof arg === 'number'; +} + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} + +function isUndefined(arg) { + return arg === void 0; +} + +},{}],22:[function(_dereq_,module,exports){ +module.exports = Array.isArray || function (arr) { + return Object.prototype.toString.call(arr) == '[object Array]'; +}; + +},{}],23:[function(_dereq_,module,exports){ +(function (process){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// resolves . and .. elements in a path array with directory names there +// must be no slashes, empty elements, or device names (c:\) in the array +// (so also no leading and trailing slashes - it does not distinguish +// relative and absolute paths) +function normalizeArray(parts, allowAboveRoot) { + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = parts.length - 1; i >= 0; i--) { + var last = parts[i]; + if (last === '.') { + parts.splice(i, 1); + } else if (last === '..') { + parts.splice(i, 1); + up++; + } else if (up) { + parts.splice(i, 1); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up--; up) { + parts.unshift('..'); + } + } + + return parts; +} + +// Split a filename into [root, dir, basename, ext], unix version +// 'root' is just a slash, or nothing. +var splitPathRe = + /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; +var splitPath = function(filename) { + return splitPathRe.exec(filename).slice(1); +}; + +// path.resolve([from ...], to) +// posix version +exports.resolve = function() { + var resolvedPath = '', + resolvedAbsolute = false; + + for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) ? arguments[i] : process.cwd(); + + // Skip empty and invalid entries + if (typeof path !== 'string') { + throw new TypeError('Arguments to path.resolve must be strings'); + } else if (!path) { + continue; + } + + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = path.charAt(0) === '/'; + } + + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) + + // Normalize the path + resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { + return !!p; + }), !resolvedAbsolute).join('/'); + + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; +}; + +// path.normalize(path) +// posix version +exports.normalize = function(path) { + var isAbsolute = exports.isAbsolute(path), + trailingSlash = substr(path, -1) === '/'; + + // Normalize the path + path = normalizeArray(filter(path.split('/'), function(p) { + return !!p; + }), !isAbsolute).join('/'); + + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + + return (isAbsolute ? '/' : '') + path; +}; + +// posix version +exports.isAbsolute = function(path) { + return path.charAt(0) === '/'; +}; + +// posix version +exports.join = function() { + var paths = Array.prototype.slice.call(arguments, 0); + return exports.normalize(filter(paths, function(p, index) { + if (typeof p !== 'string') { + throw new TypeError('Arguments to path.join must be strings'); + } + return p; + }).join('/')); +}; + + +// path.relative(from, to) +// posix version +exports.relative = function(from, to) { + from = exports.resolve(from).substr(1); + to = exports.resolve(to).substr(1); + + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + + var end = arr.length - 1; + for (; end >= 0; end--) { + if (arr[end] !== '') break; + } + + if (start > end) return []; + return arr.slice(start, end - start + 1); + } + + var fromParts = trim(from.split('/')); + var toParts = trim(to.split('/')); + + var length = Math.min(fromParts.length, toParts.length); + var samePartsLength = length; + for (var i = 0; i < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i; + break; + } + } + + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); + } + + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + + return outputParts.join('/'); +}; + +exports.sep = '/'; +exports.delimiter = ':'; + +exports.dirname = function(path) { + var result = splitPath(path), + root = result[0], + dir = result[1]; + + if (!root && !dir) { + // No dirname whatsoever + return '.'; + } + + if (dir) { + // It has a dirname, strip trailing slash + dir = dir.substr(0, dir.length - 1); + } + + return root + dir; +}; + + +exports.basename = function(path, ext) { + var f = splitPath(path)[2]; + // TODO: make this comparison case-insensitive on windows? + if (ext && f.substr(-1 * ext.length) === ext) { + f = f.substr(0, f.length - ext.length); + } + return f; +}; + + +exports.extname = function(path) { + return splitPath(path)[3]; +}; + +function filter (xs, f) { + if (xs.filter) return xs.filter(f); + var res = []; + for (var i = 0; i < xs.length; i++) { + if (f(xs[i], i, xs)) res.push(xs[i]); + } + return res; +} + +// String.prototype.substr - negative index don't work in IE8 +var substr = 'ab'.substr(-1) === 'b' + ? function (str, start, len) { return str.substr(start, len) } + : function (str, start, len) { + if (start < 0) start = str.length + start; + return str.substr(start, len); + } +; + +}).call(this,_dereq_('_process')) +},{"_process":24}],24:[function(_dereq_,module,exports){ +// shim for using process in browser + +var process = module.exports = {}; + +process.nextTick = (function () { + var canSetImmediate = typeof window !== 'undefined' + && window.setImmediate; + var canMutationObserver = typeof window !== 'undefined' + && window.MutationObserver; + var canPost = typeof window !== 'undefined' + && window.postMessage && window.addEventListener + ; + + if (canSetImmediate) { + return function (f) { return window.setImmediate(f) }; + } + + var queue = []; + + if (canMutationObserver) { + var hiddenDiv = document.createElement("div"); + var observer = new MutationObserver(function () { + var queueList = queue.slice(); + queue.length = 0; + queueList.forEach(function (fn) { + fn(); + }); + }); + + observer.observe(hiddenDiv, { attributes: true }); + + return function nextTick(fn) { + if (!queue.length) { + hiddenDiv.setAttribute('yes', 'no'); + } + queue.push(fn); + }; + } + + if (canPost) { + window.addEventListener('message', function (ev) { + var source = ev.source; + if ((source === window || source === null) && ev.data === 'process-tick') { + ev.stopPropagation(); + if (queue.length > 0) { + var fn = queue.shift(); + fn(); + } + } + }, true); + + return function nextTick(fn) { + queue.push(fn); + window.postMessage('process-tick', '*'); + }; + } + + return function nextTick(fn) { + setTimeout(fn, 0); + }; +})(); + +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +// TODO(shtylman) +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; + +},{}],25:[function(_dereq_,module,exports){ +module.exports = _dereq_("./lib/_stream_duplex.js") + +},{"./lib/_stream_duplex.js":26}],26:[function(_dereq_,module,exports){ +(function (process){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a duplex stream is just a stream that is both readable and writable. +// Since JS doesn't have multiple prototypal inheritance, this class +// prototypally inherits from Readable, and then parasitically from +// Writable. + +module.exports = Duplex; + +/*<replacement>*/ +var objectKeys = Object.keys || function (obj) { + var keys = []; + for (var key in obj) keys.push(key); + return keys; +} +/*</replacement>*/ + + +/*<replacement>*/ +var util = _dereq_('core-util-is'); +util.inherits = _dereq_('inherits'); +/*</replacement>*/ + +var Readable = _dereq_('./_stream_readable'); +var Writable = _dereq_('./_stream_writable'); + +util.inherits(Duplex, Readable); + +forEach(objectKeys(Writable.prototype), function(method) { + if (!Duplex.prototype[method]) + Duplex.prototype[method] = Writable.prototype[method]; +}); + +function Duplex(options) { + if (!(this instanceof Duplex)) + return new Duplex(options); + + Readable.call(this, options); + Writable.call(this, options); + + if (options && options.readable === false) + this.readable = false; + + if (options && options.writable === false) + this.writable = false; + + this.allowHalfOpen = true; + if (options && options.allowHalfOpen === false) + this.allowHalfOpen = false; + + this.once('end', onend); +} + +// the no-half-open enforcer +function onend() { + // if we allow half-open state, or if the writable side ended, + // then we're ok. + if (this.allowHalfOpen || this._writableState.ended) + return; + + // no more data can be written. + // But allow more writes to happen in this tick. + process.nextTick(this.end.bind(this)); +} + +function forEach (xs, f) { + for (var i = 0, l = xs.length; i < l; i++) { + f(xs[i], i); + } +} + +}).call(this,_dereq_('_process')) +},{"./_stream_readable":28,"./_stream_writable":30,"_process":24,"core-util-is":31,"inherits":44}],27:[function(_dereq_,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a passthrough stream. +// basically just the most minimal sort of Transform stream. +// Every written chunk gets output as-is. + +module.exports = PassThrough; + +var Transform = _dereq_('./_stream_transform'); + +/*<replacement>*/ +var util = _dereq_('core-util-is'); +util.inherits = _dereq_('inherits'); +/*</replacement>*/ + +util.inherits(PassThrough, Transform); + +function PassThrough(options) { + if (!(this instanceof PassThrough)) + return new PassThrough(options); + + Transform.call(this, options); +} + +PassThrough.prototype._transform = function(chunk, encoding, cb) { + cb(null, chunk); +}; + +},{"./_stream_transform":29,"core-util-is":31,"inherits":44}],28:[function(_dereq_,module,exports){ +(function (process){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +module.exports = Readable; + +/*<replacement>*/ +var isArray = _dereq_('isarray'); +/*</replacement>*/ + + +/*<replacement>*/ +var Buffer = _dereq_('buffer').Buffer; +/*</replacement>*/ + +Readable.ReadableState = ReadableState; + +var EE = _dereq_('events').EventEmitter; + +/*<replacement>*/ +if (!EE.listenerCount) EE.listenerCount = function(emitter, type) { + return emitter.listeners(type).length; +}; +/*</replacement>*/ + +var Stream = _dereq_('stream'); + +/*<replacement>*/ +var util = _dereq_('core-util-is'); +util.inherits = _dereq_('inherits'); +/*</replacement>*/ + +var StringDecoder; + +util.inherits(Readable, Stream); + +function ReadableState(options, stream) { + options = options || {}; + + // the point at which it stops calling _read() to fill the buffer + // Note: 0 is a valid value, means "don't call _read preemptively ever" + var hwm = options.highWaterMark; + this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024; + + // cast to ints. + this.highWaterMark = ~~this.highWaterMark; + + this.buffer = []; + this.length = 0; + this.pipes = null; + this.pipesCount = 0; + this.flowing = false; + this.ended = false; + this.endEmitted = false; + this.reading = false; + + // In streams that never have any data, and do push(null) right away, + // the consumer can miss the 'end' event if they do some I/O before + // consuming the stream. So, we don't emit('end') until some reading + // happens. + this.calledRead = false; + + // a flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, becuase any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. + this.sync = true; + + // whenever we return null, then we set a flag to say + // that we're awaiting a 'readable' event emission. + this.needReadable = false; + this.emittedReadable = false; + this.readableListening = false; + + + // object stream flag. Used to make read(n) ignore n and to + // make all the buffer merging and length checks go away + this.objectMode = !!options.objectMode; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // when piping, we only care about 'readable' events that happen + // after read()ing all the bytes and not getting any pushback. + this.ranOut = false; + + // the number of writers that are awaiting a drain event in .pipe()s + this.awaitDrain = 0; + + // if true, a maybeReadMore has been scheduled + this.readingMore = false; + + this.decoder = null; + this.encoding = null; + if (options.encoding) { + if (!StringDecoder) + StringDecoder = _dereq_('string_decoder/').StringDecoder; + this.decoder = new StringDecoder(options.encoding); + this.encoding = options.encoding; + } +} + +function Readable(options) { + if (!(this instanceof Readable)) + return new Readable(options); + + this._readableState = new ReadableState(options, this); + + // legacy + this.readable = true; + + Stream.call(this); +} + +// Manually shove something into the read() buffer. +// This returns true if the highWaterMark has not been hit yet, +// similar to how Writable.write() returns true if you should +// write() some more. +Readable.prototype.push = function(chunk, encoding) { + var state = this._readableState; + + if (typeof chunk === 'string' && !state.objectMode) { + encoding = encoding || state.defaultEncoding; + if (encoding !== state.encoding) { + chunk = new Buffer(chunk, encoding); + encoding = ''; + } + } + + return readableAddChunk(this, state, chunk, encoding, false); +}; + +// Unshift should *always* be something directly out of read() +Readable.prototype.unshift = function(chunk) { + var state = this._readableState; + return readableAddChunk(this, state, chunk, '', true); +}; + +function readableAddChunk(stream, state, chunk, encoding, addToFront) { + var er = chunkInvalid(state, chunk); + if (er) { + stream.emit('error', er); + } else if (chunk === null || chunk === undefined) { + state.reading = false; + if (!state.ended) + onEofChunk(stream, state); + } else if (state.objectMode || chunk && chunk.length > 0) { + if (state.ended && !addToFront) { + var e = new Error('stream.push() after EOF'); + stream.emit('error', e); + } else if (state.endEmitted && addToFront) { + var e = new Error('stream.unshift() after end event'); + stream.emit('error', e); + } else { + if (state.decoder && !addToFront && !encoding) + chunk = state.decoder.write(chunk); + + // update the buffer info. + state.length += state.objectMode ? 1 : chunk.length; + if (addToFront) { + state.buffer.unshift(chunk); + } else { + state.reading = false; + state.buffer.push(chunk); + } + + if (state.needReadable) + emitReadable(stream); + + maybeReadMore(stream, state); + } + } else if (!addToFront) { + state.reading = false; + } + + return needMoreData(state); +} + + + +// if it's past the high water mark, we can push in some more. +// Also, if we have no data yet, we can stand some +// more bytes. This is to work around cases where hwm=0, +// such as the repl. Also, if the push() triggered a +// readable event, and the user called read(largeNumber) such that +// needReadable was set, then we ought to push more, so that another +// 'readable' event will be triggered. +function needMoreData(state) { + return !state.ended && + (state.needReadable || + state.length < state.highWaterMark || + state.length === 0); +} + +// backwards compatibility. +Readable.prototype.setEncoding = function(enc) { + if (!StringDecoder) + StringDecoder = _dereq_('string_decoder/').StringDecoder; + this._readableState.decoder = new StringDecoder(enc); + this._readableState.encoding = enc; +}; + +// Don't raise the hwm > 128MB +var MAX_HWM = 0x800000; +function roundUpToNextPowerOf2(n) { + if (n >= MAX_HWM) { + n = MAX_HWM; + } else { + // Get the next highest power of 2 + n--; + for (var p = 1; p < 32; p <<= 1) n |= n >> p; + n++; + } + return n; +} + +function howMuchToRead(n, state) { + if (state.length === 0 && state.ended) + return 0; + + if (state.objectMode) + return n === 0 ? 0 : 1; + + if (n === null || isNaN(n)) { + // only flow one buffer at a time + if (state.flowing && state.buffer.length) + return state.buffer[0].length; + else + return state.length; + } + + if (n <= 0) + return 0; + + // If we're asking for more than the target buffer level, + // then raise the water mark. Bump up to the next highest + // power of 2, to prevent increasing it excessively in tiny + // amounts. + if (n > state.highWaterMark) + state.highWaterMark = roundUpToNextPowerOf2(n); + + // don't have that much. return null, unless we've ended. + if (n > state.length) { + if (!state.ended) { + state.needReadable = true; + return 0; + } else + return state.length; + } + + return n; +} + +// you can override either this method, or the async _read(n) below. +Readable.prototype.read = function(n) { + var state = this._readableState; + state.calledRead = true; + var nOrig = n; + var ret; + + if (typeof n !== 'number' || n > 0) + state.emittedReadable = false; + + // if we're doing read(0) to trigger a readable event, but we + // already have a bunch of data in the buffer, then just trigger + // the 'readable' event and move on. + if (n === 0 && + state.needReadable && + (state.length >= state.highWaterMark || state.ended)) { + emitReadable(this); + return null; + } + + n = howMuchToRead(n, state); + + // if we've ended, and we're now clear, then finish it up. + if (n === 0 && state.ended) { + ret = null; + + // In cases where the decoder did not receive enough data + // to produce a full chunk, then immediately received an + // EOF, state.buffer will contain [<Buffer >, <Buffer 00 ...>]. + // howMuchToRead will see this and coerce the amount to + // read to zero (because it's looking at the length of the + // first <Buffer > in state.buffer), and we'll end up here. + // + // This can only happen via state.decoder -- no other venue + // exists for pushing a zero-length chunk into state.buffer + // and triggering this behavior. In this case, we return our + // remaining data and end the stream, if appropriate. + if (state.length > 0 && state.decoder) { + ret = fromList(n, state); + state.length -= ret.length; + } + + if (state.length === 0) + endReadable(this); + + return ret; + } + + // All the actual chunk generation logic needs to be + // *below* the call to _read. The reason is that in certain + // synthetic stream cases, such as passthrough streams, _read + // may be a completely synchronous operation which may change + // the state of the read buffer, providing enough data when + // before there was *not* enough. + // + // So, the steps are: + // 1. Figure out what the state of things will be after we do + // a read from the buffer. + // + // 2. If that resulting state will trigger a _read, then call _read. + // Note that this may be asynchronous, or synchronous. Yes, it is + // deeply ugly to write APIs this way, but that still doesn't mean + // that the Readable class should behave improperly, as streams are + // designed to be sync/async agnostic. + // Take note if the _read call is sync or async (ie, if the read call + // has returned yet), so that we know whether or not it's safe to emit + // 'readable' etc. + // + // 3. Actually pull the requested chunks out of the buffer and return. + + // if we need a readable event, then we need to do some reading. + var doRead = state.needReadable; + + // if we currently have less than the highWaterMark, then also read some + if (state.length - n <= state.highWaterMark) + doRead = true; + + // however, if we've ended, then there's no point, and if we're already + // reading, then it's unnecessary. + if (state.ended || state.reading) + doRead = false; + + if (doRead) { + state.reading = true; + state.sync = true; + // if the length is currently zero, then we *need* a readable event. + if (state.length === 0) + state.needReadable = true; + // call internal read method + this._read(state.highWaterMark); + state.sync = false; + } + + // If _read called its callback synchronously, then `reading` + // will be false, and we need to re-evaluate how much data we + // can return to the user. + if (doRead && !state.reading) + n = howMuchToRead(nOrig, state); + + if (n > 0) + ret = fromList(n, state); + else + ret = null; + + if (ret === null) { + state.needReadable = true; + n = 0; + } + + state.length -= n; + + // If we have nothing in the buffer, then we want to know + // as soon as we *do* get something into the buffer. + if (state.length === 0 && !state.ended) + state.needReadable = true; + + // If we happened to read() exactly the remaining amount in the + // buffer, and the EOF has been seen at this point, then make sure + // that we emit 'end' on the very next tick. + if (state.ended && !state.endEmitted && state.length === 0) + endReadable(this); + + return ret; +}; + +function chunkInvalid(state, chunk) { + var er = null; + if (!Buffer.isBuffer(chunk) && + 'string' !== typeof chunk && + chunk !== null && + chunk !== undefined && + !state.objectMode) { + er = new TypeError('Invalid non-string/buffer chunk'); + } + return er; +} + + +function onEofChunk(stream, state) { + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) { + state.buffer.push(chunk); + state.length += state.objectMode ? 1 : chunk.length; + } + } + state.ended = true; + + // if we've ended and we have some data left, then emit + // 'readable' now to make sure it gets picked up. + if (state.length > 0) + emitReadable(stream); + else + endReadable(stream); +} + +// Don't emit readable right away in sync mode, because this can trigger +// another read() call => stack overflow. This way, it might trigger +// a nextTick recursion warning, but that's not so bad. +function emitReadable(stream) { + var state = stream._readableState; + state.needReadable = false; + if (state.emittedReadable) + return; + + state.emittedReadable = true; + if (state.sync) + process.nextTick(function() { + emitReadable_(stream); + }); + else + emitReadable_(stream); +} + +function emitReadable_(stream) { + stream.emit('readable'); +} + + +// at this point, the user has presumably seen the 'readable' event, +// and called read() to consume some data. that may have triggered +// in turn another _read(n) call, in which case reading = true if +// it's in progress. +// However, if we're not ended, or reading, and the length < hwm, +// then go ahead and try to read some more preemptively. +function maybeReadMore(stream, state) { + if (!state.readingMore) { + state.readingMore = true; + process.nextTick(function() { + maybeReadMore_(stream, state); + }); + } +} + +function maybeReadMore_(stream, state) { + var len = state.length; + while (!state.reading && !state.flowing && !state.ended && + state.length < state.highWaterMark) { + stream.read(0); + if (len === state.length) + // didn't get any data, stop spinning. + break; + else + len = state.length; + } + state.readingMore = false; +} + +// abstract method. to be overridden in specific implementation classes. +// call cb(er, data) where data is <= n in length. +// for virtual (non-string, non-buffer) streams, "length" is somewhat +// arbitrary, and perhaps not very meaningful. +Readable.prototype._read = function(n) { + this.emit('error', new Error('not implemented')); +}; + +Readable.prototype.pipe = function(dest, pipeOpts) { + var src = this; + var state = this._readableState; + + switch (state.pipesCount) { + case 0: + state.pipes = dest; + break; + case 1: + state.pipes = [state.pipes, dest]; + break; + default: + state.pipes.push(dest); + break; + } + state.pipesCount += 1; + + var doEnd = (!pipeOpts || pipeOpts.end !== false) && + dest !== process.stdout && + dest !== process.stderr; + + var endFn = doEnd ? onend : cleanup; + if (state.endEmitted) + process.nextTick(endFn); + else + src.once('end', endFn); + + dest.on('unpipe', onunpipe); + function onunpipe(readable) { + if (readable !== src) return; + cleanup(); + } + + function onend() { + dest.end(); + } + + // when the dest drains, it reduces the awaitDrain counter + // on the source. This would be more elegant with a .once() + // handler in flow(), but adding and removing repeatedly is + // too slow. + var ondrain = pipeOnDrain(src); + dest.on('drain', ondrain); + + function cleanup() { + // cleanup event handlers once the pipe is broken + dest.removeListener('close', onclose); + dest.removeListener('finish', onfinish); + dest.removeListener('drain', ondrain); + dest.removeListener('error', onerror); + dest.removeListener('unpipe', onunpipe); + src.removeListener('end', onend); + src.removeListener('end', cleanup); + + // if the reader is waiting for a drain event from this + // specific writer, then it would cause it to never start + // flowing again. + // So, if this is awaiting a drain, then we just call it now. + // If we don't know, then assume that we are waiting for one. + if (!dest._writableState || dest._writableState.needDrain) + ondrain(); + } + + // if the dest has an error, then stop piping into it. + // however, don't suppress the throwing behavior for this. + function onerror(er) { + unpipe(); + dest.removeListener('error', onerror); + if (EE.listenerCount(dest, 'error') === 0) + dest.emit('error', er); + } + // This is a brutally ugly hack to make sure that our error handler + // is attached before any userland ones. NEVER DO THIS. + if (!dest._events || !dest._events.error) + dest.on('error', onerror); + else if (isArray(dest._events.error)) + dest._events.error.unshift(onerror); + else + dest._events.error = [onerror, dest._events.error]; + + + + // Both close and finish should trigger unpipe, but only once. + function onclose() { + dest.removeListener('finish', onfinish); + unpipe(); + } + dest.once('close', onclose); + function onfinish() { + dest.removeListener('close', onclose); + unpipe(); + } + dest.once('finish', onfinish); + + function unpipe() { + src.unpipe(dest); + } + + // tell the dest that it's being piped to + dest.emit('pipe', src); + + // start the flow if it hasn't been started already. + if (!state.flowing) { + // the handler that waits for readable events after all + // the data gets sucked out in flow. + // This would be easier to follow with a .once() handler + // in flow(), but that is too slow. + this.on('readable', pipeOnReadable); + + state.flowing = true; + process.nextTick(function() { + flow(src); + }); + } + + return dest; +}; + +function pipeOnDrain(src) { + return function() { + var dest = this; + var state = src._readableState; + state.awaitDrain--; + if (state.awaitDrain === 0) + flow(src); + }; +} + +function flow(src) { + var state = src._readableState; + var chunk; + state.awaitDrain = 0; + + function write(dest, i, list) { + var written = dest.write(chunk); + if (false === written) { + state.awaitDrain++; + } + } + + while (state.pipesCount && null !== (chunk = src.read())) { + + if (state.pipesCount === 1) + write(state.pipes, 0, null); + else + forEach(state.pipes, write); + + src.emit('data', chunk); + + // if anyone needs a drain, then we have to wait for that. + if (state.awaitDrain > 0) + return; + } + + // if every destination was unpiped, either before entering this + // function, or in the while loop, then stop flowing. + // + // NB: This is a pretty rare edge case. + if (state.pipesCount === 0) { + state.flowing = false; + + // if there were data event listeners added, then switch to old mode. + if (EE.listenerCount(src, 'data') > 0) + emitDataEvents(src); + return; + } + + // at this point, no one needed a drain, so we just ran out of data + // on the next readable event, start it over again. + state.ranOut = true; +} + +function pipeOnReadable() { + if (this._readableState.ranOut) { + this._readableState.ranOut = false; + flow(this); + } +} + + +Readable.prototype.unpipe = function(dest) { + var state = this._readableState; + + // if we're not piping anywhere, then do nothing. + if (state.pipesCount === 0) + return this; + + // just one destination. most common case. + if (state.pipesCount === 1) { + // passed in one, but it's not the right one. + if (dest && dest !== state.pipes) + return this; + + if (!dest) + dest = state.pipes; + + // got a match. + state.pipes = null; + state.pipesCount = 0; + this.removeListener('readable', pipeOnReadable); + state.flowing = false; + if (dest) + dest.emit('unpipe', this); + return this; + } + + // slow case. multiple pipe destinations. + + if (!dest) { + // remove all. + var dests = state.pipes; + var len = state.pipesCount; + state.pipes = null; + state.pipesCount = 0; + this.removeListener('readable', pipeOnReadable); + state.flowing = false; + + for (var i = 0; i < len; i++) + dests[i].emit('unpipe', this); + return this; + } + + // try to find the right one. + var i = indexOf(state.pipes, dest); + if (i === -1) + return this; + + state.pipes.splice(i, 1); + state.pipesCount -= 1; + if (state.pipesCount === 1) + state.pipes = state.pipes[0]; + + dest.emit('unpipe', this); + + return this; +}; + +// set up data events if they are asked for +// Ensure readable listeners eventually get something +Readable.prototype.on = function(ev, fn) { + var res = Stream.prototype.on.call(this, ev, fn); + + if (ev === 'data' && !this._readableState.flowing) + emitDataEvents(this); + + if (ev === 'readable' && this.readable) { + var state = this._readableState; + if (!state.readableListening) { + state.readableListening = true; + state.emittedReadable = false; + state.needReadable = true; + if (!state.reading) { + this.read(0); + } else if (state.length) { + emitReadable(this, state); + } + } + } + + return res; +}; +Readable.prototype.addListener = Readable.prototype.on; + +// pause() and resume() are remnants of the legacy readable stream API +// If the user uses them, then switch into old mode. +Readable.prototype.resume = function() { + emitDataEvents(this); + this.read(0); + this.emit('resume'); +}; + +Readable.prototype.pause = function() { + emitDataEvents(this, true); + this.emit('pause'); +}; + +function emitDataEvents(stream, startPaused) { + var state = stream._readableState; + + if (state.flowing) { + // https://github.com/isaacs/readable-stream/issues/16 + throw new Error('Cannot switch to old mode now.'); + } + + var paused = startPaused || false; + var readable = false; + + // convert to an old-style stream. + stream.readable = true; + stream.pipe = Stream.prototype.pipe; + stream.on = stream.addListener = Stream.prototype.on; + + stream.on('readable', function() { + readable = true; + + var c; + while (!paused && (null !== (c = stream.read()))) + stream.emit('data', c); + + if (c === null) { + readable = false; + stream._readableState.needReadable = true; + } + }); + + stream.pause = function() { + paused = true; + this.emit('pause'); + }; + + stream.resume = function() { + paused = false; + if (readable) + process.nextTick(function() { + stream.emit('readable'); + }); + else + this.read(0); + this.emit('resume'); + }; + + // now make it start, just in case it hadn't already. + stream.emit('readable'); +} + +// wrap an old-style stream as the async data source. +// This is *not* part of the readable stream interface. +// It is an ugly unfortunate mess of history. +Readable.prototype.wrap = function(stream) { + var state = this._readableState; + var paused = false; + + var self = this; + stream.on('end', function() { + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) + self.push(chunk); + } + + self.push(null); + }); + + stream.on('data', function(chunk) { + if (state.decoder) + chunk = state.decoder.write(chunk); + + // don't skip over falsy values in objectMode + //if (state.objectMode && util.isNullOrUndefined(chunk)) + if (state.objectMode && (chunk === null || chunk === undefined)) + return; + else if (!state.objectMode && (!chunk || !chunk.length)) + return; + + var ret = self.push(chunk); + if (!ret) { + paused = true; + stream.pause(); + } + }); + + // proxy all the other methods. + // important when wrapping filters and duplexes. + for (var i in stream) { + if (typeof stream[i] === 'function' && + typeof this[i] === 'undefined') { + this[i] = function(method) { return function() { + return stream[method].apply(stream, arguments); + }}(i); + } + } + + // proxy certain important events. + var events = ['error', 'close', 'destroy', 'pause', 'resume']; + forEach(events, function(ev) { + stream.on(ev, self.emit.bind(self, ev)); + }); + + // when we try to consume some more bytes, simply unpause the + // underlying stream. + self._read = function(n) { + if (paused) { + paused = false; + stream.resume(); + } + }; + + return self; +}; + + + +// exposed for testing purposes only. +Readable._fromList = fromList; + +// Pluck off n bytes from an array of buffers. +// Length is the combined lengths of all the buffers in the list. +function fromList(n, state) { + var list = state.buffer; + var length = state.length; + var stringMode = !!state.decoder; + var objectMode = !!state.objectMode; + var ret; + + // nothing in the list, definitely empty. + if (list.length === 0) + return null; + + if (length === 0) + ret = null; + else if (objectMode) + ret = list.shift(); + else if (!n || n >= length) { + // read it all, truncate the array. + if (stringMode) + ret = list.join(''); + else + ret = Buffer.concat(list, length); + list.length = 0; + } else { + // read just some of it. + if (n < list[0].length) { + // just take a part of the first list item. + // slice is the same for buffers and strings. + var buf = list[0]; + ret = buf.slice(0, n); + list[0] = buf.slice(n); + } else if (n === list[0].length) { + // first list is a perfect match + ret = list.shift(); + } else { + // complex case. + // we have enough to cover it, but it spans past the first buffer. + if (stringMode) + ret = ''; + else + ret = new Buffer(n); + + var c = 0; + for (var i = 0, l = list.length; i < l && c < n; i++) { + var buf = list[0]; + var cpy = Math.min(n - c, buf.length); + + if (stringMode) + ret += buf.slice(0, cpy); + else + buf.copy(ret, c, 0, cpy); + + if (cpy < buf.length) + list[0] = buf.slice(cpy); + else + list.shift(); + + c += cpy; + } + } + } + + return ret; +} + +function endReadable(stream) { + var state = stream._readableState; + + // If we get here before consuming all the bytes, then that is a + // bug in node. Should never happen. + if (state.length > 0) + throw new Error('endReadable called on non-empty stream'); + + if (!state.endEmitted && state.calledRead) { + state.ended = true; + process.nextTick(function() { + // Check that we didn't get one last unshift. + if (!state.endEmitted && state.length === 0) { + state.endEmitted = true; + stream.readable = false; + stream.emit('end'); + } + }); + } +} + +function forEach (xs, f) { + for (var i = 0, l = xs.length; i < l; i++) { + f(xs[i], i); + } +} + +function indexOf (xs, x) { + for (var i = 0, l = xs.length; i < l; i++) { + if (xs[i] === x) return i; + } + return -1; +} + +}).call(this,_dereq_('_process')) +},{"_process":24,"buffer":17,"core-util-is":31,"events":21,"inherits":44,"isarray":22,"stream":36,"string_decoder/":37}],29:[function(_dereq_,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + +// a transform stream is a readable/writable stream where you do +// something with the data. Sometimes it's called a "filter", +// but that's not a great name for it, since that implies a thing where +// some bits pass through, and others are simply ignored. (That would +// be a valid example of a transform, of course.) +// +// While the output is causally related to the input, it's not a +// necessarily symmetric or synchronous transformation. For example, +// a zlib stream might take multiple plain-text writes(), and then +// emit a single compressed chunk some time in the future. +// +// Here's how this works: +// +// The Transform stream has all the aspects of the readable and writable +// stream classes. When you write(chunk), that calls _write(chunk,cb) +// internally, and returns false if there's a lot of pending writes +// buffered up. When you call read(), that calls _read(n) until +// there's enough pending readable data buffered up. +// +// In a transform stream, the written data is placed in a buffer. When +// _read(n) is called, it transforms the queued up data, calling the +// buffered _write cb's as it consumes chunks. If consuming a single +// written chunk would result in multiple output chunks, then the first +// outputted bit calls the readcb, and subsequent chunks just go into +// the read buffer, and will cause it to emit 'readable' if necessary. +// +// This way, back-pressure is actually determined by the reading side, +// since _read has to be called to start processing a new chunk. However, +// a pathological inflate type of transform can cause excessive buffering +// here. For example, imagine a stream where every byte of input is +// interpreted as an integer from 0-255, and then results in that many +// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in +// 1kb of data being output. In this case, you could write a very small +// amount of input, and end up with a very large amount of output. In +// such a pathological inflating mechanism, there'd be no way to tell +// the system to stop doing the transform. A single 4MB write could +// cause the system to run out of memory. +// +// However, even in such a pathological case, only a single written chunk +// would be consumed, and then the rest would wait (un-transformed) until +// the results of the previous transformed chunk were consumed. + +module.exports = Transform; + +var Duplex = _dereq_('./_stream_duplex'); + +/*<replacement>*/ +var util = _dereq_('core-util-is'); +util.inherits = _dereq_('inherits'); +/*</replacement>*/ + +util.inherits(Transform, Duplex); + + +function TransformState(options, stream) { + this.afterTransform = function(er, data) { + return afterTransform(stream, er, data); + }; + + this.needTransform = false; + this.transforming = false; + this.writecb = null; + this.writechunk = null; +} + +function afterTransform(stream, er, data) { + var ts = stream._transformState; + ts.transforming = false; + + var cb = ts.writecb; + + if (!cb) + return stream.emit('error', new Error('no writecb in Transform class')); + + ts.writechunk = null; + ts.writecb = null; + + if (data !== null && data !== undefined) + stream.push(data); + + if (cb) + cb(er); + + var rs = stream._readableState; + rs.reading = false; + if (rs.needReadable || rs.length < rs.highWaterMark) { + stream._read(rs.highWaterMark); + } +} + + +function Transform(options) { + if (!(this instanceof Transform)) + return new Transform(options); + + Duplex.call(this, options); + + var ts = this._transformState = new TransformState(options, this); + + // when the writable side finishes, then flush out anything remaining. + var stream = this; + + // start out asking for a readable event once data is transformed. + this._readableState.needReadable = true; + + // we have implemented the _read method, and done the other things + // that Readable wants before the first _read call, so unset the + // sync guard flag. + this._readableState.sync = false; + + this.once('finish', function() { + if ('function' === typeof this._flush) + this._flush(function(er) { + done(stream, er); + }); + else + done(stream); + }); +} + +Transform.prototype.push = function(chunk, encoding) { + this._transformState.needTransform = false; + return Duplex.prototype.push.call(this, chunk, encoding); +}; + +// This is the part where you do stuff! +// override this function in implementation classes. +// 'chunk' is an input chunk. +// +// Call `push(newChunk)` to pass along transformed output +// to the readable side. You may call 'push' zero or more times. +// +// Call `cb(err)` when you are done with this chunk. If you pass +// an error, then that'll put the hurt on the whole operation. If you +// never call cb(), then you'll never get another chunk. +Transform.prototype._transform = function(chunk, encoding, cb) { + throw new Error('not implemented'); +}; + +Transform.prototype._write = function(chunk, encoding, cb) { + var ts = this._transformState; + ts.writecb = cb; + ts.writechunk = chunk; + ts.writeencoding = encoding; + if (!ts.transforming) { + var rs = this._readableState; + if (ts.needTransform || + rs.needReadable || + rs.length < rs.highWaterMark) + this._read(rs.highWaterMark); + } +}; + +// Doesn't matter what the args are here. +// _transform does all the work. +// That we got here means that the readable side wants more data. +Transform.prototype._read = function(n) { + var ts = this._transformState; + + if (ts.writechunk !== null && ts.writecb && !ts.transforming) { + ts.transforming = true; + this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); + } else { + // mark that we need a transform, so that any data that comes in + // will get processed, now that we've asked for it. + ts.needTransform = true; + } +}; + + +function done(stream, er) { + if (er) + return stream.emit('error', er); + + // if there's nothing in the write buffer, then that means + // that nothing more will ever be provided + var ws = stream._writableState; + var rs = stream._readableState; + var ts = stream._transformState; + + if (ws.length) + throw new Error('calling transform done when ws.length != 0'); + + if (ts.transforming) + throw new Error('calling transform done when still transforming'); + + return stream.push(null); +} + +},{"./_stream_duplex":26,"core-util-is":31,"inherits":44}],30:[function(_dereq_,module,exports){ +(function (process){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// A bit simpler than readable streams. +// Implement an async ._write(chunk, cb), and it'll handle all +// the drain event emission and buffering. + +module.exports = Writable; + +/*<replacement>*/ +var Buffer = _dereq_('buffer').Buffer; +/*</replacement>*/ + +Writable.WritableState = WritableState; + + +/*<replacement>*/ +var util = _dereq_('core-util-is'); +util.inherits = _dereq_('inherits'); +/*</replacement>*/ + +var Stream = _dereq_('stream'); + +util.inherits(Writable, Stream); + +function WriteReq(chunk, encoding, cb) { + this.chunk = chunk; + this.encoding = encoding; + this.callback = cb; +} + +function WritableState(options, stream) { + options = options || {}; + + // the point at which write() starts returning false + // Note: 0 is a valid value, means that we always return false if + // the entire buffer is not flushed immediately on write() + var hwm = options.highWaterMark; + this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024; + + // object stream flag to indicate whether or not this stream + // contains buffers or objects. + this.objectMode = !!options.objectMode; + + // cast to ints. + this.highWaterMark = ~~this.highWaterMark; + + this.needDrain = false; + // at the start of calling end() + this.ending = false; + // when end() has been called, and returned + this.ended = false; + // when 'finish' is emitted + this.finished = false; + + // should we decode strings into buffers before passing to _write? + // this is here so that some node-core streams can optimize string + // handling at a lower level. + var noDecode = options.decodeStrings === false; + this.decodeStrings = !noDecode; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // not an actual buffer we keep track of, but a measurement + // of how much we're waiting to get pushed to some underlying + // socket or file. + this.length = 0; + + // a flag to see when we're in the middle of a write. + this.writing = false; + + // a flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, becuase any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. + this.sync = true; + + // a flag to know if we're processing previously buffered items, which + // may call the _write() callback in the same tick, so that we don't + // end up in an overlapped onwrite situation. + this.bufferProcessing = false; + + // the callback that's passed to _write(chunk,cb) + this.onwrite = function(er) { + onwrite(stream, er); + }; + + // the callback that the user supplies to write(chunk,encoding,cb) + this.writecb = null; + + // the amount that is being written when _write is called. + this.writelen = 0; + + this.buffer = []; + + // True if the error was already emitted and should not be thrown again + this.errorEmitted = false; +} + +function Writable(options) { + var Duplex = _dereq_('./_stream_duplex'); + + // Writable ctor is applied to Duplexes, though they're not + // instanceof Writable, they're instanceof Readable. + if (!(this instanceof Writable) && !(this instanceof Duplex)) + return new Writable(options); + + this._writableState = new WritableState(options, this); + + // legacy. + this.writable = true; + + Stream.call(this); +} + +// Otherwise people can pipe Writable streams, which is just wrong. +Writable.prototype.pipe = function() { + this.emit('error', new Error('Cannot pipe. Not readable.')); +}; + + +function writeAfterEnd(stream, state, cb) { + var er = new Error('write after end'); + // TODO: defer error events consistently everywhere, not just the cb + stream.emit('error', er); + process.nextTick(function() { + cb(er); + }); +} + +// If we get something that is not a buffer, string, null, or undefined, +// and we're not in objectMode, then that's an error. +// Otherwise stream chunks are all considered to be of length=1, and the +// watermarks determine how many objects to keep in the buffer, rather than +// how many bytes or characters. +function validChunk(stream, state, chunk, cb) { + var valid = true; + if (!Buffer.isBuffer(chunk) && + 'string' !== typeof chunk && + chunk !== null && + chunk !== undefined && + !state.objectMode) { + var er = new TypeError('Invalid non-string/buffer chunk'); + stream.emit('error', er); + process.nextTick(function() { + cb(er); + }); + valid = false; + } + return valid; +} + +Writable.prototype.write = function(chunk, encoding, cb) { + var state = this._writableState; + var ret = false; + + if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (Buffer.isBuffer(chunk)) + encoding = 'buffer'; + else if (!encoding) + encoding = state.defaultEncoding; + + if (typeof cb !== 'function') + cb = function() {}; + + if (state.ended) + writeAfterEnd(this, state, cb); + else if (validChunk(this, state, chunk, cb)) + ret = writeOrBuffer(this, state, chunk, encoding, cb); + + return ret; +}; + +function decodeChunk(state, chunk, encoding) { + if (!state.objectMode && + state.decodeStrings !== false && + typeof chunk === 'string') { + chunk = new Buffer(chunk, encoding); + } + return chunk; +} + +// if we're already writing something, then just put this +// in the queue, and wait our turn. Otherwise, call _write +// If we return false, then we need a drain event, so set that flag. +function writeOrBuffer(stream, state, chunk, encoding, cb) { + chunk = decodeChunk(state, chunk, encoding); + if (Buffer.isBuffer(chunk)) + encoding = 'buffer'; + var len = state.objectMode ? 1 : chunk.length; + + state.length += len; + + var ret = state.length < state.highWaterMark; + // we must ensure that previous needDrain will not be reset to false. + if (!ret) + state.needDrain = true; + + if (state.writing) + state.buffer.push(new WriteReq(chunk, encoding, cb)); + else + doWrite(stream, state, len, chunk, encoding, cb); + + return ret; +} + +function doWrite(stream, state, len, chunk, encoding, cb) { + state.writelen = len; + state.writecb = cb; + state.writing = true; + state.sync = true; + stream._write(chunk, encoding, state.onwrite); + state.sync = false; +} + +function onwriteError(stream, state, sync, er, cb) { + if (sync) + process.nextTick(function() { + cb(er); + }); + else + cb(er); + + stream._writableState.errorEmitted = true; + stream.emit('error', er); +} + +function onwriteStateUpdate(state) { + state.writing = false; + state.writecb = null; + state.length -= state.writelen; + state.writelen = 0; +} + +function onwrite(stream, er) { + var state = stream._writableState; + var sync = state.sync; + var cb = state.writecb; + + onwriteStateUpdate(state); + + if (er) + onwriteError(stream, state, sync, er, cb); + else { + // Check if we're actually ready to finish, but don't emit yet + var finished = needFinish(stream, state); + + if (!finished && !state.bufferProcessing && state.buffer.length) + clearBuffer(stream, state); + + if (sync) { + process.nextTick(function() { + afterWrite(stream, state, finished, cb); + }); + } else { + afterWrite(stream, state, finished, cb); + } + } +} + +function afterWrite(stream, state, finished, cb) { + if (!finished) + onwriteDrain(stream, state); + cb(); + if (finished) + finishMaybe(stream, state); +} + +// Must force callback to be called on nextTick, so that we don't +// emit 'drain' before the write() consumer gets the 'false' return +// value, and has a chance to attach a 'drain' listener. +function onwriteDrain(stream, state) { + if (state.length === 0 && state.needDrain) { + state.needDrain = false; + stream.emit('drain'); + } +} + + +// if there's something in the buffer waiting, then process it +function clearBuffer(stream, state) { + state.bufferProcessing = true; + + for (var c = 0; c < state.buffer.length; c++) { + var entry = state.buffer[c]; + var chunk = entry.chunk; + var encoding = entry.encoding; + var cb = entry.callback; + var len = state.objectMode ? 1 : chunk.length; + + doWrite(stream, state, len, chunk, encoding, cb); + + // if we didn't call the onwrite immediately, then + // it means that we need to wait until it does. + // also, that means that the chunk and cb are currently + // being processed, so move the buffer counter past them. + if (state.writing) { + c++; + break; + } + } + + state.bufferProcessing = false; + if (c < state.buffer.length) + state.buffer = state.buffer.slice(c); + else + state.buffer.length = 0; +} + +Writable.prototype._write = function(chunk, encoding, cb) { + cb(new Error('not implemented')); +}; + +Writable.prototype.end = function(chunk, encoding, cb) { + var state = this._writableState; + + if (typeof chunk === 'function') { + cb = chunk; + chunk = null; + encoding = null; + } else if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (typeof chunk !== 'undefined' && chunk !== null) + this.write(chunk, encoding); + + // ignore unnecessary end() calls. + if (!state.ending && !state.finished) + endWritable(this, state, cb); +}; + + +function needFinish(stream, state) { + return (state.ending && + state.length === 0 && + !state.finished && + !state.writing); +} + +function finishMaybe(stream, state) { + var need = needFinish(stream, state); + if (need) { + state.finished = true; + stream.emit('finish'); + } + return need; +} + +function endWritable(stream, state, cb) { + state.ending = true; + finishMaybe(stream, state); + if (cb) { + if (state.finished) + process.nextTick(cb); + else + stream.once('finish', cb); + } + state.ended = true; +} + +}).call(this,_dereq_('_process')) +},{"./_stream_duplex":26,"_process":24,"buffer":17,"core-util-is":31,"inherits":44,"stream":36}],31:[function(_dereq_,module,exports){ +(function (Buffer){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. +function isArray(ar) { + return Array.isArray(ar); +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return isObject(re) && objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return isObject(d) && objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return isObject(e) && + (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +function isBuffer(arg) { + return Buffer.isBuffer(arg); +} +exports.isBuffer = isBuffer; + +function objectToString(o) { + return Object.prototype.toString.call(o); +} +}).call(this,_dereq_("buffer").Buffer) +},{"buffer":17}],32:[function(_dereq_,module,exports){ +module.exports = _dereq_("./lib/_stream_passthrough.js") + +},{"./lib/_stream_passthrough.js":27}],33:[function(_dereq_,module,exports){ +var Stream = _dereq_('stream'); // hack to fix a circular dependency issue when used with browserify +exports = module.exports = _dereq_('./lib/_stream_readable.js'); +exports.Stream = Stream; +exports.Readable = exports; +exports.Writable = _dereq_('./lib/_stream_writable.js'); +exports.Duplex = _dereq_('./lib/_stream_duplex.js'); +exports.Transform = _dereq_('./lib/_stream_transform.js'); +exports.PassThrough = _dereq_('./lib/_stream_passthrough.js'); + +},{"./lib/_stream_duplex.js":26,"./lib/_stream_passthrough.js":27,"./lib/_stream_readable.js":28,"./lib/_stream_transform.js":29,"./lib/_stream_writable.js":30,"stream":36}],34:[function(_dereq_,module,exports){ +module.exports = _dereq_("./lib/_stream_transform.js") + +},{"./lib/_stream_transform.js":29}],35:[function(_dereq_,module,exports){ +module.exports = _dereq_("./lib/_stream_writable.js") + +},{"./lib/_stream_writable.js":30}],36:[function(_dereq_,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +module.exports = Stream; + +var EE = _dereq_('events').EventEmitter; +var inherits = _dereq_('inherits'); + +inherits(Stream, EE); +Stream.Readable = _dereq_('readable-stream/readable.js'); +Stream.Writable = _dereq_('readable-stream/writable.js'); +Stream.Duplex = _dereq_('readable-stream/duplex.js'); +Stream.Transform = _dereq_('readable-stream/transform.js'); +Stream.PassThrough = _dereq_('readable-stream/passthrough.js'); + +// Backwards-compat with node 0.4.x +Stream.Stream = Stream; + + + +// old-style streams. Note that the pipe method (the only relevant +// part of this class) is overridden in the Readable class. + +function Stream() { + EE.call(this); +} + +Stream.prototype.pipe = function(dest, options) { + var source = this; + + function ondata(chunk) { + if (dest.writable) { + if (false === dest.write(chunk) && source.pause) { + source.pause(); + } + } + } + + source.on('data', ondata); + + function ondrain() { + if (source.readable && source.resume) { + source.resume(); + } + } + + dest.on('drain', ondrain); + + // If the 'end' option is not supplied, dest.end() will be called when + // source gets the 'end' or 'close' events. Only dest.end() once. + if (!dest._isStdio && (!options || options.end !== false)) { + source.on('end', onend); + source.on('close', onclose); + } + + var didOnEnd = false; + function onend() { + if (didOnEnd) return; + didOnEnd = true; + + dest.end(); + } + + + function onclose() { + if (didOnEnd) return; + didOnEnd = true; + + if (typeof dest.destroy === 'function') dest.destroy(); + } + + // don't leave dangling pipes when there are errors. + function onerror(er) { + cleanup(); + if (EE.listenerCount(this, 'error') === 0) { + throw er; // Unhandled stream error in pipe. + } + } + + source.on('error', onerror); + dest.on('error', onerror); + + // remove all the event listeners that were added. + function cleanup() { + source.removeListener('data', ondata); + dest.removeListener('drain', ondrain); + + source.removeListener('end', onend); + source.removeListener('close', onclose); + + source.removeListener('error', onerror); + dest.removeListener('error', onerror); + + source.removeListener('end', cleanup); + source.removeListener('close', cleanup); + + dest.removeListener('close', cleanup); + } + + source.on('end', cleanup); + source.on('close', cleanup); + + dest.on('close', cleanup); + + dest.emit('pipe', source); + + // Allow for unix-like usage: A.pipe(B).pipe(C) + return dest; +}; + +},{"events":21,"inherits":44,"readable-stream/duplex.js":25,"readable-stream/passthrough.js":32,"readable-stream/readable.js":33,"readable-stream/transform.js":34,"readable-stream/writable.js":35}],37:[function(_dereq_,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var Buffer = _dereq_('buffer').Buffer; + +var isBufferEncoding = Buffer.isEncoding + || function(encoding) { + switch (encoding && encoding.toLowerCase()) { + case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true; + default: return false; + } + } + + +function assertEncoding(encoding) { + if (encoding && !isBufferEncoding(encoding)) { + throw new Error('Unknown encoding: ' + encoding); + } +} + +// StringDecoder provides an interface for efficiently splitting a series of +// buffers into a series of JS strings without breaking apart multi-byte +// characters. CESU-8 is handled as part of the UTF-8 encoding. +// +// @TODO Handling all encodings inside a single object makes it very difficult +// to reason about this code, so it should be split up in the future. +// @TODO There should be a utf8-strict encoding that rejects invalid UTF-8 code +// points as used by CESU-8. +var StringDecoder = exports.StringDecoder = function(encoding) { + this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, ''); + assertEncoding(encoding); + switch (this.encoding) { + case 'utf8': + // CESU-8 represents each of Surrogate Pair by 3-bytes + this.surrogateSize = 3; + break; + case 'ucs2': + case 'utf16le': + // UTF-16 represents each of Surrogate Pair by 2-bytes + this.surrogateSize = 2; + this.detectIncompleteChar = utf16DetectIncompleteChar; + break; + case 'base64': + // Base-64 stores 3 bytes in 4 chars, and pads the remainder. + this.surrogateSize = 3; + this.detectIncompleteChar = base64DetectIncompleteChar; + break; + default: + this.write = passThroughWrite; + return; + } + + // Enough space to store all bytes of a single character. UTF-8 needs 4 + // bytes, but CESU-8 may require up to 6 (3 bytes per surrogate). + this.charBuffer = new Buffer(6); + // Number of bytes received for the current incomplete multi-byte character. + this.charReceived = 0; + // Number of bytes expected for the current incomplete multi-byte character. + this.charLength = 0; +}; + + +// write decodes the given buffer and returns it as JS string that is +// guaranteed to not contain any partial multi-byte characters. Any partial +// character found at the end of the buffer is buffered up, and will be +// returned when calling write again with the remaining bytes. +// +// Note: Converting a Buffer containing an orphan surrogate to a String +// currently works, but converting a String to a Buffer (via `new Buffer`, or +// Buffer#write) will replace incomplete surrogates with the unicode +// replacement character. See https://codereview.chromium.org/121173009/ . +StringDecoder.prototype.write = function(buffer) { + var charStr = ''; + // if our last write ended with an incomplete multibyte character + while (this.charLength) { + // determine how many remaining bytes this buffer has to offer for this char + var available = (buffer.length >= this.charLength - this.charReceived) ? + this.charLength - this.charReceived : + buffer.length; + + // add the new bytes to the char buffer + buffer.copy(this.charBuffer, this.charReceived, 0, available); + this.charReceived += available; + + if (this.charReceived < this.charLength) { + // still not enough chars in this buffer? wait for more ... + return ''; + } + + // remove bytes belonging to the current character from the buffer + buffer = buffer.slice(available, buffer.length); + + // get the character that was split + charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding); + + // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character + var charCode = charStr.charCodeAt(charStr.length - 1); + if (charCode >= 0xD800 && charCode <= 0xDBFF) { + this.charLength += this.surrogateSize; + charStr = ''; + continue; + } + this.charReceived = this.charLength = 0; + + // if there are no more bytes in this buffer, just emit our char + if (buffer.length === 0) { + return charStr; + } + break; + } + + // determine and set charLength / charReceived + this.detectIncompleteChar(buffer); + + var end = buffer.length; + if (this.charLength) { + // buffer the incomplete character bytes we got + buffer.copy(this.charBuffer, 0, buffer.length - this.charReceived, end); + end -= this.charReceived; + } + + charStr += buffer.toString(this.encoding, 0, end); + + var end = charStr.length - 1; + var charCode = charStr.charCodeAt(end); + // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character + if (charCode >= 0xD800 && charCode <= 0xDBFF) { + var size = this.surrogateSize; + this.charLength += size; + this.charReceived += size; + this.charBuffer.copy(this.charBuffer, size, 0, size); + buffer.copy(this.charBuffer, 0, 0, size); + return charStr.substring(0, end); + } + + // or just emit the charStr + return charStr; +}; + +// detectIncompleteChar determines if there is an incomplete UTF-8 character at +// the end of the given buffer. If so, it sets this.charLength to the byte +// length that character, and sets this.charReceived to the number of bytes +// that are available for this character. +StringDecoder.prototype.detectIncompleteChar = function(buffer) { + // determine how many bytes we have to check at the end of this buffer + var i = (buffer.length >= 3) ? 3 : buffer.length; + + // Figure out if one of the last i bytes of our buffer announces an + // incomplete char. + for (; i > 0; i--) { + var c = buffer[buffer.length - i]; + + // See http://en.wikipedia.org/wiki/UTF-8#Description + + // 110XXXXX + if (i == 1 && c >> 5 == 0x06) { + this.charLength = 2; + break; + } + + // 1110XXXX + if (i <= 2 && c >> 4 == 0x0E) { + this.charLength = 3; + break; + } + + // 11110XXX + if (i <= 3 && c >> 3 == 0x1E) { + this.charLength = 4; + break; + } + } + this.charReceived = i; +}; + +StringDecoder.prototype.end = function(buffer) { + var res = ''; + if (buffer && buffer.length) + res = this.write(buffer); + + if (this.charReceived) { + var cr = this.charReceived; + var buf = this.charBuffer; + var enc = this.encoding; + res += buf.slice(0, cr).toString(enc); + } + + return res; +}; + +function passThroughWrite(buffer) { + return buffer.toString(this.encoding); +} + +function utf16DetectIncompleteChar(buffer) { + this.charReceived = buffer.length % 2; + this.charLength = this.charReceived ? 2 : 0; +} + +function base64DetectIncompleteChar(buffer) { + this.charReceived = buffer.length % 3; + this.charLength = this.charReceived ? 3 : 0; +} + +},{"buffer":17}],38:[function(_dereq_,module,exports){ +module.exports = function isBuffer(arg) { + return arg && typeof arg === 'object' + && typeof arg.copy === 'function' + && typeof arg.fill === 'function' + && typeof arg.readUInt8 === 'function'; +} +},{}],39:[function(_dereq_,module,exports){ +(function (process,global){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var formatRegExp = /%[sdj%]/g; +exports.format = function(f) { + if (!isString(f)) { + var objects = []; + for (var i = 0; i < arguments.length; i++) { + objects.push(inspect(arguments[i])); + } + return objects.join(' '); + } + + var i = 1; + var args = arguments; + var len = args.length; + var str = String(f).replace(formatRegExp, function(x) { + if (x === '%') return '%'; + if (i >= len) return x; + switch (x) { + case '%s': return String(args[i++]); + case '%d': return Number(args[i++]); + case '%j': + try { + return JSON.stringify(args[i++]); + } catch (_) { + return '[Circular]'; + } + default: + return x; + } + }); + for (var x = args[i]; i < len; x = args[++i]) { + if (isNull(x) || !isObject(x)) { + str += ' ' + x; + } else { + str += ' ' + inspect(x); + } + } + return str; +}; + + +// Mark that a method should not be used. +// Returns a modified function which warns once by default. +// If --no-deprecation is set, then it is a no-op. +exports.deprecate = function(fn, msg) { + // Allow for deprecating things in the process of starting up. + if (isUndefined(global.process)) { + return function() { + return exports.deprecate(fn, msg).apply(this, arguments); + }; + } + + if (process.noDeprecation === true) { + return fn; + } + + var warned = false; + function deprecated() { + if (!warned) { + if (process.throwDeprecation) { + throw new Error(msg); + } else if (process.traceDeprecation) { + console.trace(msg); + } else { + console.error(msg); + } + warned = true; + } + return fn.apply(this, arguments); + } + + return deprecated; +}; + + +var debugs = {}; +var debugEnviron; +exports.debuglog = function(set) { + if (isUndefined(debugEnviron)) + debugEnviron = process.env.NODE_DEBUG || ''; + set = set.toUpperCase(); + if (!debugs[set]) { + if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { + var pid = process.pid; + debugs[set] = function() { + var msg = exports.format.apply(exports, arguments); + console.error('%s %d: %s', set, pid, msg); + }; + } else { + debugs[set] = function() {}; + } + } + return debugs[set]; +}; + + +/** + * Echos the value of a value. Trys to print the value out + * in the best way possible given the different types. + * + * @param {Object} obj The object to print out. + * @param {Object} opts Optional options object that alters the output. + */ +/* legacy: obj, showHidden, depth, colors*/ +function inspect(obj, opts) { + // default options + var ctx = { + seen: [], + stylize: stylizeNoColor + }; + // legacy... + if (arguments.length >= 3) ctx.depth = arguments[2]; + if (arguments.length >= 4) ctx.colors = arguments[3]; + if (isBoolean(opts)) { + // legacy... + ctx.showHidden = opts; + } else if (opts) { + // got an "options" object + exports._extend(ctx, opts); + } + // set default options + if (isUndefined(ctx.showHidden)) ctx.showHidden = false; + if (isUndefined(ctx.depth)) ctx.depth = 2; + if (isUndefined(ctx.colors)) ctx.colors = false; + if (isUndefined(ctx.customInspect)) ctx.customInspect = true; + if (ctx.colors) ctx.stylize = stylizeWithColor; + return formatValue(ctx, obj, ctx.depth); +} +exports.inspect = inspect; + + +// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics +inspect.colors = { + 'bold' : [1, 22], + 'italic' : [3, 23], + 'underline' : [4, 24], + 'inverse' : [7, 27], + 'white' : [37, 39], + 'grey' : [90, 39], + 'black' : [30, 39], + 'blue' : [34, 39], + 'cyan' : [36, 39], + 'green' : [32, 39], + 'magenta' : [35, 39], + 'red' : [31, 39], + 'yellow' : [33, 39] +}; + +// Don't use 'blue' not visible on cmd.exe +inspect.styles = { + 'special': 'cyan', + 'number': 'yellow', + 'boolean': 'yellow', + 'undefined': 'grey', + 'null': 'bold', + 'string': 'green', + 'date': 'magenta', + // "name": intentionally not styling + 'regexp': 'red' +}; + + +function stylizeWithColor(str, styleType) { + var style = inspect.styles[styleType]; + + if (style) { + return '\u001b[' + inspect.colors[style][0] + 'm' + str + + '\u001b[' + inspect.colors[style][1] + 'm'; + } else { + return str; + } +} + + +function stylizeNoColor(str, styleType) { + return str; +} + + +function arrayToHash(array) { + var hash = {}; + + array.forEach(function(val, idx) { + hash[val] = true; + }); + + return hash; +} + + +function formatValue(ctx, value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if (ctx.customInspect && + value && + isFunction(value.inspect) && + // Filter out the util module, it's inspect function is special + value.inspect !== exports.inspect && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + var ret = value.inspect(recurseTimes, ctx); + if (!isString(ret)) { + ret = formatValue(ctx, ret, recurseTimes); + } + return ret; + } + + // Primitive types cannot have properties + var primitive = formatPrimitive(ctx, value); + if (primitive) { + return primitive; + } + + // Look up the keys of the object. + var keys = Object.keys(value); + var visibleKeys = arrayToHash(keys); + + if (ctx.showHidden) { + keys = Object.getOwnPropertyNames(value); + } + + // IE doesn't make error fields non-enumerable + // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx + if (isError(value) + && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { + return formatError(value); + } + + // Some type of object without properties can be shortcutted. + if (keys.length === 0) { + if (isFunction(value)) { + var name = value.name ? ': ' + value.name : ''; + return ctx.stylize('[Function' + name + ']', 'special'); + } + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } + if (isDate(value)) { + return ctx.stylize(Date.prototype.toString.call(value), 'date'); + } + if (isError(value)) { + return formatError(value); + } + } + + var base = '', array = false, braces = ['{', '}']; + + // Make Array say that they are Array + if (isArray(value)) { + array = true; + braces = ['[', ']']; + } + + // Make functions say that they are functions + if (isFunction(value)) { + var n = value.name ? ': ' + value.name : ''; + base = ' [Function' + n + ']'; + } + + // Make RegExps say that they are RegExps + if (isRegExp(value)) { + base = ' ' + RegExp.prototype.toString.call(value); + } + + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + Date.prototype.toUTCString.call(value); + } + + // Make error with message first say the error + if (isError(value)) { + base = ' ' + formatError(value); + } + + if (keys.length === 0 && (!array || value.length == 0)) { + return braces[0] + base + braces[1]; + } + + if (recurseTimes < 0) { + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } else { + return ctx.stylize('[Object]', 'special'); + } + } + + ctx.seen.push(value); + + var output; + if (array) { + output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); + } else { + output = keys.map(function(key) { + return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); + }); + } + + ctx.seen.pop(); + + return reduceToSingleString(output, base, braces); +} + + +function formatPrimitive(ctx, value) { + if (isUndefined(value)) + return ctx.stylize('undefined', 'undefined'); + if (isString(value)) { + var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return ctx.stylize(simple, 'string'); + } + if (isNumber(value)) + return ctx.stylize('' + value, 'number'); + if (isBoolean(value)) + return ctx.stylize('' + value, 'boolean'); + // For some reason typeof null is "object", so special case here. + if (isNull(value)) + return ctx.stylize('null', 'null'); +} + + +function formatError(value) { + return '[' + Error.prototype.toString.call(value) + ']'; +} + + +function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { + var output = []; + for (var i = 0, l = value.length; i < l; ++i) { + if (hasOwnProperty(value, String(i))) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + String(i), true)); + } else { + output.push(''); + } + } + keys.forEach(function(key) { + if (!key.match(/^\d+$/)) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + key, true)); + } + }); + return output; +} + + +function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { + var name, str, desc; + desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; + if (desc.get) { + if (desc.set) { + str = ctx.stylize('[Getter/Setter]', 'special'); + } else { + str = ctx.stylize('[Getter]', 'special'); + } + } else { + if (desc.set) { + str = ctx.stylize('[Setter]', 'special'); + } + } + if (!hasOwnProperty(visibleKeys, key)) { + name = '[' + key + ']'; + } + if (!str) { + if (ctx.seen.indexOf(desc.value) < 0) { + if (isNull(recurseTimes)) { + str = formatValue(ctx, desc.value, null); + } else { + str = formatValue(ctx, desc.value, recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (array) { + str = str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n').substr(2); + } else { + str = '\n' + str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = ctx.stylize('[Circular]', 'special'); + } + } + if (isUndefined(name)) { + if (array && key.match(/^\d+$/)) { + return str; + } + name = JSON.stringify('' + key); + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.substr(1, name.length - 2); + name = ctx.stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = ctx.stylize(name, 'string'); + } + } + + return name + ': ' + str; +} + + +function reduceToSingleString(output, base, braces) { + var numLinesEst = 0; + var length = output.reduce(function(prev, cur) { + numLinesEst++; + if (cur.indexOf('\n') >= 0) numLinesEst++; + return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; + }, 0); + + if (length > 60) { + return braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + } + + return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; +} + + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. +function isArray(ar) { + return Array.isArray(ar); +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return isObject(re) && objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return isObject(d) && objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return isObject(e) && + (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +exports.isBuffer = _dereq_('./support/isBuffer'); + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + + +function pad(n) { + return n < 10 ? '0' + n.toString(10) : n.toString(10); +} + + +var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', + 'Oct', 'Nov', 'Dec']; + +// 26 Feb 16:19:34 +function timestamp() { + var d = new Date(); + var time = [pad(d.getHours()), + pad(d.getMinutes()), + pad(d.getSeconds())].join(':'); + return [d.getDate(), months[d.getMonth()], time].join(' '); +} + + +// log is just a thin wrapper to console.log that prepends a timestamp +exports.log = function() { + console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); +}; + + +/** + * Inherit the prototype methods from one constructor into another. + * + * The Function.prototype.inherits from lang.js rewritten as a standalone + * function (not on Function.prototype). NOTE: If this file is to be loaded + * during bootstrapping this function needs to be rewritten using some native + * functions as prototype setup using normal JavaScript does not work as + * expected during bootstrapping (see mirror.js in r114903). + * + * @param {function} ctor Constructor function which needs to inherit the + * prototype. + * @param {function} superCtor Constructor function to inherit prototype from. + */ +exports.inherits = _dereq_('inherits'); + +exports._extend = function(origin, add) { + // Don't do anything if add isn't an object + if (!add || !isObject(add)) return origin; + + var keys = Object.keys(add); + var i = keys.length; + while (i--) { + origin[keys[i]] = add[keys[i]]; + } + return origin; +}; + +function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +} + +}).call(this,_dereq_('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./support/isBuffer":38,"_process":24,"inherits":44}],40:[function(_dereq_,module,exports){ + +/** + * This is the web browser implementation of `debug()`. + * + * Expose `debug()` as the module. + */ + +exports = module.exports = _dereq_('./debug'); +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; + +/** + * Colors. + */ + +exports.colors = [ + 'lightseagreen', + 'forestgreen', + 'goldenrod', + 'dodgerblue', + 'darkorchid', + 'crimson' +]; + +/** + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors + */ + +function useColors() { + // is webkit? http://stackoverflow.com/a/16459606/376773 + return ('WebkitAppearance' in document.documentElement.style) || + // is firebug? http://stackoverflow.com/a/398120/376773 + (window.console && (console.firebug || (console.exception && console.table))) || + // is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + (navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31); +} + +/** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ + +exports.formatters.j = function(v) { + return JSON.stringify(v); +}; + + +/** + * Colorize log arguments if enabled. + * + * @api public + */ + +function formatArgs() { + var args = arguments; + var useColors = this.useColors; + + args[0] = (useColors ? '%c' : '') + + this.namespace + + (useColors ? ' %c' : ' ') + + args[0] + + (useColors ? '%c ' : ' ') + + '+' + exports.humanize(this.diff); + + if (!useColors) return args; + + var c = 'color: ' + this.color; + args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1)); + + // the final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + var index = 0; + var lastC = 0; + args[0].replace(/%[a-z%]/g, function(match) { + if ('%' === match) return; + index++; + if ('%c' === match) { + // we only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); + + args.splice(lastC, 0, c); + return args; +} + +/** + * Invokes `console.log()` when available. + * No-op when `console.log` is not a "function". + * + * @api public + */ + +function log() { + // This hackery is required for IE8, + // where the `console.log` function doesn't have 'apply' + return 'object' == typeof console + && 'function' == typeof console.log + && Function.prototype.apply.call(console.log, console, arguments); +} + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ + +function save(namespaces) { + try { + if (null == namespaces) { + localStorage.removeItem('debug'); + } else { + localStorage.debug = namespaces; + } + } catch(e) {} +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + +function load() { + var r; + try { + r = localStorage.debug; + } catch(e) {} + return r; +} + +/** + * Enable namespaces listed in `localStorage.debug` initially. + */ + +exports.enable(load()); + +},{"./debug":41}],41:[function(_dereq_,module,exports){ + +/** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + * + * Expose `debug()` as the module. + */ + +exports = module.exports = debug; +exports.coerce = coerce; +exports.disable = disable; +exports.enable = enable; +exports.enabled = enabled; +exports.humanize = _dereq_('ms'); + +/** + * The currently active debug mode names, and names to skip. + */ + +exports.names = []; +exports.skips = []; + +/** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lowercased letter, i.e. "n". + */ + +exports.formatters = {}; + +/** + * Previously assigned color. + */ + +var prevColor = 0; + +/** + * Previous log timestamp. + */ + +var prevTime; + +/** + * Select a color. + * + * @return {Number} + * @api private + */ + +function selectColor() { + return exports.colors[prevColor++ % exports.colors.length]; +} + +/** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ + +function debug(namespace) { + + // define the `disabled` version + function disabled() { + } + disabled.enabled = false; + + // define the `enabled` version + function enabled() { + + var self = enabled; + + // set `diff` timestamp + var curr = +new Date(); + var ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; + + // add the `color` if not set + if (null == self.useColors) self.useColors = exports.useColors(); + if (null == self.color && self.useColors) self.color = selectColor(); + + var args = Array.prototype.slice.call(arguments); + + args[0] = exports.coerce(args[0]); + + if ('string' !== typeof args[0]) { + // anything else let's inspect with %o + args = ['%o'].concat(args); + } + + // apply any `formatters` transformations + var index = 0; + args[0] = args[0].replace(/%([a-z%])/g, function(match, format) { + // if we encounter an escaped % then don't increase the array index + if (match === '%') return match; + index++; + var formatter = exports.formatters[format]; + if ('function' === typeof formatter) { + var val = args[index]; + match = formatter.call(self, val); + + // now we need to remove `args[index]` since it's inlined in the `format` + args.splice(index, 1); + index--; + } + return match; + }); + + if ('function' === typeof exports.formatArgs) { + args = exports.formatArgs.apply(self, args); + } + var logFn = enabled.log || exports.log || console.log.bind(console); + logFn.apply(self, args); + } + enabled.enabled = true; + + var fn = exports.enabled(namespace) ? enabled : disabled; + + fn.namespace = namespace; + + return fn; +} + +/** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ + +function enable(namespaces) { + exports.save(namespaces); + + var split = (namespaces || '').split(/[\s,]+/); + var len = split.length; + + for (var i = 0; i < len; i++) { + if (!split[i]) continue; // ignore empty strings + namespaces = split[i].replace(/\*/g, '.*?'); + if (namespaces[0] === '-') { + exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); + } else { + exports.names.push(new RegExp('^' + namespaces + '$')); + } + } +} + +/** + * Disable debug output. + * + * @api public + */ + +function disable() { + exports.enable(''); +} + +/** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + +function enabled(name) { + var i, len; + for (i = 0, len = exports.skips.length; i < len; i++) { + if (exports.skips[i].test(name)) { + return false; + } + } + for (i = 0, len = exports.names.length; i < len; i++) { + if (exports.names[i].test(name)) { + return true; + } + } + return false; +} + +/** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + +function coerce(val) { + if (val instanceof Error) return val.stack || val.message; + return val; +} + +},{"ms":42}],42:[function(_dereq_,module,exports){ +/** + * Helpers. + */ + +var s = 1000; +var m = s * 60; +var h = m * 60; +var d = h * 24; +var y = d * 365.25; + +/** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} options + * @return {String|Number} + * @api public + */ + +module.exports = function(val, options){ + options = options || {}; + if ('string' == typeof val) return parse(val); + return options.long + ? long(val) + : short(val); +}; + +/** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function parse(str) { + var match = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str); + if (!match) return; + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'y': + return n * y; + case 'days': + case 'day': + case 'd': + return n * d; + case 'hours': + case 'hour': + case 'h': + return n * h; + case 'minutes': + case 'minute': + case 'm': + return n * m; + case 'seconds': + case 'second': + case 's': + return n * s; + case 'ms': + return n; + } +} + +/** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function short(ms) { + if (ms >= d) return Math.round(ms / d) + 'd'; + if (ms >= h) return Math.round(ms / h) + 'h'; + if (ms >= m) return Math.round(ms / m) + 'm'; + if (ms >= s) return Math.round(ms / s) + 's'; + return ms + 'ms'; +} + +/** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function long(ms) { + return plural(ms, d, 'day') + || plural(ms, h, 'hour') + || plural(ms, m, 'minute') + || plural(ms, s, 'second') + || ms + ' ms'; +} + +/** + * Pluralization helper. + */ + +function plural(ms, n, name) { + if (ms < n) return; + if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name; + return Math.ceil(ms / n) + ' ' + name + 's'; +} + +},{}],43:[function(_dereq_,module,exports){ +/** + * Copyright (c) 2013 Petka Antonov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions:</p> + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +"use strict"; +function Deque(capacity) { + this._capacity = getCapacity(capacity); + this._length = 0; + this._front = 0; + this._makeCapacity(); + if (isArray(capacity)) { + var len = capacity.length; + for (var i = 0; i < len; ++i) { + this[i] = capacity[i]; + } + this._length = len; + } +} + +Deque.prototype.toArray = function Deque$toArray() { + var len = this._length; + var ret = new Array(len); + var front = this._front; + var capacity = this._capacity; + for (var j = 0; j < len; ++j) { + ret[j] = this[(front + j) & (capacity - 1)]; + } + return ret; +}; + +Deque.prototype.push = function Deque$push(item) { + var argsLength = arguments.length; + var length = this._length; + if (argsLength > 1) { + var capacity = this._capacity; + if (length + argsLength > capacity) { + for (var i = 0; i < argsLength; ++i) { + this._checkCapacity(length + 1); + var j = (this._front + length) & (this._capacity - 1); + this[j] = arguments[i]; + length++; + this._length = length; + } + return length; + } + else { + var j = this._front; + for (var i = 0; i < argsLength; ++i) { + this[(j + length) & (capacity - 1)] = arguments[i]; + j++; + } + this._length = length + argsLength; + return length + argsLength; + } + + } + + if (argsLength === 0) return length; + + this._checkCapacity(length + 1); + var i = (this._front + length) & (this._capacity - 1); + this[i] = item; + this._length = length + 1; + return length + 1; +}; + +Deque.prototype.pop = function Deque$pop() { + var length = this._length; + if (length === 0) { + return void 0; + } + var i = (this._front + length - 1) & (this._capacity - 1); + var ret = this[i]; + this[i] = void 0; + this._length = length - 1; + return ret; +}; + +Deque.prototype.shift = function Deque$shift() { + var length = this._length; + if (length === 0) { + return void 0; + } + var front = this._front; + var ret = this[front]; + this[front] = void 0; + this._front = (front + 1) & (this._capacity - 1); + this._length = length - 1; + return ret; +}; + +Deque.prototype.unshift = function Deque$unshift(item) { + var length = this._length; + var argsLength = arguments.length; + + + if (argsLength > 1) { + var capacity = this._capacity; + if (length + argsLength > capacity) { + for (var i = argsLength - 1; i >= 0; i--) { + this._checkCapacity(length + 1); + var capacity = this._capacity; + var j = (((( this._front - 1 ) & + ( capacity - 1) ) ^ capacity ) - capacity ); + this[j] = arguments[i]; + length++; + this._length = length; + this._front = j; + } + return length; + } + else { + var front = this._front; + for (var i = argsLength - 1; i >= 0; i--) { + var j = (((( front - 1 ) & + ( capacity - 1) ) ^ capacity ) - capacity ); + this[j] = arguments[i]; + front = j; + } + this._front = front; + this._length = length + argsLength; + return length + argsLength; + } + } + + if (argsLength === 0) return length; + + this._checkCapacity(length + 1); + var capacity = this._capacity; + var i = (((( this._front - 1 ) & + ( capacity - 1) ) ^ capacity ) - capacity ); + this[i] = item; + this._length = length + 1; + this._front = i; + return length + 1; +}; + +Deque.prototype.peekBack = function Deque$peekBack() { + var length = this._length; + if (length === 0) { + return void 0; + } + var index = (this._front + length - 1) & (this._capacity - 1); + return this[index]; +}; + +Deque.prototype.peekFront = function Deque$peekFront() { + if (this._length === 0) { + return void 0; + } + return this[this._front]; +}; + +Deque.prototype.get = function Deque$get(index) { + var i = index; + if ((i !== (i | 0))) { + return void 0; + } + var len = this._length; + if (i < 0) { + i = i + len; + } + if (i < 0 || i >= len) { + return void 0; + } + return this[(this._front + i) & (this._capacity - 1)]; +}; + +Deque.prototype.isEmpty = function Deque$isEmpty() { + return this._length === 0; +}; + +Deque.prototype.clear = function Deque$clear() { + this._length = 0; + this._front = 0; + this._makeCapacity(); +}; + +Deque.prototype.toString = function Deque$toString() { + return this.toArray().toString(); +}; + +Deque.prototype.valueOf = Deque.prototype.toString; +Deque.prototype.removeFront = Deque.prototype.shift; +Deque.prototype.removeBack = Deque.prototype.pop; +Deque.prototype.insertFront = Deque.prototype.unshift; +Deque.prototype.insertBack = Deque.prototype.push; +Deque.prototype.enqueue = Deque.prototype.push; +Deque.prototype.dequeue = Deque.prototype.shift; +Deque.prototype.toJSON = Deque.prototype.toArray; + +Object.defineProperty(Deque.prototype, "length", { + get: function() { + return this._length; + }, + set: function() { + throw new RangeError(""); + } +}); + +Deque.prototype._makeCapacity = function Deque$_makeCapacity() { + var len = this._capacity; + for (var i = 0; i < len; ++i) { + this[i] = void 0; + } +}; + +Deque.prototype._checkCapacity = function Deque$_checkCapacity(size) { + if (this._capacity < size) { + this._resizeTo(getCapacity(this._capacity * 1.5 + 16)); + } +}; + +Deque.prototype._resizeTo = function Deque$_resizeTo(capacity) { + var oldFront = this._front; + var oldCapacity = this._capacity; + var oldDeque = new Array(oldCapacity); + var length = this._length; + + arrayCopy(this, 0, oldDeque, 0, oldCapacity); + this._capacity = capacity; + this._makeCapacity(); + this._front = 0; + if (oldFront + length <= oldCapacity) { + arrayCopy(oldDeque, oldFront, this, 0, length); + } else { var lengthBeforeWrapping = + length - ((oldFront + length) & (oldCapacity - 1)); + + arrayCopy(oldDeque, oldFront, this, 0, lengthBeforeWrapping); + arrayCopy(oldDeque, 0, this, lengthBeforeWrapping, + length - lengthBeforeWrapping); + } +}; + + +var isArray = Array.isArray; + +function arrayCopy(src, srcIndex, dst, dstIndex, len) { + for (var j = 0; j < len; ++j) { + dst[j + dstIndex] = src[j + srcIndex]; + } +} + +function pow2AtLeast(n) { + n = n >>> 0; + n = n - 1; + n = n | (n >> 1); + n = n | (n >> 2); + n = n | (n >> 4); + n = n | (n >> 8); + n = n | (n >> 16); + return n + 1; +} + +function getCapacity(capacity) { + if (typeof capacity !== "number") { + if (isArray(capacity)) { + capacity = capacity.length; + } + else { + return 16; + } + } + return pow2AtLeast( + Math.min( + Math.max(16, capacity), 1073741824) + ); +} + +module.exports = Deque; + +},{}],44:[function(_dereq_,module,exports){ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +} + +},{}],45:[function(_dereq_,module,exports){ +var util = _dereq_('util') +var AbstractIterator = _dereq_('abstract-leveldown').AbstractIterator +var ltgt = _dereq_('ltgt') + +module.exports = Iterator + +function Iterator (db, options) { + if (!options) options = {} + this.options = options + AbstractIterator.call(this, db) + this._order = options.reverse ? 'DESC': 'ASC' + this._limit = options.limit + this._count = 0 + this._done = false + var lower = ltgt.lowerBound(options) + var upper = ltgt.upperBound(options) + this._keyRange = lower || upper ? this.db.makeKeyRange({ + lower: lower, + upper: upper, + excludeLower: ltgt.lowerBoundExclusive(options), + excludeUpper: ltgt.upperBoundExclusive(options) + }) : null + this.callback = null +} + +util.inherits(Iterator, AbstractIterator) + +Iterator.prototype.createIterator = function() { + var self = this + + self.iterator = self.db.iterate(function () { + self.onItem.apply(self, arguments) + }, { + keyRange: self._keyRange, + autoContinue: false, + order: self._order, + onError: function(err) { console.log('horrible error', err) }, + }) +} + +// TODO the limit implementation here just ignores all reads after limit has been reached +// it should cancel the iterator instead but I don't know how +Iterator.prototype.onItem = function (value, cursor, cursorTransaction) { + if (!cursor && this.callback) { + this.callback() + this.callback = false + return + } + var shouldCall = true + + if (!!this._limit && this._limit > 0 && this._count++ >= this._limit) + shouldCall = false + + if (shouldCall) this.callback(false, cursor.key, cursor.value) + if (cursor) cursor['continue']() +} + +Iterator.prototype._next = function (callback) { + if (!callback) return new Error('next() requires a callback argument') + if (!this._started) { + this.createIterator() + this._started = true + } + this.callback = callback +} + +},{"abstract-leveldown":48,"ltgt":52,"util":39}],46:[function(_dereq_,module,exports){ +(function (process){ +/* Copyright (c) 2013 Rod Vagg, MIT License */ + +function AbstractChainedBatch (db) { + this._db = db + this._operations = [] + this._written = false +} + +AbstractChainedBatch.prototype._checkWritten = function () { + if (this._written) + throw new Error('write() already called on this batch') +} + +AbstractChainedBatch.prototype.put = function (key, value) { + this._checkWritten() + + var err = this._db._checkKeyValue(key, 'key', this._db._isBuffer) + if (err) throw err + err = this._db._checkKeyValue(value, 'value', this._db._isBuffer) + if (err) throw err + + if (!this._db._isBuffer(key)) key = String(key) + if (!this._db._isBuffer(value)) value = String(value) + + if (typeof this._put == 'function' ) + this._put(key, value) + else + this._operations.push({ type: 'put', key: key, value: value }) + + return this +} + +AbstractChainedBatch.prototype.del = function (key) { + this._checkWritten() + + var err = this._db._checkKeyValue(key, 'key', this._db._isBuffer) + if (err) throw err + + if (!this._db._isBuffer(key)) key = String(key) + + if (typeof this._del == 'function' ) + this._del(key) + else + this._operations.push({ type: 'del', key: key }) + + return this +} + +AbstractChainedBatch.prototype.clear = function () { + this._checkWritten() + + this._operations = [] + + if (typeof this._clear == 'function' ) + this._clear() + + return this +} + +AbstractChainedBatch.prototype.write = function (options, callback) { + this._checkWritten() + + if (typeof options == 'function') + callback = options + if (typeof callback != 'function') + throw new Error('write() requires a callback argument') + if (typeof options != 'object') + options = {} + + this._written = true + + if (typeof this._write == 'function' ) + return this._write(callback) + + if (typeof this._db._batch == 'function') + return this._db._batch(this._operations, options, callback) + + process.nextTick(callback) +} + +module.exports = AbstractChainedBatch +}).call(this,_dereq_('_process')) +},{"_process":24}],47:[function(_dereq_,module,exports){ +(function (process){ +/* Copyright (c) 2013 Rod Vagg, MIT License */ + +function AbstractIterator (db) { + this.db = db + this._ended = false + this._nexting = false +} + +AbstractIterator.prototype.next = function (callback) { + var self = this + + if (typeof callback != 'function') + throw new Error('next() requires a callback argument') + + if (self._ended) + return callback(new Error('cannot call next() after end()')) + if (self._nexting) + return callback(new Error('cannot call next() before previous next() has completed')) + + self._nexting = true + if (typeof self._next == 'function') { + return self._next(function () { + self._nexting = false + callback.apply(null, arguments) + }) + } + + process.nextTick(function () { + self._nexting = false + callback() + }) +} + +AbstractIterator.prototype.end = function (callback) { + if (typeof callback != 'function') + throw new Error('end() requires a callback argument') + + if (this._ended) + return callback(new Error('end() already called on iterator')) + + this._ended = true + + if (typeof this._end == 'function') + return this._end(callback) + + process.nextTick(callback) +} + +module.exports = AbstractIterator + +}).call(this,_dereq_('_process')) +},{"_process":24}],48:[function(_dereq_,module,exports){ +(function (process,Buffer){ +/* Copyright (c) 2013 Rod Vagg, MIT License */ + +var xtend = _dereq_('xtend') + , AbstractIterator = _dereq_('./abstract-iterator') + , AbstractChainedBatch = _dereq_('./abstract-chained-batch') + +function AbstractLevelDOWN (location) { + if (!arguments.length || location === undefined) + throw new Error('constructor requires at least a location argument') + + if (typeof location != 'string') + throw new Error('constructor requires a location string argument') + + this.location = location +} + +AbstractLevelDOWN.prototype.open = function (options, callback) { + if (typeof options == 'function') + callback = options + + if (typeof callback != 'function') + throw new Error('open() requires a callback argument') + + if (typeof options != 'object') + options = {} + + if (typeof this._open == 'function') + return this._open(options, callback) + + process.nextTick(callback) +} + +AbstractLevelDOWN.prototype.close = function (callback) { + if (typeof callback != 'function') + throw new Error('close() requires a callback argument') + + if (typeof this._close == 'function') + return this._close(callback) + + process.nextTick(callback) +} + +AbstractLevelDOWN.prototype.get = function (key, options, callback) { + var err + + if (typeof options == 'function') + callback = options + + if (typeof callback != 'function') + throw new Error('get() requires a callback argument') + + if (err = this._checkKeyValue(key, 'key', this._isBuffer)) + return callback(err) + + if (!this._isBuffer(key)) + key = String(key) + + if (typeof options != 'object') + options = {} + + if (typeof this._get == 'function') + return this._get(key, options, callback) + + process.nextTick(function () { callback(new Error('NotFound')) }) +} + +AbstractLevelDOWN.prototype.put = function (key, value, options, callback) { + var err + + if (typeof options == 'function') + callback = options + + if (typeof callback != 'function') + throw new Error('put() requires a callback argument') + + if (err = this._checkKeyValue(key, 'key', this._isBuffer)) + return callback(err) + + if (err = this._checkKeyValue(value, 'value', this._isBuffer)) + return callback(err) + + if (!this._isBuffer(key)) + key = String(key) + + // coerce value to string in node, don't touch it in browser + // (indexeddb can store any JS type) + if (!this._isBuffer(value) && !process.browser) + value = String(value) + + if (typeof options != 'object') + options = {} + + if (typeof this._put == 'function') + return this._put(key, value, options, callback) + + process.nextTick(callback) +} + +AbstractLevelDOWN.prototype.del = function (key, options, callback) { + var err + + if (typeof options == 'function') + callback = options + + if (typeof callback != 'function') + throw new Error('del() requires a callback argument') + + if (err = this._checkKeyValue(key, 'key', this._isBuffer)) + return callback(err) + + if (!this._isBuffer(key)) + key = String(key) + + if (typeof options != 'object') + options = {} + + if (typeof this._del == 'function') + return this._del(key, options, callback) + + process.nextTick(callback) +} + +AbstractLevelDOWN.prototype.batch = function (array, options, callback) { + if (!arguments.length) + return this._chainedBatch() + + if (typeof options == 'function') + callback = options + + if (typeof callback != 'function') + throw new Error('batch(array) requires a callback argument') + + if (!Array.isArray(array)) + return callback(new Error('batch(array) requires an array argument')) + + if (typeof options != 'object') + options = {} + + var i = 0 + , l = array.length + , e + , err + + for (; i < l; i++) { + e = array[i] + if (typeof e != 'object') + continue + + if (err = this._checkKeyValue(e.type, 'type', this._isBuffer)) + return callback(err) + + if (err = this._checkKeyValue(e.key, 'key', this._isBuffer)) + return callback(err) + + if (e.type == 'put') { + if (err = this._checkKeyValue(e.value, 'value', this._isBuffer)) + return callback(err) + } + } + + if (typeof this._batch == 'function') + return this._batch(array, options, callback) + + process.nextTick(callback) +} + +//TODO: remove from here, not a necessary primitive +AbstractLevelDOWN.prototype.approximateSize = function (start, end, callback) { + if ( start == null + || end == null + || typeof start == 'function' + || typeof end == 'function') { + throw new Error('approximateSize() requires valid `start`, `end` and `callback` arguments') + } + + if (typeof callback != 'function') + throw new Error('approximateSize() requires a callback argument') + + if (!this._isBuffer(start)) + start = String(start) + + if (!this._isBuffer(end)) + end = String(end) + + if (typeof this._approximateSize == 'function') + return this._approximateSize(start, end, callback) + + process.nextTick(function () { + callback(null, 0) + }) +} + +AbstractLevelDOWN.prototype._setupIteratorOptions = function (options) { + var self = this + + options = xtend(options) + + ;[ 'start', 'end', 'gt', 'gte', 'lt', 'lte' ].forEach(function (o) { + if (options[o] && self._isBuffer(options[o]) && options[o].length === 0) + delete options[o] + }) + + options.reverse = !!options.reverse + + // fix `start` so it takes into account gt, gte, lt, lte as appropriate + if (options.reverse && options.lt) + options.start = options.lt + if (options.reverse && options.lte) + options.start = options.lte + if (!options.reverse && options.gt) + options.start = options.gt + if (!options.reverse && options.gte) + options.start = options.gte + + if ((options.reverse && options.lt && !options.lte) + || (!options.reverse && options.gt && !options.gte)) + options.exclusiveStart = true // start should *not* include matching key + + return options +} + +AbstractLevelDOWN.prototype.iterator = function (options) { + if (typeof options != 'object') + options = {} + + options = this._setupIteratorOptions(options) + + if (typeof this._iterator == 'function') + return this._iterator(options) + + return new AbstractIterator(this) +} + +AbstractLevelDOWN.prototype._chainedBatch = function () { + return new AbstractChainedBatch(this) +} + +AbstractLevelDOWN.prototype._isBuffer = function (obj) { + return Buffer.isBuffer(obj) +} + +AbstractLevelDOWN.prototype._checkKeyValue = function (obj, type) { + + if (obj === null || obj === undefined) + return new Error(type + ' cannot be `null` or `undefined`') + + if (this._isBuffer(obj)) { + if (obj.length === 0) + return new Error(type + ' cannot be an empty Buffer') + } else if (String(obj) === '') + return new Error(type + ' cannot be an empty String') +} + +module.exports.AbstractLevelDOWN = AbstractLevelDOWN +module.exports.AbstractIterator = AbstractIterator +module.exports.AbstractChainedBatch = AbstractChainedBatch + +}).call(this,_dereq_('_process'),_dereq_("buffer").Buffer) +},{"./abstract-chained-batch":46,"./abstract-iterator":47,"_process":24,"buffer":17,"xtend":49}],49:[function(_dereq_,module,exports){ +module.exports = extend + +function extend() { + var target = {} + + for (var i = 0; i < arguments.length; i++) { + var source = arguments[i] + + for (var key in source) { + if (source.hasOwnProperty(key)) { + target[key] = source[key] + } + } + } + + return target +} + +},{}],50:[function(_dereq_,module,exports){ +/*global window:false, self:false, define:false, module:false */ + +/** + * @license IDBWrapper - A cross-browser wrapper for IndexedDB + * Copyright (c) 2011 - 2013 Jens Arps + * http://jensarps.de/ + * + * Licensed under the MIT (X11) license + */ + +(function (name, definition, global) { + if (typeof define === 'function') { + define(definition); + } else if (typeof module !== 'undefined' && module.exports) { + module.exports = definition(); + } else { + global[name] = definition(); + } +})('IDBStore', function () { + + 'use strict'; + + var defaultErrorHandler = function (error) { + throw error; + }; + + var defaults = { + storeName: 'Store', + storePrefix: 'IDBWrapper-', + dbVersion: 1, + keyPath: 'id', + autoIncrement: true, + onStoreReady: function () { + }, + onError: defaultErrorHandler, + indexes: [] + }; + + /** + * + * The IDBStore constructor + * + * @constructor + * @name IDBStore + * @version 1.4.1 + * + * @param {Object} [kwArgs] An options object used to configure the store and + * set callbacks + * @param {String} [kwArgs.storeName='Store'] The name of the store + * @param {String} [kwArgs.storePrefix='IDBWrapper-'] A prefix that is + * internally used to construct the name of the database, which will be + * kwArgs.storePrefix + kwArgs.storeName + * @param {Number} [kwArgs.dbVersion=1] The version of the store + * @param {String} [kwArgs.keyPath='id'] The key path to use. If you want to + * setup IDBWrapper to work with out-of-line keys, you need to set this to + * `null` + * @param {Boolean} [kwArgs.autoIncrement=true] If set to true, IDBStore will + * automatically make sure a unique keyPath value is present on each object + * that is stored. + * @param {Function} [kwArgs.onStoreReady] A callback to be called when the + * store is ready to be used. + * @param {Function} [kwArgs.onError=throw] A callback to be called when an + * error occurred during instantiation of the store. + * @param {Array} [kwArgs.indexes=[]] An array of indexData objects + * defining the indexes to use with the store. For every index to be used + * one indexData object needs to be passed in the array. + * An indexData object is defined as follows: + * @param {Object} [kwArgs.indexes.indexData] An object defining the index to + * use + * @param {String} kwArgs.indexes.indexData.name The name of the index + * @param {String} [kwArgs.indexes.indexData.keyPath] The key path of the index + * @param {Boolean} [kwArgs.indexes.indexData.unique] Whether the index is unique + * @param {Boolean} [kwArgs.indexes.indexData.multiEntry] Whether the index is multi entry + * @param {Function} [onStoreReady] A callback to be called when the store + * is ready to be used. + * @example + // create a store for customers with an additional index over the + // `lastname` property. + var myCustomerStore = new IDBStore({ + dbVersion: 1, + storeName: 'customer-index', + keyPath: 'customerid', + autoIncrement: true, + onStoreReady: populateTable, + indexes: [ + { name: 'lastname', keyPath: 'lastname', unique: false, multiEntry: false } + ] + }); + * @example + // create a generic store + var myCustomerStore = new IDBStore({ + storeName: 'my-data-store', + onStoreReady: function(){ + // start working with the store. + } + }); + */ + var IDBStore = function (kwArgs, onStoreReady) { + + if (typeof onStoreReady == 'undefined' && typeof kwArgs == 'function') { + onStoreReady = kwArgs; + } + if (Object.prototype.toString.call(kwArgs) != '[object Object]') { + kwArgs = {}; + } + + for (var key in defaults) { + this[key] = typeof kwArgs[key] != 'undefined' ? kwArgs[key] : defaults[key]; + } + + this.dbName = this.storePrefix + this.storeName; + this.dbVersion = parseInt(this.dbVersion, 10) || 1; + + onStoreReady && (this.onStoreReady = onStoreReady); + + var env = typeof window == 'object' ? window : self; + this.idb = env.indexedDB || env.webkitIndexedDB || env.mozIndexedDB; + this.keyRange = env.IDBKeyRange || env.webkitIDBKeyRange || env.mozIDBKeyRange; + + this.features = { + hasAutoIncrement: !env.mozIndexedDB + }; + + this.consts = { + 'READ_ONLY': 'readonly', + 'READ_WRITE': 'readwrite', + 'VERSION_CHANGE': 'versionchange', + 'NEXT': 'next', + 'NEXT_NO_DUPLICATE': 'nextunique', + 'PREV': 'prev', + 'PREV_NO_DUPLICATE': 'prevunique' + }; + + this.openDB(); + }; + + IDBStore.prototype = /** @lends IDBStore */ { + + /** + * A pointer to the IDBStore ctor + * + * @type IDBStore + */ + constructor: IDBStore, + + /** + * The version of IDBStore + * + * @type String + */ + version: '1.4.1', + + /** + * A reference to the IndexedDB object + * + * @type Object + */ + db: null, + + /** + * The full name of the IndexedDB used by IDBStore, composed of + * this.storePrefix + this.storeName + * + * @type String + */ + dbName: null, + + /** + * The version of the IndexedDB used by IDBStore + * + * @type Number + */ + dbVersion: null, + + /** + * A reference to the objectStore used by IDBStore + * + * @type Object + */ + store: null, + + /** + * The store name + * + * @type String + */ + storeName: null, + + /** + * The key path + * + * @type String + */ + keyPath: null, + + /** + * Whether IDBStore uses autoIncrement + * + * @type Boolean + */ + autoIncrement: null, + + /** + * The indexes used by IDBStore + * + * @type Array + */ + indexes: null, + + /** + * A hashmap of features of the used IDB implementation + * + * @type Object + * @proprty {Boolean} autoIncrement If the implementation supports + * native auto increment + */ + features: null, + + /** + * The callback to be called when the store is ready to be used + * + * @type Function + */ + onStoreReady: null, + + /** + * The callback to be called if an error occurred during instantiation + * of the store + * + * @type Function + */ + onError: null, + + /** + * The internal insertID counter + * + * @type Number + * @private + */ + _insertIdCount: 0, + + /** + * Opens an IndexedDB; called by the constructor. + * + * Will check if versions match and compare provided index configuration + * with existing ones, and update indexes if necessary. + * + * Will call this.onStoreReady() if everything went well and the store + * is ready to use, and this.onError() is something went wrong. + * + * @private + * + */ + openDB: function () { + + var openRequest = this.idb.open(this.dbName, this.dbVersion); + var preventSuccessCallback = false; + + openRequest.onerror = function (error) { + + var gotVersionErr = false; + if ('error' in error.target) { + gotVersionErr = error.target.error.name == 'VersionError'; + } else if ('errorCode' in error.target) { + gotVersionErr = error.target.errorCode == 12; + } + + if (gotVersionErr) { + this.onError(new Error('The version number provided is lower than the existing one.')); + } else { + this.onError(error); + } + }.bind(this); + + openRequest.onsuccess = function (event) { + + if (preventSuccessCallback) { + return; + } + + if(this.db){ + this.onStoreReady(); + return; + } + + this.db = event.target.result; + + if(typeof this.db.version == 'string'){ + this.onError(new Error('The IndexedDB implementation in this browser is outdated. Please upgrade your browser.')); + return; + } + + if(!this.db.objectStoreNames.contains(this.storeName)){ + // We should never ever get here. + // Lets notify the user anyway. + this.onError(new Error('Something is wrong with the IndexedDB implementation in this browser. Please upgrade your browser.')); + return; + } + + var emptyTransaction = this.db.transaction([this.storeName], this.consts.READ_ONLY); + this.store = emptyTransaction.objectStore(this.storeName); + + // check indexes + var existingIndexes = Array.prototype.slice.call(this.getIndexList()); + this.indexes.forEach(function(indexData){ + var indexName = indexData.name; + + if(!indexName){ + preventSuccessCallback = true; + this.onError(new Error('Cannot create index: No index name given.')); + return; + } + + this.normalizeIndexData(indexData); + + if(this.hasIndex(indexName)){ + // check if it complies + var actualIndex = this.store.index(indexName); + var complies = this.indexComplies(actualIndex, indexData); + if(!complies){ + preventSuccessCallback = true; + this.onError(new Error('Cannot modify index "' + indexName + '" for current version. Please bump version number to ' + ( this.dbVersion + 1 ) + '.')); + } + + existingIndexes.splice(existingIndexes.indexOf(indexName), 1); + } else { + preventSuccessCallback = true; + this.onError(new Error('Cannot create new index "' + indexName + '" for current version. Please bump version number to ' + ( this.dbVersion + 1 ) + '.')); + } + + }, this); + + if (existingIndexes.length) { + preventSuccessCallback = true; + this.onError(new Error('Cannot delete index(es) "' + existingIndexes.toString() + '" for current version. Please bump version number to ' + ( this.dbVersion + 1 ) + '.')); + } + + preventSuccessCallback || this.onStoreReady(); + }.bind(this); + + openRequest.onupgradeneeded = function(/* IDBVersionChangeEvent */ event){ + + this.db = event.target.result; + + if(this.db.objectStoreNames.contains(this.storeName)){ + this.store = event.target.transaction.objectStore(this.storeName); + } else { + var optionalParameters = { autoIncrement: this.autoIncrement }; + if (this.keyPath !== null) { + optionalParameters.keyPath = this.keyPath; + } + this.store = this.db.createObjectStore(this.storeName, optionalParameters); + } + + var existingIndexes = Array.prototype.slice.call(this.getIndexList()); + this.indexes.forEach(function(indexData){ + var indexName = indexData.name; + + if(!indexName){ + preventSuccessCallback = true; + this.onError(new Error('Cannot create index: No index name given.')); + } + + this.normalizeIndexData(indexData); + + if(this.hasIndex(indexName)){ + // check if it complies + var actualIndex = this.store.index(indexName); + var complies = this.indexComplies(actualIndex, indexData); + if(!complies){ + // index differs, need to delete and re-create + this.store.deleteIndex(indexName); + this.store.createIndex(indexName, indexData.keyPath, { unique: indexData.unique, multiEntry: indexData.multiEntry }); + } + + existingIndexes.splice(existingIndexes.indexOf(indexName), 1); + } else { + this.store.createIndex(indexName, indexData.keyPath, { unique: indexData.unique, multiEntry: indexData.multiEntry }); + } + + }, this); + + if (existingIndexes.length) { + existingIndexes.forEach(function(_indexName){ + this.store.deleteIndex(_indexName); + }, this); + } + + }.bind(this); + }, + + /** + * Deletes the database used for this store if the IDB implementations + * provides that functionality. + */ + deleteDatabase: function () { + if (this.idb.deleteDatabase) { + this.idb.deleteDatabase(this.dbName); + } + }, + + /********************* + * data manipulation * + *********************/ + + /** + * Puts an object into the store. If an entry with the given id exists, + * it will be overwritten. This method has a different signature for inline + * keys and out-of-line keys; please see the examples below. + * + * @param {*} [key] The key to store. This is only needed if IDBWrapper + * is set to use out-of-line keys. For inline keys - the default scenario - + * this can be omitted. + * @param {Object} value The data object to store. + * @param {Function} [onSuccess] A callback that is called if insertion + * was successful. + * @param {Function} [onError] A callback that is called if insertion + * failed. + * @returns {IDBTransaction} The transaction used for this operation. + * @example + // Storing an object, using inline keys (the default scenario): + var myCustomer = { + customerid: 2346223, + lastname: 'Doe', + firstname: 'John' + }; + myCustomerStore.put(myCustomer, mySuccessHandler, myErrorHandler); + // Note that passing success- and error-handlers is optional. + * @example + // Storing an object, using out-of-line keys: + var myCustomer = { + lastname: 'Doe', + firstname: 'John' + }; + myCustomerStore.put(2346223, myCustomer, mySuccessHandler, myErrorHandler); + // Note that passing success- and error-handlers is optional. + */ + put: function (key, value, onSuccess, onError) { + if (this.keyPath !== null) { + onError = onSuccess; + onSuccess = value; + value = key; + } + onError || (onError = defaultErrorHandler); + onSuccess || (onSuccess = noop); + + var hasSuccess = false, + result = null, + putRequest; + + var putTransaction = this.db.transaction([this.storeName], this.consts.READ_WRITE); + putTransaction.oncomplete = function () { + var callback = hasSuccess ? onSuccess : onError; + callback(result); + }; + putTransaction.onabort = onError; + putTransaction.onerror = onError; + + if (this.keyPath !== null) { // in-line keys + this._addIdPropertyIfNeeded(value); + putRequest = putTransaction.objectStore(this.storeName).put(value); + } else { // out-of-line keys + putRequest = putTransaction.objectStore(this.storeName).put(value, key); + } + putRequest.onsuccess = function (event) { + hasSuccess = true; + result = event.target.result; + }; + putRequest.onerror = onError; + + return putTransaction; + }, + + /** + * Retrieves an object from the store. If no entry exists with the given id, + * the success handler will be called with null as first and only argument. + * + * @param {*} key The id of the object to fetch. + * @param {Function} [onSuccess] A callback that is called if fetching + * was successful. Will receive the object as only argument. + * @param {Function} [onError] A callback that will be called if an error + * occurred during the operation. + * @returns {IDBTransaction} The transaction used for this operation. + */ + get: function (key, onSuccess, onError) { + onError || (onError = defaultErrorHandler); + onSuccess || (onSuccess = noop); + + var hasSuccess = false, + result = null; + + var getTransaction = this.db.transaction([this.storeName], this.consts.READ_ONLY); + getTransaction.oncomplete = function () { + var callback = hasSuccess ? onSuccess : onError; + callback(result); + }; + getTransaction.onabort = onError; + getTransaction.onerror = onError; + var getRequest = getTransaction.objectStore(this.storeName).get(key); + getRequest.onsuccess = function (event) { + hasSuccess = true; + result = event.target.result; + }; + getRequest.onerror = onError; + + return getTransaction; + }, + + /** + * Removes an object from the store. + * + * @param {*} key The id of the object to remove. + * @param {Function} [onSuccess] A callback that is called if the removal + * was successful. + * @param {Function} [onError] A callback that will be called if an error + * occurred during the operation. + * @returns {IDBTransaction} The transaction used for this operation. + */ + remove: function (key, onSuccess, onError) { + onError || (onError = defaultErrorHandler); + onSuccess || (onSuccess = noop); + + var hasSuccess = false, + result = null; + + var removeTransaction = this.db.transaction([this.storeName], this.consts.READ_WRITE); + removeTransaction.oncomplete = function () { + var callback = hasSuccess ? onSuccess : onError; + callback(result); + }; + removeTransaction.onabort = onError; + removeTransaction.onerror = onError; + + var deleteRequest = removeTransaction.objectStore(this.storeName)['delete'](key); + deleteRequest.onsuccess = function (event) { + hasSuccess = true; + result = event.target.result; + }; + deleteRequest.onerror = onError; + + return removeTransaction; + }, + + /** + * Runs a batch of put and/or remove operations on the store. + * + * @param {Array} dataArray An array of objects containing the operation to run + * and the data object (for put operations). + * @param {Function} [onSuccess] A callback that is called if all operations + * were successful. + * @param {Function} [onError] A callback that is called if an error + * occurred during one of the operations. + * @returns {IDBTransaction} The transaction used for this operation. + */ + batch: function (dataArray, onSuccess, onError) { + onError || (onError = defaultErrorHandler); + onSuccess || (onSuccess = noop); + + if(Object.prototype.toString.call(dataArray) != '[object Array]'){ + onError(new Error('dataArray argument must be of type Array.')); + } + var batchTransaction = this.db.transaction([this.storeName] , this.consts.READ_WRITE); + batchTransaction.oncomplete = function () { + var callback = hasSuccess ? onSuccess : onError; + callback(hasSuccess); + }; + batchTransaction.onabort = onError; + batchTransaction.onerror = onError; + + var count = dataArray.length; + var called = false; + var hasSuccess = false; + + var onItemSuccess = function () { + count--; + if (count === 0 && !called) { + called = true; + hasSuccess = true; + } + }; + + dataArray.forEach(function (operation) { + var type = operation.type; + var key = operation.key; + var value = operation.value; + + var onItemError = function (err) { + batchTransaction.abort(); + if (!called) { + called = true; + onError(err, type, key); + } + }; + + if (type == 'remove') { + var deleteRequest = batchTransaction.objectStore(this.storeName)['delete'](key); + deleteRequest.onsuccess = onItemSuccess; + deleteRequest.onerror = onItemError; + } else if (type == 'put') { + var putRequest; + if (this.keyPath !== null) { // in-line keys + this._addIdPropertyIfNeeded(value); + putRequest = batchTransaction.objectStore(this.storeName).put(value); + } else { // out-of-line keys + putRequest = batchTransaction.objectStore(this.storeName).put(value, key); + } + putRequest.onsuccess = onItemSuccess; + putRequest.onerror = onItemError; + } + }, this); + + return batchTransaction; + }, + + /** + * Takes an array of objects and stores them in a single transaction. + * + * @param {Array} dataArray An array of objects to store + * @param {Function} [onSuccess] A callback that is called if all operations + * were successful. + * @param {Function} [onError] A callback that is called if an error + * occurred during one of the operations. + * @returns {IDBTransaction} The transaction used for this operation. + */ + putBatch: function (dataArray, onSuccess, onError) { + var batchData = dataArray.map(function(item){ + return { type: 'put', value: item }; + }); + + return this.batch(batchData, onSuccess, onError); + }, + + /** + * Takes an array of keys and removes matching objects in a single + * transaction. + * + * @param {Array} keyArray An array of keys to remove + * @param {Function} [onSuccess] A callback that is called if all operations + * were successful. + * @param {Function} [onError] A callback that is called if an error + * occurred during one of the operations. + * @returns {IDBTransaction} The transaction used for this operation. + */ + removeBatch: function (keyArray, onSuccess, onError) { + var batchData = keyArray.map(function(key){ + return { type: 'remove', key: key }; + }); + + return this.batch(batchData, onSuccess, onError); + }, + + /** + * Takes an array of keys and fetches matching objects + * + * @param {Array} keyArray An array of keys identifying the objects to fetch + * @param {Function} [onSuccess] A callback that is called if all operations + * were successful. + * @param {Function} [onError] A callback that is called if an error + * occurred during one of the operations. + * @param {String} [arrayType='sparse'] The type of array to pass to the + * success handler. May be one of 'sparse', 'dense' or 'skip'. Defaults to + * 'sparse'. This parameter specifies how to handle the situation if a get + * operation did not throw an error, but there was no matching object in + * the database. In most cases, 'sparse' provides the most desired + * behavior. See the examples for details. + * @returns {IDBTransaction} The transaction used for this operation. + * @example + // given that there are two objects in the database with the keypath + // values 1 and 2, and the call looks like this: + myStore.getBatch([1, 5, 2], onError, function (data) { … }, arrayType); + + // this is what the `data` array will be like: + + // arrayType == 'sparse': + // data is a sparse array containing two entries and having a length of 3: + [Object, 2: Object] + 0: Object + 2: Object + length: 3 + __proto__: Array[0] + // calling forEach on data will result in the callback being called two + // times, with the index parameter matching the index of the key in the + // keyArray. + + // arrayType == 'dense': + // data is a dense array containing three entries and having a length of 3, + // where data[1] is of type undefined: + [Object, undefined, Object] + 0: Object + 1: undefined + 2: Object + length: 3 + __proto__: Array[0] + // calling forEach on data will result in the callback being called three + // times, with the index parameter matching the index of the key in the + // keyArray, but the second call will have undefined as first argument. + + // arrayType == 'skip': + // data is a dense array containing two entries and having a length of 2: + [Object, Object] + 0: Object + 1: Object + length: 2 + __proto__: Array[0] + // calling forEach on data will result in the callback being called two + // times, with the index parameter not matching the index of the key in the + // keyArray. + */ + getBatch: function (keyArray, onSuccess, onError, arrayType) { + onError || (onError = defaultErrorHandler); + onSuccess || (onSuccess = noop); + arrayType || (arrayType = 'sparse'); + + if(Object.prototype.toString.call(keyArray) != '[object Array]'){ + onError(new Error('keyArray argument must be of type Array.')); + } + var batchTransaction = this.db.transaction([this.storeName] , this.consts.READ_ONLY); + batchTransaction.oncomplete = function () { + var callback = hasSuccess ? onSuccess : onError; + callback(result); + }; + batchTransaction.onabort = onError; + batchTransaction.onerror = onError; + + var data = []; + var count = keyArray.length; + var called = false; + var hasSuccess = false; + var result = null; + + var onItemSuccess = function (event) { + if (event.target.result || arrayType == 'dense') { + data.push(event.target.result); + } else if (arrayType == 'sparse') { + data.length++; + } + count--; + if (count === 0) { + called = true; + hasSuccess = true; + result = data; + } + }; + + keyArray.forEach(function (key) { + + var onItemError = function (err) { + called = true; + result = err; + onError(err); + batchTransaction.abort(); + }; + + var getRequest = batchTransaction.objectStore(this.storeName).get(key); + getRequest.onsuccess = onItemSuccess; + getRequest.onerror = onItemError; + + }, this); + + return batchTransaction; + }, + + /** + * Fetches all entries in the store. + * + * @param {Function} [onSuccess] A callback that is called if the operation + * was successful. Will receive an array of objects. + * @param {Function} [onError] A callback that will be called if an error + * occurred during the operation. + * @returns {IDBTransaction} The transaction used for this operation. + */ + getAll: function (onSuccess, onError) { + onError || (onError = defaultErrorHandler); + onSuccess || (onSuccess = noop); + var getAllTransaction = this.db.transaction([this.storeName], this.consts.READ_ONLY); + var store = getAllTransaction.objectStore(this.storeName); + if (store.getAll) { + this._getAllNative(getAllTransaction, store, onSuccess, onError); + } else { + this._getAllCursor(getAllTransaction, store, onSuccess, onError); + } + + return getAllTransaction; + }, + + /** + * Implements getAll for IDB implementations that have a non-standard + * getAll() method. + * + * @param {Object} getAllTransaction An open READ transaction. + * @param {Object} store A reference to the store. + * @param {Function} onSuccess A callback that will be called if the + * operation was successful. + * @param {Function} onError A callback that will be called if an + * error occurred during the operation. + * @private + */ + _getAllNative: function (getAllTransaction, store, onSuccess, onError) { + var hasSuccess = false, + result = null; + + getAllTransaction.oncomplete = function () { + var callback = hasSuccess ? onSuccess : onError; + callback(result); + }; + getAllTransaction.onabort = onError; + getAllTransaction.onerror = onError; + + var getAllRequest = store.getAll(); + getAllRequest.onsuccess = function (event) { + hasSuccess = true; + result = event.target.result; + }; + getAllRequest.onerror = onError; + }, + + /** + * Implements getAll for IDB implementations that do not have a getAll() + * method. + * + * @param {Object} getAllTransaction An open READ transaction. + * @param {Object} store A reference to the store. + * @param {Function} onSuccess A callback that will be called if the + * operation was successful. + * @param {Function} onError A callback that will be called if an + * error occurred during the operation. + * @private + */ + _getAllCursor: function (getAllTransaction, store, onSuccess, onError) { + var all = [], + hasSuccess = false, + result = null; + + getAllTransaction.oncomplete = function () { + var callback = hasSuccess ? onSuccess : onError; + callback(result); + }; + getAllTransaction.onabort = onError; + getAllTransaction.onerror = onError; + + var cursorRequest = store.openCursor(); + cursorRequest.onsuccess = function (event) { + var cursor = event.target.result; + if (cursor) { + all.push(cursor.value); + cursor['continue'](); + } + else { + hasSuccess = true; + result = all; + } + }; + cursorRequest.onError = onError; + }, + + /** + * Clears the store, i.e. deletes all entries in the store. + * + * @param {Function} [onSuccess] A callback that will be called if the + * operation was successful. + * @param {Function} [onError] A callback that will be called if an + * error occurred during the operation. + * @returns {IDBTransaction} The transaction used for this operation. + */ + clear: function (onSuccess, onError) { + onError || (onError = defaultErrorHandler); + onSuccess || (onSuccess = noop); + + var hasSuccess = false, + result = null; + + var clearTransaction = this.db.transaction([this.storeName], this.consts.READ_WRITE); + clearTransaction.oncomplete = function () { + var callback = hasSuccess ? onSuccess : onError; + callback(result); + }; + clearTransaction.onabort = onError; + clearTransaction.onerror = onError; + + var clearRequest = clearTransaction.objectStore(this.storeName).clear(); + clearRequest.onsuccess = function (event) { + hasSuccess = true; + result = event.target.result; + }; + clearRequest.onerror = onError; + + return clearTransaction; + }, + + /** + * Checks if an id property needs to present on a object and adds one if + * necessary. + * + * @param {Object} dataObj The data object that is about to be stored + * @private + */ + _addIdPropertyIfNeeded: function (dataObj) { + if (!this.features.hasAutoIncrement && typeof dataObj[this.keyPath] == 'undefined') { + dataObj[this.keyPath] = this._insertIdCount++ + Date.now(); + } + }, + + /************ + * indexing * + ************/ + + /** + * Returns a DOMStringList of index names of the store. + * + * @return {DOMStringList} The list of index names + */ + getIndexList: function () { + return this.store.indexNames; + }, + + /** + * Checks if an index with the given name exists in the store. + * + * @param {String} indexName The name of the index to look for + * @return {Boolean} Whether the store contains an index with the given name + */ + hasIndex: function (indexName) { + return this.store.indexNames.contains(indexName); + }, + + /** + * Normalizes an object containing index data and assures that all + * properties are set. + * + * @param {Object} indexData The index data object to normalize + * @param {String} indexData.name The name of the index + * @param {String} [indexData.keyPath] The key path of the index + * @param {Boolean} [indexData.unique] Whether the index is unique + * @param {Boolean} [indexData.multiEntry] Whether the index is multi entry + */ + normalizeIndexData: function (indexData) { + indexData.keyPath = indexData.keyPath || indexData.name; + indexData.unique = !!indexData.unique; + indexData.multiEntry = !!indexData.multiEntry; + }, + + /** + * Checks if an actual index complies with an expected index. + * + * @param {Object} actual The actual index found in the store + * @param {Object} expected An Object describing an expected index + * @return {Boolean} Whether both index definitions are identical + */ + indexComplies: function (actual, expected) { + var complies = ['keyPath', 'unique', 'multiEntry'].every(function (key) { + // IE10 returns undefined for no multiEntry + if (key == 'multiEntry' && actual[key] === undefined && expected[key] === false) { + return true; + } + // Compound keys + if (key == 'keyPath' && Object.prototype.toString.call(expected[key]) == '[object Array]') { + var exp = expected.keyPath; + var act = actual.keyPath; + + // IE10 can't handle keyPath sequences and stores them as a string. + // The index will be unusable there, but let's still return true if + // the keyPath sequence matches. + if (typeof act == 'string') { + return exp.toString() == act; + } + + // Chrome/Opera stores keyPath squences as DOMStringList, Firefox + // as Array + if ( ! (typeof act.contains == 'function' || typeof act.indexOf == 'function') ) { + return false; + } + + if (act.length !== exp.length) { + return false; + } + + for (var i = 0, m = exp.length; i<m; i++) { + if ( ! ( (act.contains && act.contains(exp[i])) || act.indexOf(exp[i] !== -1) )) { + return false; + } + } + return true; + } + return expected[key] == actual[key]; + }); + return complies; + }, + + /********** + * cursor * + **********/ + + /** + * Iterates over the store using the given options and calling onItem + * for each entry matching the options. + * + * @param {Function} onItem A callback to be called for each match + * @param {Object} [options] An object defining specific options + * @param {Object} [options.index=null] An IDBIndex to operate on + * @param {String} [options.order=ASC] The order in which to provide the + * results, can be 'DESC' or 'ASC' + * @param {Boolean} [options.autoContinue=true] Whether to automatically + * iterate the cursor to the next result + * @param {Boolean} [options.filterDuplicates=false] Whether to exclude + * duplicate matches + * @param {Object} [options.keyRange=null] An IDBKeyRange to use + * @param {Boolean} [options.writeAccess=false] Whether grant write access + * to the store in the onItem callback + * @param {Function} [options.onEnd=null] A callback to be called after + * iteration has ended + * @param {Function} [options.onError=throw] A callback to be called + * if an error occurred during the operation. + * @returns {IDBTransaction} The transaction used for this operation. + */ + iterate: function (onItem, options) { + options = mixin({ + index: null, + order: 'ASC', + autoContinue: true, + filterDuplicates: false, + keyRange: null, + writeAccess: false, + onEnd: null, + onError: defaultErrorHandler + }, options || {}); + + var directionType = options.order.toLowerCase() == 'desc' ? 'PREV' : 'NEXT'; + if (options.filterDuplicates) { + directionType += '_NO_DUPLICATE'; + } + + var hasSuccess = false; + var cursorTransaction = this.db.transaction([this.storeName], this.consts[options.writeAccess ? 'READ_WRITE' : 'READ_ONLY']); + var cursorTarget = cursorTransaction.objectStore(this.storeName); + if (options.index) { + cursorTarget = cursorTarget.index(options.index); + } + + cursorTransaction.oncomplete = function () { + if (!hasSuccess) { + options.onError(null); + return; + } + if (options.onEnd) { + options.onEnd(); + } else { + onItem(null); + } + }; + cursorTransaction.onabort = options.onError; + cursorTransaction.onerror = options.onError; + + var cursorRequest = cursorTarget.openCursor(options.keyRange, this.consts[directionType]); + cursorRequest.onerror = options.onError; + cursorRequest.onsuccess = function (event) { + var cursor = event.target.result; + if (cursor) { + onItem(cursor.value, cursor, cursorTransaction); + if (options.autoContinue) { + cursor['continue'](); + } + } else { + hasSuccess = true; + } + }; + + return cursorTransaction; + }, + + /** + * Runs a query against the store and passes an array containing matched + * objects to the success handler. + * + * @param {Function} onSuccess A callback to be called when the operation + * was successful. + * @param {Object} [options] An object defining specific query options + * @param {Object} [options.index=null] An IDBIndex to operate on + * @param {String} [options.order=ASC] The order in which to provide the + * results, can be 'DESC' or 'ASC' + * @param {Boolean} [options.filterDuplicates=false] Whether to exclude + * duplicate matches + * @param {Object} [options.keyRange=null] An IDBKeyRange to use + * @param {Function} [options.onError=throw] A callback to be called if an error + * occurred during the operation. + * @returns {IDBTransaction} The transaction used for this operation. + */ + query: function (onSuccess, options) { + var result = []; + options = options || {}; + options.onEnd = function () { + onSuccess(result); + }; + return this.iterate(function (item) { + result.push(item); + }, options); + }, + + /** + * + * Runs a query against the store, but only returns the number of matches + * instead of the matches itself. + * + * @param {Function} onSuccess A callback to be called if the opration + * was successful. + * @param {Object} [options] An object defining specific options + * @param {Object} [options.index=null] An IDBIndex to operate on + * @param {Object} [options.keyRange=null] An IDBKeyRange to use + * @param {Function} [options.onError=throw] A callback to be called if an error + * occurred during the operation. + * @returns {IDBTransaction} The transaction used for this operation. + */ + count: function (onSuccess, options) { + + options = mixin({ + index: null, + keyRange: null + }, options || {}); + + var onError = options.onError || defaultErrorHandler; + + var hasSuccess = false, + result = null; + + var cursorTransaction = this.db.transaction([this.storeName], this.consts.READ_ONLY); + cursorTransaction.oncomplete = function () { + var callback = hasSuccess ? onSuccess : onError; + callback(result); + }; + cursorTransaction.onabort = onError; + cursorTransaction.onerror = onError; + + var cursorTarget = cursorTransaction.objectStore(this.storeName); + if (options.index) { + cursorTarget = cursorTarget.index(options.index); + } + var countRequest = cursorTarget.count(options.keyRange); + countRequest.onsuccess = function (evt) { + hasSuccess = true; + result = evt.target.result; + }; + countRequest.onError = onError; + + return cursorTransaction; + }, + + /**************/ + /* key ranges */ + /**************/ + + /** + * Creates a key range using specified options. This key range can be + * handed over to the count() and iterate() methods. + * + * Note: You must provide at least one or both of "lower" or "upper" value. + * + * @param {Object} options The options for the key range to create + * @param {*} [options.lower] The lower bound + * @param {Boolean} [options.excludeLower] Whether to exclude the lower + * bound passed in options.lower from the key range + * @param {*} [options.upper] The upper bound + * @param {Boolean} [options.excludeUpper] Whether to exclude the upper + * bound passed in options.upper from the key range + * @param {*} [options.only] A single key value. Use this if you need a key + * range that only includes one value for a key. Providing this + * property invalidates all other properties. + * @return {Object} The IDBKeyRange representing the specified options + */ + makeKeyRange: function(options){ + /*jshint onecase:true */ + var keyRange, + hasLower = typeof options.lower != 'undefined', + hasUpper = typeof options.upper != 'undefined', + isOnly = typeof options.only != 'undefined'; + + switch(true){ + case isOnly: + keyRange = this.keyRange.only(options.only); + break; + case hasLower && hasUpper: + keyRange = this.keyRange.bound(options.lower, options.upper, options.excludeLower, options.excludeUpper); + break; + case hasLower: + keyRange = this.keyRange.lowerBound(options.lower, options.excludeLower); + break; + case hasUpper: + keyRange = this.keyRange.upperBound(options.upper, options.excludeUpper); + break; + default: + throw new Error('Cannot create KeyRange. Provide one or both of "lower" or "upper" value, or an "only" value.'); + } + + return keyRange; + + } + + }; + + /** helpers **/ + + var noop = function () { + }; + var empty = {}; + var mixin = function (target, source) { + var name, s; + for (name in source) { + s = source[name]; + if (s !== empty[name] && s !== target[name]) { + target[name] = s; + } + } + return target; + }; + + IDBStore.version = IDBStore.prototype.version; + + return IDBStore; + +}, this); + +},{}],51:[function(_dereq_,module,exports){ +var Buffer = _dereq_('buffer').Buffer; + +module.exports = isBuffer; + +function isBuffer (o) { + return Buffer.isBuffer(o) + || /\[object (.+Array|Array.+)\]/.test(Object.prototype.toString.call(o)); +} + +},{"buffer":17}],52:[function(_dereq_,module,exports){ +(function (Buffer){ + +exports.compare = function (a, b) { + + if(Buffer.isBuffer(a)) { + var l = Math.min(a.length, b.length) + for(var i = 0; i < l; i++) { + var cmp = a[i] - b[i] + if(cmp) return cmp + } + return a.length - b.length + } + + return a < b ? -1 : a > b ? 1 : 0 +} + +function has(obj, key) { + return Object.hasOwnProperty.call(obj, key) +} + +// to be compatible with the current abstract-leveldown tests +// nullish or empty strings. +// I could use !!val but I want to permit numbers and booleans, +// if possible. + +function isDef (val) { + return val !== undefined && val !== '' +} + +function has (range, name) { + return Object.hasOwnProperty.call(range, name) +} + +function hasKey(range, name) { + return Object.hasOwnProperty.call(range, name) && name +} + +var lowerBoundKey = exports.lowerBoundKey = function (range) { + return ( + hasKey(range, 'gt') + || hasKey(range, 'gte') + || hasKey(range, 'min') + || (range.reverse ? hasKey(range, 'end') : hasKey(range, 'start')) + || undefined + ) +} + +var lowerBound = exports.lowerBound = function (range) { + var k = lowerBoundKey(range) + return k && range[k] + return ( + has(range, 'gt') ? range.gt + : has(range, 'gte') ? range.gte + : has(range, 'min') ? range.min + : has(range, 'start') && !range.reverse ? range.start + : has(range, 'end') && range.reverse ? range.end + : undefined + ) +} + +exports.lowerBoundInclusive = function (range) { + return has(range, 'gt') ? false : true +} + +exports.upperBoundInclusive = + function (range) { + return has(range, 'lt') || !range.minEx ? false : true + } + +var lowerBoundExclusive = exports.lowerBoundExclusive = + function (range) { + return has(range, 'gt') || range.minEx ? true : false + } + +var upperBoundExclusive = exports.upperBoundExclusive = + function (range) { + return has(range, 'lt') ? true : false + } + +var upperBoundKey = exports.upperBoundKey = function (range) { + return ( + hasKey(range, 'lt') + || hasKey(range, 'lte') + || hasKey(range, 'max') + || (range.reverse ? hasKey(range, 'start') : hasKey(range, 'end')) + || undefined + ) +} + +var upperBound = exports.upperBound = function (range) { + var k = upperBoundKey(range) + return k && range[k] +} + +function id (e) { return e } + +exports.toLtgt = function (range, _range, map, lower, upper) { + _range = _range || {} + map = map || id + var defaults = arguments.length > 3 + var lb = exports.lowerBoundKey(range) + var ub = exports.upperBoundKey(range) + if(lb) { + if(lb === 'gt') _range.gt = map(range.gt) + else _range.gte = map(range[lb]) + } + else if(defaults) + _range.gte = lower + + if(ub) { + if(ub === 'lt') _range.lt = map(range.lt) + else _range.lte = map(range[ub]) + } + else if(defaults) + _range.lte = upper + + _range.reverse = !!range.reverse + + return _range +} + +exports.contains = function (range, key, compare) { + compare = compare || exports.compare + + var lb = lowerBound(range) + if(isDef(lb)) { + var cmp = compare(key, lb) + if(cmp < 0 || (cmp === 0 && lowerBoundExclusive(range))) + return false + } + + var ub = upperBound(range) + if(isDef(ub)) { + var cmp = compare(key, ub) + if(cmp > 0 || (cmp === 0) && upperBoundExclusive(range)) + return false + } + + return true +} + +exports.filter = function (range, compare) { + return function (key) { + return exports.contains(range, key, compare) + } +} + +}).call(this,_dereq_("buffer").Buffer) +},{"buffer":17}],53:[function(_dereq_,module,exports){ +(function (Buffer){ +/** + * Convert a typed array to a Buffer without a copy + * + * Author: Feross Aboukhadijeh <feross@feross.org> <http://feross.org> + * License: MIT + * + * `npm install typedarray-to-buffer` + */ + +module.exports = function (arr) { + if (typeof Buffer._augment === 'function' && Buffer.TYPED_ARRAY_SUPPORT) { + // If `Buffer` is from the `buffer` module and this browser supports typed arrays, + // then augment it with all the `Buffer` methods. + return Buffer._augment(arr) + } else { + // Otherwise, fallback to creating a `Buffer` with a copy. + return new Buffer(arr) + } +} + +}).call(this,_dereq_("buffer").Buffer) +},{"buffer":17}],54:[function(_dereq_,module,exports){ +module.exports = hasKeys + +function hasKeys(source) { + return source !== null && + (typeof source === "object" || + typeof source === "function") +} + +},{}],55:[function(_dereq_,module,exports){ +var Keys = _dereq_("object-keys") +var hasKeys = _dereq_("./has-keys") + +module.exports = extend + +function extend() { + var target = {} + + for (var i = 0; i < arguments.length; i++) { + var source = arguments[i] + + if (!hasKeys(source)) { + continue + } + + var keys = Keys(source) + + for (var j = 0; j < keys.length; j++) { + var name = keys[j] + target[name] = source[name] + } + } + + return target +} + +},{"./has-keys":54,"object-keys":57}],56:[function(_dereq_,module,exports){ +var hasOwn = Object.prototype.hasOwnProperty; +var toString = Object.prototype.toString; + +var isFunction = function (fn) { + var isFunc = (typeof fn === 'function' && !(fn instanceof RegExp)) || toString.call(fn) === '[object Function]'; + if (!isFunc && typeof window !== 'undefined') { + isFunc = fn === window.setTimeout || fn === window.alert || fn === window.confirm || fn === window.prompt; + } + return isFunc; +}; + +module.exports = function forEach(obj, fn) { + if (!isFunction(fn)) { + throw new TypeError('iterator must be a function'); + } + var i, k, + isString = typeof obj === 'string', + l = obj.length, + context = arguments.length > 2 ? arguments[2] : null; + if (l === +l) { + for (i = 0; i < l; i++) { + if (context === null) { + fn(isString ? obj.charAt(i) : obj[i], i, obj); + } else { + fn.call(context, isString ? obj.charAt(i) : obj[i], i, obj); + } + } + } else { + for (k in obj) { + if (hasOwn.call(obj, k)) { + if (context === null) { + fn(obj[k], k, obj); + } else { + fn.call(context, obj[k], k, obj); + } + } + } + } +}; + + +},{}],57:[function(_dereq_,module,exports){ +module.exports = Object.keys || _dereq_('./shim'); + + +},{"./shim":59}],58:[function(_dereq_,module,exports){ +var toString = Object.prototype.toString; + +module.exports = function isArguments(value) { + var str = toString.call(value); + var isArguments = str === '[object Arguments]'; + if (!isArguments) { + isArguments = str !== '[object Array]' + && value !== null + && typeof value === 'object' + && typeof value.length === 'number' + && value.length >= 0 + && toString.call(value.callee) === '[object Function]'; + } + return isArguments; +}; + + +},{}],59:[function(_dereq_,module,exports){ +(function () { + "use strict"; + + // modified from https://github.com/kriskowal/es5-shim + var has = Object.prototype.hasOwnProperty, + toString = Object.prototype.toString, + forEach = _dereq_('./foreach'), + isArgs = _dereq_('./isArguments'), + hasDontEnumBug = !({'toString': null}).propertyIsEnumerable('toString'), + hasProtoEnumBug = (function () {}).propertyIsEnumerable('prototype'), + dontEnums = [ + "toString", + "toLocaleString", + "valueOf", + "hasOwnProperty", + "isPrototypeOf", + "propertyIsEnumerable", + "constructor" + ], + keysShim; + + keysShim = function keys(object) { + var isObject = object !== null && typeof object === 'object', + isFunction = toString.call(object) === '[object Function]', + isArguments = isArgs(object), + theKeys = []; + + if (!isObject && !isFunction && !isArguments) { + throw new TypeError("Object.keys called on a non-object"); + } + + if (isArguments) { + forEach(object, function (value) { + theKeys.push(value); + }); + } else { + var name, + skipProto = hasProtoEnumBug && isFunction; + + for (name in object) { + if (!(skipProto && name === 'prototype') && has.call(object, name)) { + theKeys.push(name); + } + } + } + + if (hasDontEnumBug) { + var ctor = object.constructor, + skipConstructor = ctor && ctor.prototype === object; + + forEach(dontEnums, function (dontEnum) { + if (!(skipConstructor && dontEnum === 'constructor') && has.call(object, dontEnum)) { + theKeys.push(dontEnum); + } + }); + } + return theKeys; + }; + + module.exports = keysShim; +}()); + + +},{"./foreach":56,"./isArguments":58}],60:[function(_dereq_,module,exports){ +function addOperation (type, key, value, options) { + var operation = { + type: type, + key: key, + value: value, + options: options + } + + if (options && options.prefix) { + operation.prefix = options.prefix + delete options.prefix + } + + this._operations.push(operation) + + return this +} + +function Batch(sdb) { + this._operations = [] + this._sdb = sdb + + this.put = addOperation.bind(this, 'put') + this.del = addOperation.bind(this, 'del') +} + +var B = Batch.prototype + + +B.clear = function () { + this._operations = [] +} + +B.write = function (cb) { + this._sdb.batch(this._operations, cb) +} + +module.exports = Batch + +},{}],61:[function(_dereq_,module,exports){ +(function (process){ +var EventEmitter = _dereq_('events').EventEmitter +var next = process.nextTick +var SubDb = _dereq_('./sub') +var Batch = _dereq_('./batch') +var fixRange = _dereq_('level-fix-range') + +var Hooks = _dereq_('level-hooks') + +module.exports = function (_db, options) { + function DB () {} + DB.prototype = _db + var db = new DB() + + if (db.sublevel) return db + + options = options || {} + + //use \xff (255) as the seperator, + //so that sections of the database will sort after the regular keys + var sep = options.sep = options.sep || '\xff' + db._options = options + + Hooks(db) + + db.sublevels = {} + + db.sublevel = function (prefix, options) { + if(db.sublevels[prefix]) + return db.sublevels[prefix] + return new SubDb(db, prefix, options || this._options) + } + + db.methods = {} + + db.prefix = function (key) { + return '' + (key || '') + } + + db.pre = function (range, hook) { + if(!hook) + hook = range, range = { + max : sep + } + return db.hooks.pre(range, hook) + } + + db.post = function (range, hook) { + if(!hook) + hook = range, range = { + max : sep + } + return db.hooks.post(range, hook) + } + + function safeRange(fun) { + return function (opts) { + opts = opts || {} + opts = fixRange(opts) + + if(opts.reverse) opts.start = opts.start || sep + else opts.end = opts.end || sep + + return fun.call(db, opts) + } + } + + db.readStream = + db.createReadStream = safeRange(db.createReadStream) + db.keyStream = + db.createKeyStream = safeRange(db.createKeyStream) + db.valuesStream = + db.createValueStream = safeRange(db.createValueStream) + + var batch = db.batch + db.batch = function (changes, opts, cb) { + if(!Array.isArray(changes)) + return new Batch(db) + changes.forEach(function (e) { + if(e.prefix) { + if('function' === typeof e.prefix.prefix) + e.key = e.prefix.prefix(e.key) + else if('string' === typeof e.prefix) + e.key = e.prefix + e.key + } + }) + batch.call(db, changes, opts, cb) + } + return db +} + + +}).call(this,_dereq_('_process')) +},{"./batch":60,"./sub":72,"_process":24,"events":21,"level-fix-range":62,"level-hooks":64}],62:[function(_dereq_,module,exports){ +var clone = _dereq_('clone') + +module.exports = +function fixRange(opts) { + opts = clone(opts) + + var reverse = opts.reverse + var end = opts.max || opts.end + var start = opts.min || opts.start + + var range = [start, end] + if(start != null && end != null) + range.sort() + if(reverse) + range = range.reverse() + + opts.start = range[0] + opts.end = range[1] + + delete opts.min + delete opts.max + + return opts +} + +},{"clone":63}],63:[function(_dereq_,module,exports){ +(function (Buffer){ +'use strict'; + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + +// shim for Node's 'util' package +// DO NOT REMOVE THIS! It is required for compatibility with EnderJS (http://enderjs.com/). +var util = { + isArray: function (ar) { + return Array.isArray(ar) || (typeof ar === 'object' && objectToString(ar) === '[object Array]'); + }, + isDate: function (d) { + return typeof d === 'object' && objectToString(d) === '[object Date]'; + }, + isRegExp: function (re) { + return typeof re === 'object' && objectToString(re) === '[object RegExp]'; + }, + getRegExpFlags: function (re) { + var flags = ''; + re.global && (flags += 'g'); + re.ignoreCase && (flags += 'i'); + re.multiline && (flags += 'm'); + return flags; + } +}; + + +if (typeof module === 'object') + module.exports = clone; + +/** + * Clones (copies) an Object using deep copying. + * + * This function supports circular references by default, but if you are certain + * there are no circular references in your object, you can save some CPU time + * by calling clone(obj, false). + * + * Caution: if `circular` is false and `parent` contains circular references, + * your program may enter an infinite loop and crash. + * + * @param `parent` - the object to be cloned + * @param `circular` - set to true if the object to be cloned may contain + * circular references. (optional - true by default) + * @param `depth` - set to a number if the object is only to be cloned to + * a particular depth. (optional - defaults to Infinity) + * @param `prototype` - sets the prototype to be used when cloning an object. + * (optional - defaults to parent prototype). +*/ + +function clone(parent, circular, depth, prototype) { + // maintain two arrays for circular references, where corresponding parents + // and children have the same index + var allParents = []; + var allChildren = []; + + var useBuffer = typeof Buffer != 'undefined'; + + if (typeof circular == 'undefined') + circular = true; + + if (typeof depth == 'undefined') + depth = Infinity; + + // recurse this function so we don't reset allParents and allChildren + function _clone(parent, depth) { + // cloning null always returns null + if (parent === null) + return null; + + if (depth == 0) + return parent; + + var child; + var proto; + if (typeof parent != 'object') { + return parent; + } + + if (util.isArray(parent)) { + child = []; + } else if (util.isRegExp(parent)) { + child = new RegExp(parent.source, util.getRegExpFlags(parent)); + if (parent.lastIndex) child.lastIndex = parent.lastIndex; + } else if (util.isDate(parent)) { + child = new Date(parent.getTime()); + } else if (useBuffer && Buffer.isBuffer(parent)) { + child = new Buffer(parent.length); + parent.copy(child); + return child; + } else { + if (typeof prototype == 'undefined') { + proto = Object.getPrototypeOf(parent); + child = Object.create(proto); + } + else { + child = Object.create(prototype); + proto = prototype; + } + } + + if (circular) { + var index = allParents.indexOf(parent); + + if (index != -1) { + return allChildren[index]; + } + allParents.push(parent); + allChildren.push(child); + } + + for (var i in parent) { + var attrs; + if (proto) { + attrs = Object.getOwnPropertyDescriptor(proto, i); + } + + if (attrs && attrs.set == null) { + continue; + } + child[i] = _clone(parent[i], depth - 1); + } + + return child; + } + + return _clone(parent, depth); +} + +/** + * Simple flat clone using prototype, accepts only objects, usefull for property + * override on FLAT configuration object (no nested props). + * + * USE WITH CAUTION! This may not behave as you wish if you do not know how this + * works. + */ +clone.clonePrototype = function(parent) { + if (parent === null) + return null; + + var c = function () {}; + c.prototype = parent; + return new c(); +}; + +}).call(this,_dereq_("buffer").Buffer) +},{"buffer":17}],64:[function(_dereq_,module,exports){ +var ranges = _dereq_('string-range') + +module.exports = function (db) { + + if(db.hooks) { + return + } + + var posthooks = [] + var prehooks = [] + + function getPrefix (p) { + return p && ( + 'string' === typeof p ? p + : 'string' === typeof p.prefix ? p.prefix + : 'function' === typeof p.prefix ? p.prefix() + : '' + ) + } + + function getKeyEncoding (db) { + if(db && db._getKeyEncoding) + return db._getKeyEncoding(db) + } + + function getValueEncoding (db) { + if(db && db._getValueEncoding) + return db._getValueEncoding(db) + } + + function remover (array, item) { + return function () { + var i = array.indexOf(item) + if(!~i) return false + array.splice(i, 1) + return true + } + } + + db.hooks = { + post: function (prefix, hook) { + if(!hook) hook = prefix, prefix = '' + var h = {test: ranges.checker(prefix), hook: hook} + posthooks.push(h) + return remover(posthooks, h) + }, + pre: function (prefix, hook) { + if(!hook) hook = prefix, prefix = '' + var h = { + test: ranges.checker(prefix), + hook: hook, + safe: false !== prefix.safe + } + prehooks.push(h) + return remover(prehooks, h) + }, + posthooks: posthooks, + prehooks: prehooks + } + + //POST HOOKS + + function each (e) { + if(e && e.type) { + posthooks.forEach(function (h) { + if(h.test(e.key)) h.hook(e) + }) + } + } + + db.on('put', function (key, val) { + each({type: 'put', key: key, value: val}) + }) + db.on('del', function (key, val) { + each({type: 'del', key: key, value: val}) + }) + db.on('batch', function onBatch (ary) { + ary.forEach(each) + }) + + //PRE HOOKS + + var put = db.put + var del = db.del + var batch = db.batch + + function callHooks (isBatch, b, opts, cb) { + try { + b.forEach(function hook(e, i) { + prehooks.forEach(function (h) { + if(h.test(String(e.key))) { + //optimize this? + //maybe faster to not create a new object each time? + //have one object and expose scope to it? + var context = { + add: function (ch, db) { + if(typeof ch === 'undefined') { + return this + } + if(ch === false) + return delete b[i] + var prefix = ( + getPrefix(ch.prefix) || + getPrefix(db) || + h.prefix || '' + ) + //don't leave a circular json object there incase using multilevel. + if(prefix) ch.prefix = prefix + ch.key = prefix + ch.key + if(h.safe && h.test(String(ch.key))) { + //this usually means a stack overflow. + throw new Error('prehook cannot insert into own range') + } + var ke = ch.keyEncoding || getKeyEncoding(ch.prefix) + var ve = ch.valueEncoding || getValueEncoding(ch.prefix) + if(ke) ch.keyEncoding = ke + if(ve) ch.valueEncoding = ve + + b.push(ch) + hook(ch, b.length - 1) + return this + }, + put: function (ch, db) { + if('object' === typeof ch) ch.type = 'put' + return this.add(ch, db) + }, + del: function (ch, db) { + if('object' === typeof ch) ch.type = 'del' + return this.add(ch, db) + }, + veto: function () { + return this.add(false) + } + } + h.hook.call(context, e, context.add, b) + } + }) + }) + } catch (err) { + return (cb || opts)(err) + } + b = b.filter(function (e) { + return e && e.type //filter out empty items + }) + + if(b.length == 1 && !isBatch) { + var change = b[0] + return change.type == 'put' + ? put.call(db, change.key, change.value, opts, cb) + : del.call(db, change.key, opts, cb) + } + return batch.call(db, b, opts, cb) + } + + db.put = function (key, value, opts, cb ) { + var batch = [{key: key, value: value, type: 'put'}] + return callHooks(false, batch, opts, cb) + } + + db.del = function (key, opts, cb) { + var batch = [{key: key, type: 'del'}] + return callHooks(false, batch, opts, cb) + } + + db.batch = function (batch, opts, cb) { + return callHooks(true, batch, opts, cb) + } +} + +},{"string-range":65}],65:[function(_dereq_,module,exports){ + +//force to a valid range +var range = exports.range = function (obj) { + return null == obj ? {} : 'string' === typeof range ? { + min: range, max: range + '\xff' + } : obj +} + +//turn into a sub range. +var prefix = exports.prefix = function (range, within, term) { + range = exports.range(range) + var _range = {} + term = term || '\xff' + if(range instanceof RegExp || 'function' == typeof range) { + _range.min = within + _range.max = within + term, + _range.inner = function (k) { + var j = k.substring(within.length) + if(range.test) + return range.test(j) + return range(j) + } + } + else if('object' === typeof range) { + _range.min = within + (range.min || range.start || '') + _range.max = within + (range.max || range.end || (term || '~')) + _range.reverse = !!range.reverse + } + return _range +} + +//return a function that checks a range +var checker = exports.checker = function (range) { + if(!range) range = {} + + if ('string' === typeof range) + return function (key) { + return key.indexOf(range) == 0 + } + else if(range instanceof RegExp) + return function (key) { + return range.test(key) + } + else if('object' === typeof range) + return function (key) { + var min = range.min || range.start + var max = range.max || range.end + + // fixes keys passed as ints from sublevels + key = String(key) + + return ( + !min || key >= min + ) && ( + !max || key <= max + ) && ( + !range.inner || ( + range.inner.test + ? range.inner.test(key) + : range.inner(key) + ) + ) + } + else if('function' === typeof range) + return range +} +//check if a key is within a range. +var satifies = exports.satisfies = function (key, range) { + return checker(range)(key) +} + + + +},{}],66:[function(_dereq_,module,exports){ +module.exports=_dereq_(54) +},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/has-keys.js":54}],67:[function(_dereq_,module,exports){ +arguments[4][55][0].apply(exports,arguments) +},{"./has-keys":66,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/index.js":55,"object-keys":68}],68:[function(_dereq_,module,exports){ +arguments[4][57][0].apply(exports,arguments) +},{"./shim":71,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/index.js":57}],69:[function(_dereq_,module,exports){ + +var hasOwn = Object.prototype.hasOwnProperty; +var toString = Object.prototype.toString; + +module.exports = function forEach (obj, fn, ctx) { + if (toString.call(fn) !== '[object Function]') { + throw new TypeError('iterator must be a function'); + } + var l = obj.length; + if (l === +l) { + for (var i = 0; i < l; i++) { + fn.call(ctx, obj[i], i, obj); + } + } else { + for (var k in obj) { + if (hasOwn.call(obj, k)) { + fn.call(ctx, obj[k], k, obj); + } + } + } +}; + + +},{}],70:[function(_dereq_,module,exports){ + +/**! + * is + * the definitive JavaScript type testing library + * + * @copyright 2013 Enrico Marino + * @license MIT + */ + +var objProto = Object.prototype; +var owns = objProto.hasOwnProperty; +var toString = objProto.toString; +var isActualNaN = function (value) { + return value !== value; +}; +var NON_HOST_TYPES = { + "boolean": 1, + "number": 1, + "string": 1, + "undefined": 1 +}; + +/** + * Expose `is` + */ + +var is = module.exports = {}; + +/** + * Test general. + */ + +/** + * is.type + * Test if `value` is a type of `type`. + * + * @param {Mixed} value value to test + * @param {String} type type + * @return {Boolean} true if `value` is a type of `type`, false otherwise + * @api public + */ + +is.a = +is.type = function (value, type) { + return typeof value === type; +}; + +/** + * is.defined + * Test if `value` is defined. + * + * @param {Mixed} value value to test + * @return {Boolean} true if 'value' is defined, false otherwise + * @api public + */ + +is.defined = function (value) { + return value !== undefined; +}; + +/** + * is.empty + * Test if `value` is empty. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is empty, false otherwise + * @api public + */ + +is.empty = function (value) { + var type = toString.call(value); + var key; + + if ('[object Array]' === type || '[object Arguments]' === type) { + return value.length === 0; + } + + if ('[object Object]' === type) { + for (key in value) if (owns.call(value, key)) return false; + return true; + } + + if ('[object String]' === type) { + return '' === value; + } + + return false; +}; + +/** + * is.equal + * Test if `value` is equal to `other`. + * + * @param {Mixed} value value to test + * @param {Mixed} other value to compare with + * @return {Boolean} true if `value` is equal to `other`, false otherwise + */ + +is.equal = function (value, other) { + var type = toString.call(value) + var key; + + if (type !== toString.call(other)) { + return false; + } + + if ('[object Object]' === type) { + for (key in value) { + if (!is.equal(value[key], other[key])) { + return false; + } + } + return true; + } + + if ('[object Array]' === type) { + key = value.length; + if (key !== other.length) { + return false; + } + while (--key) { + if (!is.equal(value[key], other[key])) { + return false; + } + } + return true; + } + + if ('[object Function]' === type) { + return value.prototype === other.prototype; + } + + if ('[object Date]' === type) { + return value.getTime() === other.getTime(); + } + + return value === other; +}; + +/** + * is.hosted + * Test if `value` is hosted by `host`. + * + * @param {Mixed} value to test + * @param {Mixed} host host to test with + * @return {Boolean} true if `value` is hosted by `host`, false otherwise + * @api public + */ + +is.hosted = function (value, host) { + var type = typeof host[value]; + return type === 'object' ? !!host[value] : !NON_HOST_TYPES[type]; +}; + +/** + * is.instance + * Test if `value` is an instance of `constructor`. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is an instance of `constructor` + * @api public + */ + +is.instance = is['instanceof'] = function (value, constructor) { + return value instanceof constructor; +}; + +/** + * is.null + * Test if `value` is null. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is null, false otherwise + * @api public + */ + +is['null'] = function (value) { + return value === null; +}; + +/** + * is.undefined + * Test if `value` is undefined. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is undefined, false otherwise + * @api public + */ + +is.undefined = function (value) { + return value === undefined; +}; + +/** + * Test arguments. + */ + +/** + * is.arguments + * Test if `value` is an arguments object. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is an arguments object, false otherwise + * @api public + */ + +is.arguments = function (value) { + var isStandardArguments = '[object Arguments]' === toString.call(value); + var isOldArguments = !is.array(value) && is.arraylike(value) && is.object(value) && is.fn(value.callee); + return isStandardArguments || isOldArguments; +}; + +/** + * Test array. + */ + +/** + * is.array + * Test if 'value' is an array. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is an array, false otherwise + * @api public + */ + +is.array = function (value) { + return '[object Array]' === toString.call(value); +}; + +/** + * is.arguments.empty + * Test if `value` is an empty arguments object. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is an empty arguments object, false otherwise + * @api public + */ +is.arguments.empty = function (value) { + return is.arguments(value) && value.length === 0; +}; + +/** + * is.array.empty + * Test if `value` is an empty array. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is an empty array, false otherwise + * @api public + */ +is.array.empty = function (value) { + return is.array(value) && value.length === 0; +}; + +/** + * is.arraylike + * Test if `value` is an arraylike object. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is an arguments object, false otherwise + * @api public + */ + +is.arraylike = function (value) { + return !!value && !is.boolean(value) + && owns.call(value, 'length') + && isFinite(value.length) + && is.number(value.length) + && value.length >= 0; +}; + +/** + * Test boolean. + */ + +/** + * is.boolean + * Test if `value` is a boolean. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is a boolean, false otherwise + * @api public + */ + +is.boolean = function (value) { + return '[object Boolean]' === toString.call(value); +}; + +/** + * is.false + * Test if `value` is false. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is false, false otherwise + * @api public + */ + +is['false'] = function (value) { + return is.boolean(value) && (value === false || value.valueOf() === false); +}; + +/** + * is.true + * Test if `value` is true. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is true, false otherwise + * @api public + */ + +is['true'] = function (value) { + return is.boolean(value) && (value === true || value.valueOf() === true); +}; + +/** + * Test date. + */ + +/** + * is.date + * Test if `value` is a date. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is a date, false otherwise + * @api public + */ + +is.date = function (value) { + return '[object Date]' === toString.call(value); +}; + +/** + * Test element. + */ + +/** + * is.element + * Test if `value` is an html element. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is an HTML Element, false otherwise + * @api public + */ + +is.element = function (value) { + return value !== undefined + && typeof HTMLElement !== 'undefined' + && value instanceof HTMLElement + && value.nodeType === 1; +}; + +/** + * Test error. + */ + +/** + * is.error + * Test if `value` is an error object. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is an error object, false otherwise + * @api public + */ + +is.error = function (value) { + return '[object Error]' === toString.call(value); +}; + +/** + * Test function. + */ + +/** + * is.fn / is.function (deprecated) + * Test if `value` is a function. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is a function, false otherwise + * @api public + */ + +is.fn = is['function'] = function (value) { + var isAlert = typeof window !== 'undefined' && value === window.alert; + return isAlert || '[object Function]' === toString.call(value); +}; + +/** + * Test number. + */ + +/** + * is.number + * Test if `value` is a number. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is a number, false otherwise + * @api public + */ + +is.number = function (value) { + return '[object Number]' === toString.call(value); +}; + +/** + * is.infinite + * Test if `value` is positive or negative infinity. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is positive or negative Infinity, false otherwise + * @api public + */ +is.infinite = function (value) { + return value === Infinity || value === -Infinity; +}; + +/** + * is.decimal + * Test if `value` is a decimal number. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is a decimal number, false otherwise + * @api public + */ + +is.decimal = function (value) { + return is.number(value) && !isActualNaN(value) && !is.infinite(value) && value % 1 !== 0; +}; + +/** + * is.divisibleBy + * Test if `value` is divisible by `n`. + * + * @param {Number} value value to test + * @param {Number} n dividend + * @return {Boolean} true if `value` is divisible by `n`, false otherwise + * @api public + */ + +is.divisibleBy = function (value, n) { + var isDividendInfinite = is.infinite(value); + var isDivisorInfinite = is.infinite(n); + var isNonZeroNumber = is.number(value) && !isActualNaN(value) && is.number(n) && !isActualNaN(n) && n !== 0; + return isDividendInfinite || isDivisorInfinite || (isNonZeroNumber && value % n === 0); +}; + +/** + * is.int + * Test if `value` is an integer. + * + * @param value to test + * @return {Boolean} true if `value` is an integer, false otherwise + * @api public + */ + +is.int = function (value) { + return is.number(value) && !isActualNaN(value) && value % 1 === 0; +}; + +/** + * is.maximum + * Test if `value` is greater than 'others' values. + * + * @param {Number} value value to test + * @param {Array} others values to compare with + * @return {Boolean} true if `value` is greater than `others` values + * @api public + */ + +is.maximum = function (value, others) { + if (isActualNaN(value)) { + throw new TypeError('NaN is not a valid value'); + } else if (!is.arraylike(others)) { + throw new TypeError('second argument must be array-like'); + } + var len = others.length; + + while (--len >= 0) { + if (value < others[len]) { + return false; + } + } + + return true; +}; + +/** + * is.minimum + * Test if `value` is less than `others` values. + * + * @param {Number} value value to test + * @param {Array} others values to compare with + * @return {Boolean} true if `value` is less than `others` values + * @api public + */ + +is.minimum = function (value, others) { + if (isActualNaN(value)) { + throw new TypeError('NaN is not a valid value'); + } else if (!is.arraylike(others)) { + throw new TypeError('second argument must be array-like'); + } + var len = others.length; + + while (--len >= 0) { + if (value > others[len]) { + return false; + } + } + + return true; +}; + +/** + * is.nan + * Test if `value` is not a number. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is not a number, false otherwise + * @api public + */ + +is.nan = function (value) { + return !is.number(value) || value !== value; +}; + +/** + * is.even + * Test if `value` is an even number. + * + * @param {Number} value value to test + * @return {Boolean} true if `value` is an even number, false otherwise + * @api public + */ + +is.even = function (value) { + return is.infinite(value) || (is.number(value) && value === value && value % 2 === 0); +}; + +/** + * is.odd + * Test if `value` is an odd number. + * + * @param {Number} value value to test + * @return {Boolean} true if `value` is an odd number, false otherwise + * @api public + */ + +is.odd = function (value) { + return is.infinite(value) || (is.number(value) && value === value && value % 2 !== 0); +}; + +/** + * is.ge + * Test if `value` is greater than or equal to `other`. + * + * @param {Number} value value to test + * @param {Number} other value to compare with + * @return {Boolean} + * @api public + */ + +is.ge = function (value, other) { + if (isActualNaN(value) || isActualNaN(other)) { + throw new TypeError('NaN is not a valid value'); + } + return !is.infinite(value) && !is.infinite(other) && value >= other; +}; + +/** + * is.gt + * Test if `value` is greater than `other`. + * + * @param {Number} value value to test + * @param {Number} other value to compare with + * @return {Boolean} + * @api public + */ + +is.gt = function (value, other) { + if (isActualNaN(value) || isActualNaN(other)) { + throw new TypeError('NaN is not a valid value'); + } + return !is.infinite(value) && !is.infinite(other) && value > other; +}; + +/** + * is.le + * Test if `value` is less than or equal to `other`. + * + * @param {Number} value value to test + * @param {Number} other value to compare with + * @return {Boolean} if 'value' is less than or equal to 'other' + * @api public + */ + +is.le = function (value, other) { + if (isActualNaN(value) || isActualNaN(other)) { + throw new TypeError('NaN is not a valid value'); + } + return !is.infinite(value) && !is.infinite(other) && value <= other; +}; + +/** + * is.lt + * Test if `value` is less than `other`. + * + * @param {Number} value value to test + * @param {Number} other value to compare with + * @return {Boolean} if `value` is less than `other` + * @api public + */ + +is.lt = function (value, other) { + if (isActualNaN(value) || isActualNaN(other)) { + throw new TypeError('NaN is not a valid value'); + } + return !is.infinite(value) && !is.infinite(other) && value < other; +}; + +/** + * is.within + * Test if `value` is within `start` and `finish`. + * + * @param {Number} value value to test + * @param {Number} start lower bound + * @param {Number} finish upper bound + * @return {Boolean} true if 'value' is is within 'start' and 'finish' + * @api public + */ +is.within = function (value, start, finish) { + if (isActualNaN(value) || isActualNaN(start) || isActualNaN(finish)) { + throw new TypeError('NaN is not a valid value'); + } else if (!is.number(value) || !is.number(start) || !is.number(finish)) { + throw new TypeError('all arguments must be numbers'); + } + var isAnyInfinite = is.infinite(value) || is.infinite(start) || is.infinite(finish); + return isAnyInfinite || (value >= start && value <= finish); +}; + +/** + * Test object. + */ + +/** + * is.object + * Test if `value` is an object. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is an object, false otherwise + * @api public + */ + +is.object = function (value) { + return value && '[object Object]' === toString.call(value); +}; + +/** + * is.hash + * Test if `value` is a hash - a plain object literal. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is a hash, false otherwise + * @api public + */ + +is.hash = function (value) { + return is.object(value) && value.constructor === Object && !value.nodeType && !value.setInterval; +}; + +/** + * Test regexp. + */ + +/** + * is.regexp + * Test if `value` is a regular expression. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is a regexp, false otherwise + * @api public + */ + +is.regexp = function (value) { + return '[object RegExp]' === toString.call(value); +}; + +/** + * Test string. + */ + +/** + * is.string + * Test if `value` is a string. + * + * @param {Mixed} value value to test + * @return {Boolean} true if 'value' is a string, false otherwise + * @api public + */ + +is.string = function (value) { + return '[object String]' === toString.call(value); +}; + + +},{}],71:[function(_dereq_,module,exports){ +(function () { + "use strict"; + + // modified from https://github.com/kriskowal/es5-shim + var has = Object.prototype.hasOwnProperty, + is = _dereq_('is'), + forEach = _dereq_('foreach'), + hasDontEnumBug = !({'toString': null}).propertyIsEnumerable('toString'), + dontEnums = [ + "toString", + "toLocaleString", + "valueOf", + "hasOwnProperty", + "isPrototypeOf", + "propertyIsEnumerable", + "constructor" + ], + keysShim; + + keysShim = function keys(object) { + if (!is.object(object) && !is.array(object)) { + throw new TypeError("Object.keys called on a non-object"); + } + + var name, theKeys = []; + for (name in object) { + if (has.call(object, name)) { + theKeys.push(name); + } + } + + if (hasDontEnumBug) { + forEach(dontEnums, function (dontEnum) { + if (has.call(object, dontEnum)) { + theKeys.push(dontEnum); + } + }); + } + return theKeys; + }; + + module.exports = keysShim; +}()); + + +},{"foreach":69,"is":70}],72:[function(_dereq_,module,exports){ +var EventEmitter = _dereq_('events').EventEmitter +var inherits = _dereq_('util').inherits +var ranges = _dereq_('string-range') +var fixRange = _dereq_('level-fix-range') +var xtend = _dereq_('xtend') +var Batch = _dereq_('./batch') + +inherits(SubDB, EventEmitter) + +function SubDB (db, prefix, options) { + if('string' === typeof options) { + console.error('db.sublevel(name, seperator<string>) is depreciated') + console.error('use db.sublevel(name, {sep: separator})) if you must') + options = {sep: options} + } + if(!(this instanceof SubDB)) return new SubDB(db, prefix, options) + if(!db) throw new Error('must provide db') + if(!prefix) throw new Error('must provide prefix') + + options = options || {} + options.sep = options.sep || '\xff' + + this._parent = db + this._options = options + this.options = options + this._prefix = prefix + this._root = root(this) + db.sublevels[prefix] = this + this.sublevels = {} + this.methods = {} + var self = this + this.hooks = { + pre: function () { + return self.pre.apply(self, arguments) + }, + post: function () { + return self.post.apply(self, arguments) + } + } +} + +var SDB = SubDB.prototype + +SDB._key = function (key) { + var sep = this._options.sep + return sep + + this._prefix + + sep + + key +} + +SDB._getOptsAndCb = function (opts, cb) { + if (typeof opts == 'function') { + cb = opts + opts = {} + } + return { opts: xtend(opts, this._options), cb: cb } +} + +SDB.sublevel = function (prefix, options) { + if(this.sublevels[prefix]) + return this.sublevels[prefix] + return new SubDB(this, prefix, options || this._options) +} + +SDB.put = function (key, value, opts, cb) { + var res = this._getOptsAndCb(opts, cb) + this._root.put(this.prefix(key), value, res.opts, res.cb) +} + +SDB.get = function (key, opts, cb) { + var res = this._getOptsAndCb(opts, cb) + this._root.get(this.prefix(key), res.opts, res.cb) +} + +SDB.del = function (key, opts, cb) { + var res = this._getOptsAndCb(opts, cb) + this._root.del(this.prefix(key), res.opts, res.cb) +} + +SDB.batch = function (changes, opts, cb) { + if(!Array.isArray(changes)) + return new Batch(this) + var self = this, + res = this._getOptsAndCb(opts, cb) + changes.forEach(function (ch) { + + //OH YEAH, WE NEED TO VALIDATE THAT UPDATING THIS KEY/PREFIX IS ALLOWED + if('string' === typeof ch.prefix) + ch.key = ch.prefix + ch.key + else + ch.key = (ch.prefix || self).prefix(ch.key) + + if(ch.prefix) ch.prefix = null + }) + this._root.batch(changes, res.opts, res.cb) +} + +SDB._getKeyEncoding = function () { + if(this.options.keyEncoding) + return this.options.keyEncoding + if(this._parent && this._parent._getKeyEncoding) + return this._parent._getKeyEncoding() +} + +SDB._getValueEncoding = function () { + if(this.options.valueEncoding) + return this.options.valueEncoding + if(this._parent && this._parent._getValueEncoding) + return this._parent._getValueEncoding() +} + +SDB.prefix = function (key) { + var sep = this._options.sep + return this._parent.prefix() + sep + this._prefix + sep + (key || '') +} + +SDB.keyStream = +SDB.createKeyStream = function (opts) { + opts = opts || {} + opts.keys = true + opts.values = false + return this.createReadStream(opts) +} + +SDB.valueStream = +SDB.createValueStream = function (opts) { + opts = opts || {} + opts.keys = false + opts.values = true + opts.keys = false + return this.createReadStream(opts) +} + +function selectivelyMerge(_opts, opts) { + [ 'valueEncoding' + , 'encoding' + , 'keyEncoding' + , 'reverse' + , 'values' + , 'keys' + , 'limit' + , 'fillCache' + ] + .forEach(function (k) { + if (opts.hasOwnProperty(k)) _opts[k] = opts[k] + }) +} + +SDB.readStream = +SDB.createReadStream = function (opts) { + opts = opts || {} + var r = root(this) + var p = this.prefix() + + var _opts = ranges.prefix(opts, p) + selectivelyMerge(_opts, xtend(opts, this._options)) + + var s = r.createReadStream(_opts) + + if(_opts.values === false) { + var read = s.read + if (read) { + s.read = function (size) { + var val = read.call(this, size) + if (val) val = val.substring(p.length) + return val + } + } else { + var emit = s.emit + s.emit = function (event, val) { + if(event === 'data') { + emit.call(this, 'data', val.substring(p.length)) + } else + emit.call(this, event, val) + } + } + return s + } else if(_opts.keys === false) + return s + else { + var read = s.read + if (read) { + s.read = function (size) { + var d = read.call(this, size) + if (d) d.key = d.key.substring(p.length) + return d + } + } else { + s.on('data', function (d) { + //mutate the prefix! + //this doesn't work for createKeyStream admittedly. + d.key = d.key.substring(p.length) + }) + } + return s + } +} + + +SDB.writeStream = +SDB.createWriteStream = function () { + var r = root(this) + var p = this.prefix() + var ws = r.createWriteStream.apply(r, arguments) + var write = ws.write + + var encoding = this._options.encoding + var valueEncoding = this._options.valueEncoding + var keyEncoding = this._options.keyEncoding + + // slight optimization, if no encoding was specified at all, + // which will be the case most times, make write not check at all + var nocheck = !encoding && !valueEncoding && !keyEncoding + + ws.write = nocheck + ? function (data) { + data.key = p + data.key + return write.call(ws, data) + } + : function (data) { + data.key = p + data.key + + // not merging all options here since this happens on every write and things could get slowed down + // at this point we only consider encoding important to propagate + if (encoding && typeof data.encoding === 'undefined') + data.encoding = encoding + if (valueEncoding && typeof data.valueEncoding === 'undefined') + data.valueEncoding = valueEncoding + if (keyEncoding && typeof data.keyEncoding === 'undefined') + data.keyEncoding = keyEncoding + + return write.call(ws, data) + } + return ws +} + +SDB.approximateSize = function () { + var r = root(db) + return r.approximateSize.apply(r, arguments) +} + +function root(db) { + if(!db._parent) return db + return root(db._parent) +} + +SDB.pre = function (range, hook) { + if(!hook) hook = range, range = null + range = ranges.prefix(range, this.prefix(), this._options.sep) + var r = root(this._parent) + var p = this.prefix() + return r.hooks.pre(fixRange(range), function (ch, add, batch) { + hook({ + key: ch.key.substring(p.length), + value: ch.value, + type: ch.type + }, function (ch, _p) { + //maybe remove the second add arg now + //that op can have prefix? + add(ch, ch.prefix ? _p : (_p || p)) + }, batch) + }) +} + +SDB.post = function (range, hook) { + if(!hook) hook = range, range = null + var r = root(this._parent) + var p = this.prefix() + range = ranges.prefix(range, p, this._options.sep) + return r.hooks.post(fixRange(range), function (data) { + hook({key: data.key.substring(p.length), value: data.value, type: data.type}) + }) +} + +var exports = module.exports = SubDB + + +},{"./batch":60,"events":21,"level-fix-range":62,"string-range":65,"util":39,"xtend":67}],73:[function(_dereq_,module,exports){ +/* Copyright (c) 2012-2014 LevelUP contributors + * See list at <https://github.com/rvagg/node-levelup#contributing> + * MIT License + * <https://github.com/rvagg/node-levelup/blob/master/LICENSE.md> + */ + +var util = _dereq_('./util') + , WriteError = _dereq_('./errors').WriteError + + , getOptions = util.getOptions + , dispatchError = util.dispatchError + +function Batch (levelup) { + this._levelup = levelup + this.batch = levelup.db.batch() + this.ops = [] +} + +Batch.prototype.put = function (key_, value_, options) { + options = getOptions(this._levelup, options) + + var key = util.encodeKey(key_, options) + , value = util.encodeValue(value_, options) + + try { + this.batch.put(key, value) + } catch (e) { + throw new WriteError(e) + } + this.ops.push({ type : 'put', key : key, value : value }) + + return this +} + +Batch.prototype.del = function (key_, options) { + options = getOptions(this._levelup, options) + + var key = util.encodeKey(key_, options) + + try { + this.batch.del(key) + } catch (err) { + throw new WriteError(err) + } + this.ops.push({ type : 'del', key : key }) + + return this +} + +Batch.prototype.clear = function () { + try { + this.batch.clear() + } catch (err) { + throw new WriteError(err) + } + + this.ops = [] + return this +} + +Batch.prototype.write = function (callback) { + var levelup = this._levelup + , ops = this.ops + + try { + this.batch.write(function (err) { + if (err) + return dispatchError(levelup, new WriteError(err), callback) + levelup.emit('batch', ops) + if (callback) + callback() + }) + } catch (err) { + throw new WriteError(err) + } +} + +module.exports = Batch + +},{"./errors":74,"./util":77}],74:[function(_dereq_,module,exports){ +/* Copyright (c) 2012-2014 LevelUP contributors + * See list at <https://github.com/rvagg/node-levelup#contributing> + * MIT License + * <https://github.com/rvagg/node-levelup/blob/master/LICENSE.md> + */ + +var createError = _dereq_('errno').create + , LevelUPError = createError('LevelUPError') + , NotFoundError = createError('NotFoundError', LevelUPError) + +NotFoundError.prototype.notFound = true +NotFoundError.prototype.status = 404 + +module.exports = { + LevelUPError : LevelUPError + , InitializationError : createError('InitializationError', LevelUPError) + , OpenError : createError('OpenError', LevelUPError) + , ReadError : createError('ReadError', LevelUPError) + , WriteError : createError('WriteError', LevelUPError) + , NotFoundError : NotFoundError + , EncodingError : createError('EncodingError', LevelUPError) +} + +},{"errno":85}],75:[function(_dereq_,module,exports){ +(function (process){ +/* Copyright (c) 2012-2014 LevelUP contributors + * See list at <https://github.com/rvagg/node-levelup#contributing> + * MIT License + * <https://github.com/rvagg/node-levelup/blob/master/LICENSE.md> + */ + +var EventEmitter = _dereq_('events').EventEmitter + , inherits = _dereq_('util').inherits + , extend = _dereq_('xtend') + , prr = _dereq_('prr') + , DeferredLevelDOWN = _dereq_('deferred-leveldown') + + , WriteError = _dereq_('./errors').WriteError + , ReadError = _dereq_('./errors').ReadError + , NotFoundError = _dereq_('./errors').NotFoundError + , OpenError = _dereq_('./errors').OpenError + , EncodingError = _dereq_('./errors').EncodingError + , InitializationError = _dereq_('./errors').InitializationError + + , ReadStream = _dereq_('./read-stream') + , WriteStream = _dereq_('./write-stream') + , util = _dereq_('./util') + , Batch = _dereq_('./batch') + + , getOptions = util.getOptions + , defaultOptions = util.defaultOptions + , getLevelDOWN = util.getLevelDOWN + , dispatchError = util.dispatchError + +function getCallback (options, callback) { + return typeof options == 'function' ? options : callback +} + +// Possible LevelUP#_status values: +// - 'new' - newly created, not opened or closed +// - 'opening' - waiting for the database to be opened, post open() +// - 'open' - successfully opened the database, available for use +// - 'closing' - waiting for the database to be closed, post close() +// - 'closed' - database has been successfully closed, should not be +// used except for another open() operation + +function LevelUP (location, options, callback) { + if (!(this instanceof LevelUP)) + return new LevelUP(location, options, callback) + + var error + + EventEmitter.call(this) + this.setMaxListeners(Infinity) + + if (typeof location == 'function') { + options = typeof options == 'object' ? options : {} + options.db = location + location = null + } else if (typeof location == 'object' && typeof location.db == 'function') { + options = location + location = null + } + + if (typeof options == 'function') { + callback = options + options = {} + } + + if ((!options || typeof options.db != 'function') && typeof location != 'string') { + error = new InitializationError( + 'Must provide a location for the database') + if (callback) { + return process.nextTick(function () { + callback(error) + }) + } + throw error + } + + options = getOptions(this, options) + this.options = extend(defaultOptions, options) + this._status = 'new' + // set this.location as enumerable but not configurable or writable + prr(this, 'location', location, 'e') + + this.open(callback) +} + +inherits(LevelUP, EventEmitter) + +LevelUP.prototype.open = function (callback) { + var self = this + , dbFactory + , db + + if (this.isOpen()) { + if (callback) + process.nextTick(function () { callback(null, self) }) + return this + } + + if (this._isOpening()) { + return callback && this.once( + 'open' + , function () { callback(null, self) } + ) + } + + this.emit('opening') + + this._status = 'opening' + this.db = new DeferredLevelDOWN(this.location) + dbFactory = this.options.db || getLevelDOWN() + db = dbFactory(this.location) + + db.open(this.options, function (err) { + if (err) { + return dispatchError(self, new OpenError(err), callback) + } else { + self.db.setDb(db) + self.db = db + self._status = 'open' + if (callback) + callback(null, self) + self.emit('open') + self.emit('ready') + } + }) +} + +LevelUP.prototype.close = function (callback) { + var self = this + + if (this.isOpen()) { + this._status = 'closing' + this.db.close(function () { + self._status = 'closed' + self.emit('closed') + if (callback) + callback.apply(null, arguments) + }) + this.emit('closing') + this.db = null + } else if (this._status == 'closed' && callback) { + return process.nextTick(callback) + } else if (this._status == 'closing' && callback) { + this.once('closed', callback) + } else if (this._isOpening()) { + this.once('open', function () { + self.close(callback) + }) + } +} + +LevelUP.prototype.isOpen = function () { + return this._status == 'open' +} + +LevelUP.prototype._isOpening = function () { + return this._status == 'opening' +} + +LevelUP.prototype.isClosed = function () { + return (/^clos/).test(this._status) +} + +LevelUP.prototype.get = function (key_, options, callback) { + var self = this + , key + + callback = getCallback(options, callback) + + if (typeof callback != 'function') { + return dispatchError( + this + , new ReadError('get() requires key and callback arguments') + ) + } + + if (!this._isOpening() && !this.isOpen()) { + return dispatchError( + this + , new ReadError('Database is not open') + , callback + ) + } + + options = util.getOptions(this, options) + key = util.encodeKey(key_, options) + + options.asBuffer = util.isValueAsBuffer(options) + + this.db.get(key, options, function (err, value) { + if (err) { + if ((/notfound/i).test(err)) { + err = new NotFoundError( + 'Key not found in database [' + key_ + ']', err) + } else { + err = new ReadError(err) + } + return dispatchError(self, err, callback) + } + if (callback) { + try { + value = util.decodeValue(value, options) + } catch (e) { + return callback(new EncodingError(e)) + } + callback(null, value) + } + }) +} + +LevelUP.prototype.put = function (key_, value_, options, callback) { + var self = this + , key + , value + + callback = getCallback(options, callback) + + if (key_ === null || key_ === undefined + || value_ === null || value_ === undefined) { + return dispatchError( + this + , new WriteError('put() requires key and value arguments') + , callback + ) + } + + if (!this._isOpening() && !this.isOpen()) { + return dispatchError( + this + , new WriteError('Database is not open') + , callback + ) + } + + options = getOptions(this, options) + key = util.encodeKey(key_, options) + value = util.encodeValue(value_, options) + + this.db.put(key, value, options, function (err) { + if (err) { + return dispatchError(self, new WriteError(err), callback) + } else { + self.emit('put', key_, value_) + if (callback) + callback() + } + }) +} + +LevelUP.prototype.del = function (key_, options, callback) { + var self = this + , key + + callback = getCallback(options, callback) + + if (key_ === null || key_ === undefined) { + return dispatchError( + this + , new WriteError('del() requires a key argument') + , callback + ) + } + + if (!this._isOpening() && !this.isOpen()) { + return dispatchError( + this + , new WriteError('Database is not open') + , callback + ) + } + + options = getOptions(this, options) + key = util.encodeKey(key_, options) + + this.db.del(key, options, function (err) { + if (err) { + return dispatchError(self, new WriteError(err), callback) + } else { + self.emit('del', key_) + if (callback) + callback() + } + }) +} + +LevelUP.prototype.batch = function (arr_, options, callback) { + var self = this + , keyEnc + , valueEnc + , arr + + if (!arguments.length) + return new Batch(this) + + callback = getCallback(options, callback) + + if (!Array.isArray(arr_)) { + return dispatchError( + this + , new WriteError('batch() requires an array argument') + , callback + ) + } + + if (!this._isOpening() && !this.isOpen()) { + return dispatchError( + this + , new WriteError('Database is not open') + , callback + ) + } + + options = getOptions(this, options) + keyEnc = options.keyEncoding + valueEnc = options.valueEncoding + + arr = arr_.map(function (e) { + if (e.type === undefined || e.key === undefined) + return {} + + // inherit encoding + var kEnc = e.keyEncoding || keyEnc + , vEnc = e.valueEncoding || e.encoding || valueEnc + , o + + // If we're not dealing with plain utf8 strings or plain + // Buffers then we have to do some work on the array to + // encode the keys and/or values. This includes JSON types. + + if (kEnc != 'utf8' && kEnc != 'binary' + || vEnc != 'utf8' && vEnc != 'binary') { + o = { + type: e.type + , key: util.encodeKey(e.key, options, e) + } + + if (e.value !== undefined) + o.value = util.encodeValue(e.value, options, e) + + return o + } else { + return e + } + }) + + this.db.batch(arr, options, function (err) { + if (err) { + return dispatchError(self, new WriteError(err), callback) + } else { + self.emit('batch', arr_) + if (callback) + callback() + } + }) +} + +// DEPRECATED: prefer accessing LevelDOWN for this: db.db.approximateSize() +LevelUP.prototype.approximateSize = function (start_, end_, callback) { + var self = this + , start + , end + + if (start_ === null || start_ === undefined + || end_ === null || end_ === undefined + || typeof callback != 'function') { + return dispatchError( + this + , new ReadError('approximateSize() requires start, end and callback arguments') + , callback + ) + } + + start = util.encodeKey(start_, this.options) + end = util.encodeKey(end_, this.options) + + if (!this._isOpening() && !this.isOpen()) { + return dispatchError( + this + , new WriteError('Database is not open') + , callback + ) + } + + this.db.approximateSize(start, end, function (err, size) { + if (err) { + return dispatchError(self, new OpenError(err), callback) + } else if (callback) { + callback(null, size) + } + }) +} + +LevelUP.prototype.readStream = +LevelUP.prototype.createReadStream = function (options) { + var self = this + options = extend(this.options, options) + return new ReadStream( + options + , this + , function (options) { + return self.db.iterator(options) + } + ) +} + +LevelUP.prototype.keyStream = +LevelUP.prototype.createKeyStream = function (options) { + return this.createReadStream(extend(options, { keys: true, values: false })) +} + +LevelUP.prototype.valueStream = +LevelUP.prototype.createValueStream = function (options) { + return this.createReadStream(extend(options, { keys: false, values: true })) +} + +LevelUP.prototype.writeStream = +LevelUP.prototype.createWriteStream = function (options) { + return new WriteStream(extend(options), this) +} + +LevelUP.prototype.toString = function () { + return 'LevelUP' +} + +function utilStatic (name) { + return function (location, callback) { + getLevelDOWN()[name](location, callback || function () {}) + } +} + +module.exports = LevelUP +module.exports.copy = util.copy +// DEPRECATED: prefer accessing LevelDOWN for this: require('leveldown').destroy() +module.exports.destroy = utilStatic('destroy') +// DEPRECATED: prefer accessing LevelDOWN for this: require('leveldown').repair() +module.exports.repair = utilStatic('repair') + +}).call(this,_dereq_('_process')) +},{"./batch":73,"./errors":74,"./read-stream":76,"./util":77,"./write-stream":78,"_process":24,"deferred-leveldown":80,"events":21,"prr":86,"util":39,"xtend":96}],76:[function(_dereq_,module,exports){ +/* Copyright (c) 2012-2014 LevelUP contributors + * See list at <https://github.com/rvagg/node-levelup#contributing> + * MIT License <https://github.com/rvagg/node-levelup/blob/master/LICENSE.md> + */ + +// NOTE: we are fixed to readable-stream@1.0.x for now +// for pure Streams2 across Node versions +var Readable = _dereq_('readable-stream').Readable + , inherits = _dereq_('util').inherits + , extend = _dereq_('xtend') + , EncodingError = _dereq_('./errors').EncodingError + , util = _dereq_('./util') + + , defaultOptions = { keys: true, values: true } + + , makeKeyValueData = function (key, value) { + return { + key: util.decodeKey(key, this._options) + , value: util.decodeValue(value, this._options) + } + } + , makeKeyData = function (key) { + return util.decodeKey(key, this._options) + } + , makeValueData = function (_, value) { + return util.decodeValue(value, this._options) + } + , makeNoData = function () { return null } + +function ReadStream (options, db, iteratorFactory) { + if (!(this instanceof ReadStream)) + return new ReadStream(options, db, iteratorFactory) + + Readable.call(this, { objectMode: true, highWaterMark: options.highWaterMark }) + + // purely to keep `db` around until we're done so it's not GCed if the user doesn't keep a ref + this._db = db + + options = this._options = extend(defaultOptions, options) + + this._keyEncoding = options.keyEncoding || options.encoding + this._valueEncoding = options.valueEncoding || options.encoding + + if (typeof this._options.start != 'undefined') + this._options.start = util.encodeKey(this._options.start, this._options) + if (typeof this._options.end != 'undefined') + this._options.end = util.encodeKey(this._options.end, this._options) + if (typeof this._options.limit != 'number') + this._options.limit = -1 + + this._options.keyAsBuffer = util.isKeyAsBuffer(this._options) + + this._options.valueAsBuffer = util.isValueAsBuffer(this._options) + + this._makeData = this._options.keys && this._options.values + ? makeKeyValueData : this._options.keys + ? makeKeyData : this._options.values + ? makeValueData : makeNoData + + var self = this + if (!this._db.isOpen()) { + this._db.once('ready', function () { + if (!self._destroyed) { + self._iterator = iteratorFactory(self._options) + } + }) + } else + this._iterator = iteratorFactory(this._options) +} + +inherits(ReadStream, Readable) + +ReadStream.prototype._read = function read () { + var self = this + if (!self._db.isOpen()) { + return self._db.once('ready', function () { read.call(self) }) + } + if (self._destroyed) + return + + self._iterator.next(function(err, key, value) { + if (err || (key === undefined && value === undefined)) { + if (!err && !self._destroyed) + self.push(null) + return self._cleanup(err) + } + + try { + value = self._makeData(key, value) + } catch (e) { + return self._cleanup(new EncodingError(e)) + } + if (!self._destroyed) + self.push(value) + }) +} + +ReadStream.prototype._cleanup = function (err) { + if (this._destroyed) + return + + this._destroyed = true + + var self = this + if (err) + self.emit('error', err) + + if (self._iterator) { + self._iterator.end(function () { + self._iterator = null + self.emit('close') + }) + } else { + self.emit('close') + } +} + +ReadStream.prototype.destroy = function () { + this._cleanup() +} + +ReadStream.prototype.toString = function () { + return 'LevelUP.ReadStream' +} + +module.exports = ReadStream + +},{"./errors":74,"./util":77,"readable-stream":95,"util":39,"xtend":96}],77:[function(_dereq_,module,exports){ +(function (process,Buffer){ +/* Copyright (c) 2012-2014 LevelUP contributors + * See list at <https://github.com/rvagg/node-levelup#contributing> + * MIT License + * <https://github.com/rvagg/node-levelup/blob/master/LICENSE.md> + */ + +var extend = _dereq_('xtend') + , LevelUPError = _dereq_('./errors').LevelUPError + + , encodingNames = [ + 'hex' + , 'utf8' + , 'utf-8' + , 'ascii' + , 'binary' + , 'base64' + , 'ucs2' + , 'ucs-2' + , 'utf16le' + , 'utf-16le' + ] + + , defaultOptions = { + createIfMissing : true + , errorIfExists : false + , keyEncoding : 'utf8' + , valueEncoding : 'utf8' + , compression : true + } + + , leveldown + + , encodings = (function () { + function isBinary (data) { + return data === undefined || data === null || Buffer.isBuffer(data) + } + + var encodings = {} + encodings.utf8 = encodings['utf-8'] = { + encode : function (data) { + return isBinary(data) ? data : String(data) + } + , decode : function (data) { + return data + } + , buffer : false + , type : 'utf8' + } + encodings.json = { + encode : JSON.stringify + , decode : JSON.parse + , buffer : false + , type : 'json' + } + encodingNames.forEach(function (type) { + if (encodings[type]) + return + encodings[type] = { + encode : function (data) { + return isBinary(data) ? data : new Buffer(data, type) + } + , decode : function (buffer) { + return process.browser ? buffer.toString(type) : buffer; + } + , buffer : true + , type : type // useful for debugging purposes + } + }) + return encodings + })() + + , encodingOpts = (function () { + var eo = {} + encodingNames.forEach(function (e) { + eo[e] = { valueEncoding : e } + }) + return eo + }()) + +function copy (srcdb, dstdb, callback) { + srcdb.readStream() + .pipe(dstdb.writeStream()) + .on('close', callback ? callback : function () {}) + .on('error', callback ? callback : function (err) { throw err }) +} + +function getOptions (levelup, options) { + var s = typeof options == 'string' // just an encoding + if (!s && options && options.encoding && !options.valueEncoding) + options.valueEncoding = options.encoding + return extend( + (levelup && levelup.options) || {} + , s ? encodingOpts[options] || encodingOpts[defaultOptions.valueEncoding] + : options + ) +} + +function getLevelDOWN () { + if (leveldown) + return leveldown + + var requiredVersion = _dereq_('../package.json').devDependencies.leveldown + , missingLevelDOWNError = 'Could not locate LevelDOWN, try `npm install leveldown`' + , leveldownVersion + + try { + leveldownVersion = _dereq_('leveldown/package').version + } catch (e) { + throw new LevelUPError(missingLevelDOWNError) + } + + if (!_dereq_('semver').satisfies(leveldownVersion, requiredVersion)) { + throw new LevelUPError( + 'Installed version of LevelDOWN (' + + leveldownVersion + + ') does not match required version (' + + requiredVersion + + ')' + ) + } + + try { + return leveldown = _dereq_('leveldown') + } catch (e) { + throw new LevelUPError(missingLevelDOWNError) + } +} + +function dispatchError (levelup, error, callback) { + return typeof callback == 'function' + ? callback(error) + : levelup.emit('error', error) +} + +function getKeyEncoder (options, op) { + var type = ((op && op.keyEncoding) || options.keyEncoding) || 'utf8' + return encodings[type] || type +} + +function getValueEncoder (options, op) { + var type = (((op && (op.valueEncoding || op.encoding)) + || options.valueEncoding || options.encoding)) || 'utf8' + return encodings[type] || type +} + +function encodeKey (key, options, op) { + return getKeyEncoder(options, op).encode(key) +} + +function encodeValue (value, options, op) { + return getValueEncoder(options, op).encode(value) +} + +function decodeKey (key, options) { + return getKeyEncoder(options).decode(key) +} + +function decodeValue (value, options) { + return getValueEncoder(options).decode(value) +} + +function isValueAsBuffer (options, op) { + return getValueEncoder(options, op).buffer +} + +function isKeyAsBuffer (options, op) { + return getKeyEncoder(options, op).buffer +} + +module.exports = { + defaultOptions : defaultOptions + , copy : copy + , getOptions : getOptions + , getLevelDOWN : getLevelDOWN + , dispatchError : dispatchError + , encodeKey : encodeKey + , encodeValue : encodeValue + , isValueAsBuffer : isValueAsBuffer + , isKeyAsBuffer : isKeyAsBuffer + , decodeValue : decodeValue + , decodeKey : decodeKey +} + +}).call(this,_dereq_('_process'),_dereq_("buffer").Buffer) +},{"../package.json":97,"./errors":74,"_process":24,"buffer":17,"leveldown":"leveldown","leveldown/package":16,"semver":16,"xtend":96}],78:[function(_dereq_,module,exports){ +(function (process,global){ +/* Copyright (c) 2012-2014 LevelUP contributors + * See list at <https://github.com/rvagg/node-levelup#contributing> + * MIT License + * <https://github.com/rvagg/node-levelup/blob/master/LICENSE.md> + */ + +var Stream = _dereq_('stream').Stream + , inherits = _dereq_('util').inherits + , extend = _dereq_('xtend') + , bl = _dereq_('bl') + + , setImmediate = global.setImmediate || process.nextTick + + , getOptions = _dereq_('./util').getOptions + + , defaultOptions = { type: 'put' } + +function WriteStream (options, db) { + if (!(this instanceof WriteStream)) + return new WriteStream(options, db) + + Stream.call(this) + this._options = extend(defaultOptions, getOptions(db, options)) + this._db = db + this._buffer = [] + this._status = 'init' + this._end = false + this.writable = true + this.readable = false + + var self = this + , ready = function () { + if (!self.writable) + return + self._status = 'ready' + self.emit('ready') + self._process() + } + + if (db.isOpen()) + setImmediate(ready) + else + db.once('ready', ready) +} + +inherits(WriteStream, Stream) + +WriteStream.prototype.write = function (data) { + if (!this.writable) + return false + this._buffer.push(data) + if (this._status != 'init') + this._processDelayed() + if (this._options.maxBufferLength && + this._buffer.length > this._options.maxBufferLength) { + this._writeBlock = true + return false + } + return true +} + +WriteStream.prototype.end = function (data) { + var self = this + if (data) + this.write(data) + setImmediate(function () { + self._end = true + self._process() + }) +} + +WriteStream.prototype.destroy = function () { + this.writable = false + this.end() +} + +WriteStream.prototype.destroySoon = function () { + this.end() +} + +WriteStream.prototype.add = function (entry) { + if (!entry.props) + return + if (entry.props.Directory) + entry.pipe(this._db.writeStream(this._options)) + else if (entry.props.File || entry.File || entry.type == 'File') + this._write(entry) + return true +} + +WriteStream.prototype._processDelayed = function () { + var self = this + setImmediate(function () { + self._process() + }) +} + +WriteStream.prototype._process = function () { + var buffer + , self = this + + , cb = function (err) { + if (!self.writable) + return + if (self._status != 'closed') + self._status = 'ready' + if (err) { + self.writable = false + return self.emit('error', err) + } + self._process() + } + + if (self._status != 'ready' && self.writable) { + if (self._buffer.length && self._status != 'closed') + self._processDelayed() + return + } + + if (self._buffer.length && self.writable) { + self._status = 'writing' + buffer = self._buffer + self._buffer = [] + + self._db.batch(buffer.map(function (d) { + return { + type : d.type || self._options.type + , key : d.key + , value : d.value + , keyEncoding : d.keyEncoding || self._options.keyEncoding + , valueEncoding : d.valueEncoding + || d.encoding + || self._options.valueEncoding + } + }), cb) + + if (self._writeBlock) { + self._writeBlock = false + self.emit('drain') + } + + // don't allow close until callback has returned + return + } + + if (self._end && self._status != 'closed') { + self._status = 'closed' + self.writable = false + self.emit('close') + } +} + +WriteStream.prototype._write = function (entry) { + var key = entry.path || entry.props.path + , self = this + + if (!key) + return + + entry.pipe(bl(function (err, data) { + if (err) { + self.writable = false + return self.emit('error', err) + } + + if (self._options.fstreamRoot && + key.indexOf(self._options.fstreamRoot) > -1) + key = key.substr(self._options.fstreamRoot.length + 1) + + self.write({ key: key, value: data.slice(0) }) + })) +} + +WriteStream.prototype.toString = function () { + return 'LevelUP.WriteStream' +} + +module.exports = WriteStream + +}).call(this,_dereq_('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./util":77,"_process":24,"bl":79,"stream":36,"util":39,"xtend":96}],79:[function(_dereq_,module,exports){ +(function (Buffer){ +var DuplexStream = _dereq_('readable-stream').Duplex + , util = _dereq_('util') + +function BufferList (callback) { + if (!(this instanceof BufferList)) + return new BufferList(callback) + + this._bufs = [] + this.length = 0 + + if (typeof callback == 'function') { + this._callback = callback + + var piper = function (err) { + if (this._callback) { + this._callback(err) + this._callback = null + } + }.bind(this) + + this.on('pipe', function (src) { + src.on('error', piper) + }) + this.on('unpipe', function (src) { + src.removeListener('error', piper) + }) + } + else if (Buffer.isBuffer(callback)) + this.append(callback) + else if (Array.isArray(callback)) { + callback.forEach(function (b) { + Buffer.isBuffer(b) && this.append(b) + }.bind(this)) + } + + DuplexStream.call(this) +} + +util.inherits(BufferList, DuplexStream) + +BufferList.prototype._offset = function (offset) { + var tot = 0, i = 0, _t + for (; i < this._bufs.length; i++) { + _t = tot + this._bufs[i].length + if (offset < _t) + return [ i, offset - tot ] + tot = _t + } +} + +BufferList.prototype.append = function (buf) { + this._bufs.push(Buffer.isBuffer(buf) ? buf : new Buffer(buf)) + this.length += buf.length + return this +} + +BufferList.prototype._write = function (buf, encoding, callback) { + this.append(buf) + if (callback) + callback() +} + +BufferList.prototype._read = function (size) { + if (!this.length) + return this.push(null) + size = Math.min(size, this.length) + this.push(this.slice(0, size)) + this.consume(size) +} + +BufferList.prototype.end = function (chunk) { + DuplexStream.prototype.end.call(this, chunk) + + if (this._callback) { + this._callback(null, this.slice()) + this._callback = null + } +} + +BufferList.prototype.get = function (index) { + return this.slice(index, index + 1)[0] +} + +BufferList.prototype.slice = function (start, end) { + return this.copy(null, 0, start, end) +} + +BufferList.prototype.copy = function (dst, dstStart, srcStart, srcEnd) { + if (typeof srcStart != 'number' || srcStart < 0) + srcStart = 0 + if (typeof srcEnd != 'number' || srcEnd > this.length) + srcEnd = this.length + if (srcStart >= this.length) + return dst || new Buffer(0) + if (srcEnd <= 0) + return dst || new Buffer(0) + + var copy = !!dst + , off = this._offset(srcStart) + , len = srcEnd - srcStart + , bytes = len + , bufoff = (copy && dstStart) || 0 + , start = off[1] + , l + , i + + // copy/slice everything + if (srcStart === 0 && srcEnd == this.length) { + if (!copy) // slice, just return a full concat + return Buffer.concat(this._bufs) + + // copy, need to copy individual buffers + for (i = 0; i < this._bufs.length; i++) { + this._bufs[i].copy(dst, bufoff) + bufoff += this._bufs[i].length + } + + return dst + } + + // easy, cheap case where it's a subset of one of the buffers + if (bytes <= this._bufs[off[0]].length - start) { + return copy + ? this._bufs[off[0]].copy(dst, dstStart, start, start + bytes) + : this._bufs[off[0]].slice(start, start + bytes) + } + + if (!copy) // a slice, we need something to copy in to + dst = new Buffer(len) + + for (i = off[0]; i < this._bufs.length; i++) { + l = this._bufs[i].length - start + + if (bytes > l) { + this._bufs[i].copy(dst, bufoff, start) + } else { + this._bufs[i].copy(dst, bufoff, start, start + bytes) + break + } + + bufoff += l + bytes -= l + + if (start) + start = 0 + } + + return dst +} + +BufferList.prototype.toString = function (encoding, start, end) { + return this.slice(start, end).toString(encoding) +} + +BufferList.prototype.consume = function (bytes) { + while (this._bufs.length) { + if (bytes > this._bufs[0].length) { + bytes -= this._bufs[0].length + this.length -= this._bufs[0].length + this._bufs.shift() + } else { + this._bufs[0] = this._bufs[0].slice(bytes) + this.length -= bytes + break + } + } + return this +} + +BufferList.prototype.duplicate = function () { + var i = 0 + , copy = new BufferList() + + for (; i < this._bufs.length; i++) + copy.append(this._bufs[i]) + + return copy +} + +BufferList.prototype.destroy = function () { + this._bufs.length = 0; + this.length = 0; + this.push(null); +} + +;(function () { + var methods = { + 'readDoubleBE' : 8 + , 'readDoubleLE' : 8 + , 'readFloatBE' : 4 + , 'readFloatLE' : 4 + , 'readInt32BE' : 4 + , 'readInt32LE' : 4 + , 'readUInt32BE' : 4 + , 'readUInt32LE' : 4 + , 'readInt16BE' : 2 + , 'readInt16LE' : 2 + , 'readUInt16BE' : 2 + , 'readUInt16LE' : 2 + , 'readInt8' : 1 + , 'readUInt8' : 1 + } + + for (var m in methods) { + (function (m) { + BufferList.prototype[m] = function (offset) { + return this.slice(offset, offset + methods[m])[m](0) + } + }(m)) + } +}()) + +module.exports = BufferList + +}).call(this,_dereq_("buffer").Buffer) +},{"buffer":17,"readable-stream":95,"util":39}],80:[function(_dereq_,module,exports){ +(function (process,Buffer){ +var util = _dereq_('util') + , AbstractLevelDOWN = _dereq_('abstract-leveldown').AbstractLevelDOWN + +function DeferredLevelDOWN (location) { + AbstractLevelDOWN.call(this, typeof location == 'string' ? location : '') // optional location, who cares? + this._db = undefined + this._operations = [] +} + +util.inherits(DeferredLevelDOWN, AbstractLevelDOWN) + +// called by LevelUP when we have a real DB to take its place +DeferredLevelDOWN.prototype.setDb = function (db) { + this._db = db + this._operations.forEach(function (op) { + db[op.method].apply(db, op.args) + }) +} + +DeferredLevelDOWN.prototype._open = function (options, callback) { + return process.nextTick(callback) +} + +// queue a new deferred operation +DeferredLevelDOWN.prototype._operation = function (method, args) { + if (this._db) + return this._db[method].apply(this._db, args) + this._operations.push({ method: method, args: args }) +} + +// deferrables +'put get del batch approximateSize'.split(' ').forEach(function (m) { + DeferredLevelDOWN.prototype['_' + m] = function () { + this._operation(m, arguments) + } +}) + +DeferredLevelDOWN.prototype._isBuffer = function (obj) { + return Buffer.isBuffer(obj) +} + +// don't need to implement this as LevelUP's ReadStream checks for 'ready' state +DeferredLevelDOWN.prototype._iterator = function () { + throw new TypeError('not implemented') +} + +module.exports = DeferredLevelDOWN + +}).call(this,_dereq_('_process'),_dereq_("buffer").Buffer) +},{"_process":24,"abstract-leveldown":83,"buffer":17,"util":39}],81:[function(_dereq_,module,exports){ +module.exports=_dereq_(46) +},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/abstract-leveldown/abstract-chained-batch.js":46,"_process":24}],82:[function(_dereq_,module,exports){ +module.exports=_dereq_(47) +},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/abstract-leveldown/abstract-iterator.js":47,"_process":24}],83:[function(_dereq_,module,exports){ +module.exports=_dereq_(48) +},{"./abstract-chained-batch":81,"./abstract-iterator":82,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/abstract-leveldown/abstract-leveldown.js":48,"_process":24,"buffer":17,"xtend":96}],84:[function(_dereq_,module,exports){ +var prr = _dereq_('prr') + +function init (type, message, cause) { + prr(this, { + type : type + , name : type + // can be passed just a 'cause' + , cause : typeof message != 'string' ? message : cause + , message : !!message && typeof message != 'string' ? message.message : message + + }, 'ewr') +} + +// generic prototype, not intended to be actually used - helpful for `instanceof` +function CustomError (message, cause) { + Error.call(this) + if (Error.captureStackTrace) + Error.captureStackTrace(this, arguments.callee) + init.call(this, 'CustomError', message, cause) +} + +CustomError.prototype = new Error() + +function createError (errno, type, proto) { + var err = function (message, cause) { + init.call(this, type, message, cause) + //TODO: the specificity here is stupid, errno should be available everywhere + if (type == 'FilesystemError') { + this.code = this.cause.code + this.path = this.cause.path + this.errno = this.cause.errno + this.message = + (errno.errno[this.cause.errno] + ? errno.errno[this.cause.errno].description + : this.cause.message) + + (this.cause.path ? ' [' + this.cause.path + ']' : '') + } + Error.call(this) + if (Error.captureStackTrace) + Error.captureStackTrace(this, arguments.callee) + } + err.prototype = !!proto ? new proto() : new CustomError() + return err +} + +module.exports = function (errno) { + var ce = function (type, proto) { + return createError(errno, type, proto) + } + return { + CustomError : CustomError + , FilesystemError : ce('FilesystemError') + , createError : ce + } +} + +},{"prr":86}],85:[function(_dereq_,module,exports){ +var all = module.exports.all = [ + { + "errno": -1, + "code": "UNKNOWN", + "description": "unknown error" + }, + { + "errno": 0, + "code": "OK", + "description": "success" + }, + { + "errno": 1, + "code": "EOF", + "description": "end of file" + }, + { + "errno": 2, + "code": "EADDRINFO", + "description": "getaddrinfo error" + }, + { + "errno": 3, + "code": "EACCES", + "description": "permission denied" + }, + { + "errno": 4, + "code": "EAGAIN", + "description": "resource temporarily unavailable" + }, + { + "errno": 5, + "code": "EADDRINUSE", + "description": "address already in use" + }, + { + "errno": 6, + "code": "EADDRNOTAVAIL", + "description": "address not available" + }, + { + "errno": 7, + "code": "EAFNOSUPPORT", + "description": "address family not supported" + }, + { + "errno": 8, + "code": "EALREADY", + "description": "connection already in progress" + }, + { + "errno": 9, + "code": "EBADF", + "description": "bad file descriptor" + }, + { + "errno": 10, + "code": "EBUSY", + "description": "resource busy or locked" + }, + { + "errno": 11, + "code": "ECONNABORTED", + "description": "software caused connection abort" + }, + { + "errno": 12, + "code": "ECONNREFUSED", + "description": "connection refused" + }, + { + "errno": 13, + "code": "ECONNRESET", + "description": "connection reset by peer" + }, + { + "errno": 14, + "code": "EDESTADDRREQ", + "description": "destination address required" + }, + { + "errno": 15, + "code": "EFAULT", + "description": "bad address in system call argument" + }, + { + "errno": 16, + "code": "EHOSTUNREACH", + "description": "host is unreachable" + }, + { + "errno": 17, + "code": "EINTR", + "description": "interrupted system call" + }, + { + "errno": 18, + "code": "EINVAL", + "description": "invalid argument" + }, + { + "errno": 19, + "code": "EISCONN", + "description": "socket is already connected" + }, + { + "errno": 20, + "code": "EMFILE", + "description": "too many open files" + }, + { + "errno": 21, + "code": "EMSGSIZE", + "description": "message too long" + }, + { + "errno": 22, + "code": "ENETDOWN", + "description": "network is down" + }, + { + "errno": 23, + "code": "ENETUNREACH", + "description": "network is unreachable" + }, + { + "errno": 24, + "code": "ENFILE", + "description": "file table overflow" + }, + { + "errno": 25, + "code": "ENOBUFS", + "description": "no buffer space available" + }, + { + "errno": 26, + "code": "ENOMEM", + "description": "not enough memory" + }, + { + "errno": 27, + "code": "ENOTDIR", + "description": "not a directory" + }, + { + "errno": 28, + "code": "EISDIR", + "description": "illegal operation on a directory" + }, + { + "errno": 29, + "code": "ENONET", + "description": "machine is not on the network" + }, + { + "errno": 31, + "code": "ENOTCONN", + "description": "socket is not connected" + }, + { + "errno": 32, + "code": "ENOTSOCK", + "description": "socket operation on non-socket" + }, + { + "errno": 33, + "code": "ENOTSUP", + "description": "operation not supported on socket" + }, + { + "errno": 34, + "code": "ENOENT", + "description": "no such file or directory" + }, + { + "errno": 35, + "code": "ENOSYS", + "description": "function not implemented" + }, + { + "errno": 36, + "code": "EPIPE", + "description": "broken pipe" + }, + { + "errno": 37, + "code": "EPROTO", + "description": "protocol error" + }, + { + "errno": 38, + "code": "EPROTONOSUPPORT", + "description": "protocol not supported" + }, + { + "errno": 39, + "code": "EPROTOTYPE", + "description": "protocol wrong type for socket" + }, + { + "errno": 40, + "code": "ETIMEDOUT", + "description": "connection timed out" + }, + { + "errno": 41, + "code": "ECHARSET", + "description": "invalid Unicode character" + }, + { + "errno": 42, + "code": "EAIFAMNOSUPPORT", + "description": "address family for hostname not supported" + }, + { + "errno": 44, + "code": "EAISERVICE", + "description": "servname not supported for ai_socktype" + }, + { + "errno": 45, + "code": "EAISOCKTYPE", + "description": "ai_socktype not supported" + }, + { + "errno": 46, + "code": "ESHUTDOWN", + "description": "cannot send after transport endpoint shutdown" + }, + { + "errno": 47, + "code": "EEXIST", + "description": "file already exists" + }, + { + "errno": 48, + "code": "ESRCH", + "description": "no such process" + }, + { + "errno": 49, + "code": "ENAMETOOLONG", + "description": "name too long" + }, + { + "errno": 50, + "code": "EPERM", + "description": "operation not permitted" + }, + { + "errno": 51, + "code": "ELOOP", + "description": "too many symbolic links encountered" + }, + { + "errno": 52, + "code": "EXDEV", + "description": "cross-device link not permitted" + }, + { + "errno": 53, + "code": "ENOTEMPTY", + "description": "directory not empty" + }, + { + "errno": 54, + "code": "ENOSPC", + "description": "no space left on device" + }, + { + "errno": 55, + "code": "EIO", + "description": "i/o error" + }, + { + "errno": 56, + "code": "EROFS", + "description": "read-only file system" + }, + { + "errno": 57, + "code": "ENODEV", + "description": "no such device" + }, + { + "errno": 58, + "code": "ESPIPE", + "description": "invalid seek" + }, + { + "errno": 59, + "code": "ECANCELED", + "description": "operation canceled" + } +] + + +module.exports.errno = { + '-1': all[0] + , '0': all[1] + , '1': all[2] + , '2': all[3] + , '3': all[4] + , '4': all[5] + , '5': all[6] + , '6': all[7] + , '7': all[8] + , '8': all[9] + , '9': all[10] + , '10': all[11] + , '11': all[12] + , '12': all[13] + , '13': all[14] + , '14': all[15] + , '15': all[16] + , '16': all[17] + , '17': all[18] + , '18': all[19] + , '19': all[20] + , '20': all[21] + , '21': all[22] + , '22': all[23] + , '23': all[24] + , '24': all[25] + , '25': all[26] + , '26': all[27] + , '27': all[28] + , '28': all[29] + , '29': all[30] + , '31': all[31] + , '32': all[32] + , '33': all[33] + , '34': all[34] + , '35': all[35] + , '36': all[36] + , '37': all[37] + , '38': all[38] + , '39': all[39] + , '40': all[40] + , '41': all[41] + , '42': all[42] + , '44': all[43] + , '45': all[44] + , '46': all[45] + , '47': all[46] + , '48': all[47] + , '49': all[48] + , '50': all[49] + , '51': all[50] + , '52': all[51] + , '53': all[52] + , '54': all[53] + , '55': all[54] + , '56': all[55] + , '57': all[56] + , '58': all[57] + , '59': all[58] +} + + +module.exports.code = { + 'UNKNOWN': all[0] + , 'OK': all[1] + , 'EOF': all[2] + , 'EADDRINFO': all[3] + , 'EACCES': all[4] + , 'EAGAIN': all[5] + , 'EADDRINUSE': all[6] + , 'EADDRNOTAVAIL': all[7] + , 'EAFNOSUPPORT': all[8] + , 'EALREADY': all[9] + , 'EBADF': all[10] + , 'EBUSY': all[11] + , 'ECONNABORTED': all[12] + , 'ECONNREFUSED': all[13] + , 'ECONNRESET': all[14] + , 'EDESTADDRREQ': all[15] + , 'EFAULT': all[16] + , 'EHOSTUNREACH': all[17] + , 'EINTR': all[18] + , 'EINVAL': all[19] + , 'EISCONN': all[20] + , 'EMFILE': all[21] + , 'EMSGSIZE': all[22] + , 'ENETDOWN': all[23] + , 'ENETUNREACH': all[24] + , 'ENFILE': all[25] + , 'ENOBUFS': all[26] + , 'ENOMEM': all[27] + , 'ENOTDIR': all[28] + , 'EISDIR': all[29] + , 'ENONET': all[30] + , 'ENOTCONN': all[31] + , 'ENOTSOCK': all[32] + , 'ENOTSUP': all[33] + , 'ENOENT': all[34] + , 'ENOSYS': all[35] + , 'EPIPE': all[36] + , 'EPROTO': all[37] + , 'EPROTONOSUPPORT': all[38] + , 'EPROTOTYPE': all[39] + , 'ETIMEDOUT': all[40] + , 'ECHARSET': all[41] + , 'EAIFAMNOSUPPORT': all[42] + , 'EAISERVICE': all[43] + , 'EAISOCKTYPE': all[44] + , 'ESHUTDOWN': all[45] + , 'EEXIST': all[46] + , 'ESRCH': all[47] + , 'ENAMETOOLONG': all[48] + , 'EPERM': all[49] + , 'ELOOP': all[50] + , 'EXDEV': all[51] + , 'ENOTEMPTY': all[52] + , 'ENOSPC': all[53] + , 'EIO': all[54] + , 'EROFS': all[55] + , 'ENODEV': all[56] + , 'ESPIPE': all[57] + , 'ECANCELED': all[58] +} + + +module.exports.custom = _dereq_("./custom")(module.exports) +module.exports.create = module.exports.custom.createError +},{"./custom":84}],86:[function(_dereq_,module,exports){ +/*! + * prr + * (c) 2013 Rod Vagg <rod@vagg.org> + * https://github.com/rvagg/prr + * License: MIT + */ + +(function (name, context, definition) { + if (typeof module != 'undefined' && module.exports) + module.exports = definition() + else + context[name] = definition() +})('prr', this, function() { + + var setProperty = typeof Object.defineProperty == 'function' + ? function (obj, key, options) { + Object.defineProperty(obj, key, options) + return obj + } + : function (obj, key, options) { // < es5 + obj[key] = options.value + return obj + } + + , makeOptions = function (value, options) { + var oo = typeof options == 'object' + , os = !oo && typeof options == 'string' + , op = function (p) { + return oo + ? !!options[p] + : os + ? options.indexOf(p[0]) > -1 + : false + } + + return { + enumerable : op('enumerable') + , configurable : op('configurable') + , writable : op('writable') + , value : value + } + } + + , prr = function (obj, key, value, options) { + var k + + options = makeOptions(value, options) + + if (typeof key == 'object') { + for (k in key) { + if (Object.hasOwnProperty.call(key, k)) { + options.value = key[k] + setProperty(obj, k, options) + } + } + return obj + } + + return setProperty(obj, key, options) + } + + return prr +}) +},{}],87:[function(_dereq_,module,exports){ +module.exports=_dereq_(26) +},{"./_stream_readable":89,"./_stream_writable":91,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_duplex.js":26,"_process":24,"core-util-is":92,"inherits":44}],88:[function(_dereq_,module,exports){ +module.exports=_dereq_(27) +},{"./_stream_transform":90,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_passthrough.js":27,"core-util-is":92,"inherits":44}],89:[function(_dereq_,module,exports){ +module.exports=_dereq_(28) +},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_readable.js":28,"_process":24,"buffer":17,"core-util-is":92,"events":21,"inherits":44,"isarray":93,"stream":36,"string_decoder/":94}],90:[function(_dereq_,module,exports){ +module.exports=_dereq_(29) +},{"./_stream_duplex":87,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_transform.js":29,"core-util-is":92,"inherits":44}],91:[function(_dereq_,module,exports){ +module.exports=_dereq_(30) +},{"./_stream_duplex":87,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_writable.js":30,"_process":24,"buffer":17,"core-util-is":92,"inherits":44,"stream":36}],92:[function(_dereq_,module,exports){ +module.exports=_dereq_(31) +},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/node_modules/core-util-is/lib/util.js":31,"buffer":17}],93:[function(_dereq_,module,exports){ +module.exports=_dereq_(22) +},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/isarray/index.js":22}],94:[function(_dereq_,module,exports){ +module.exports=_dereq_(37) +},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/string_decoder/index.js":37,"buffer":17}],95:[function(_dereq_,module,exports){ +module.exports=_dereq_(33) +},{"./lib/_stream_duplex.js":87,"./lib/_stream_passthrough.js":88,"./lib/_stream_readable.js":89,"./lib/_stream_transform.js":90,"./lib/_stream_writable.js":91,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/readable.js":33,"stream":36}],96:[function(_dereq_,module,exports){ +module.exports=_dereq_(49) +},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/abstract-leveldown/node_modules/xtend/index.js":49}],97:[function(_dereq_,module,exports){ +module.exports={ + "name": "levelup", + "description": "Fast & simple storage - a Node.js-style LevelDB wrapper", + "version": "0.18.6", + "contributors": [ + { + "name": "Rod Vagg", + "email": "r@va.gg", + "url": "https://github.com/rvagg" + }, + { + "name": "John Chesley", + "email": "john@chesl.es", + "url": "https://github.com/chesles/" + }, + { + "name": "Jake Verbaten", + "email": "raynos2@gmail.com", + "url": "https://github.com/raynos" + }, + { + "name": "Dominic Tarr", + "email": "dominic.tarr@gmail.com", + "url": "https://github.com/dominictarr" + }, + { + "name": "Max Ogden", + "email": "max@maxogden.com", + "url": "https://github.com/maxogden" + }, + { + "name": "Lars-Magnus Skog", + "email": "lars.magnus.skog@gmail.com", + "url": "https://github.com/ralphtheninja" + }, + { + "name": "David Björklund", + "email": "david.bjorklund@gmail.com", + "url": "https://github.com/kesla" + }, + { + "name": "Julian Gruber", + "email": "julian@juliangruber.com", + "url": "https://github.com/juliangruber" + }, + { + "name": "Paolo Fragomeni", + "email": "paolo@async.ly", + "url": "https://github.com/hij1nx" + }, + { + "name": "Anton Whalley", + "email": "anton.whalley@nearform.com", + "url": "https://github.com/No9" + }, + { + "name": "Matteo Collina", + "email": "matteo.collina@gmail.com", + "url": "https://github.com/mcollina" + }, + { + "name": "Pedro Teixeira", + "email": "pedro.teixeira@gmail.com", + "url": "https://github.com/pgte" + }, + { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "https://github.com/substack" + } + ], + "repository": { + "type": "git", + "url": "https://github.com/rvagg/node-levelup.git" + }, + "homepage": "https://github.com/rvagg/node-levelup", + "keywords": [ + "leveldb", + "stream", + "database", + "db", + "store", + "storage", + "json" + ], + "main": "lib/levelup.js", + "dependencies": { + "bl": "~0.8.1", + "deferred-leveldown": "~0.2.0", + "errno": "~0.1.1", + "prr": "~0.0.0", + "readable-stream": "~1.0.26", + "semver": "~2.3.1", + "xtend": "~3.0.0" + }, + "devDependencies": { + "leveldown": "~0.10.0", + "bustermove": "*", + "tap": "*", + "referee": "*", + "rimraf": "*", + "async": "*", + "fstream": "*", + "tar": "*", + "mkfiletree": "*", + "readfiletree": "*", + "slow-stream": ">=0.0.4", + "delayed": "*", + "boganipsum": "*", + "du": "*", + "memdown": "*", + "msgpack-js": "*" + }, + "browser": { + "leveldown": false, + "leveldown/package": false, + "semver": false + }, + "scripts": { + "test": "tap test/*-test.js --stderr", + "functionaltests": "node ./test/functional/fstream-test.js && node ./test/functional/binary-data-test.js && node ./test/functional/compat-test.js", + "alltests": "npm test && npm run-script functionaltests" + }, + "license": "MIT", + "gitHead": "213e989e2b75273e2b44c23f84f95e35bff7ea11", + "bugs": { + "url": "https://github.com/rvagg/node-levelup/issues" + }, + "_id": "levelup@0.18.6", + "_shasum": "e6a01cb089616c8ecc0291c2a9bd3f0c44e3e5eb", + "_from": "levelup@~0.18.4", + "_npmVersion": "1.4.14", + "_npmUser": { + "name": "rvagg", + "email": "rod@vagg.org" + }, + "maintainers": [ + { + "name": "rvagg", + "email": "rod@vagg.org" + } + ], + "dist": { + "shasum": "e6a01cb089616c8ecc0291c2a9bd3f0c44e3e5eb", + "tarball": "http://127.0.0.1:5080/tarballs/levelup/0.18.6.tgz" + }, + "_resolved": "http://127.0.0.1:5080/tarballs/levelup/0.18.6.tgz", + "readme": "ERROR: No README data found!" +} + +},{}],98:[function(_dereq_,module,exports){ +'use strict'; + +module.exports = INTERNAL; + +function INTERNAL() {} +},{}],99:[function(_dereq_,module,exports){ +'use strict'; +var Promise = _dereq_('./promise'); +var reject = _dereq_('./reject'); +var resolve = _dereq_('./resolve'); +var INTERNAL = _dereq_('./INTERNAL'); +var handlers = _dereq_('./handlers'); +module.exports = all; +function all(iterable) { + if (Object.prototype.toString.call(iterable) !== '[object Array]') { + return reject(new TypeError('must be an array')); + } + + var len = iterable.length; + var called = false; + if (!len) { + return resolve([]); + } + + var values = new Array(len); + var resolved = 0; + var i = -1; + var promise = new Promise(INTERNAL); + + while (++i < len) { + allResolver(iterable[i], i); + } + return promise; + function allResolver(value, i) { + resolve(value).then(resolveFromAll, function (error) { + if (!called) { + called = true; + handlers.reject(promise, error); + } + }); + function resolveFromAll(outValue) { + values[i] = outValue; + if (++resolved === len & !called) { + called = true; + handlers.resolve(promise, values); + } + } + } +} +},{"./INTERNAL":98,"./handlers":100,"./promise":102,"./reject":105,"./resolve":106}],100:[function(_dereq_,module,exports){ +'use strict'; +var tryCatch = _dereq_('./tryCatch'); +var resolveThenable = _dereq_('./resolveThenable'); +var states = _dereq_('./states'); + +exports.resolve = function (self, value) { + var result = tryCatch(getThen, value); + if (result.status === 'error') { + return exports.reject(self, result.value); + } + var thenable = result.value; + + if (thenable) { + resolveThenable.safely(self, thenable); + } else { + self.state = states.FULFILLED; + self.outcome = value; + var i = -1; + var len = self.queue.length; + while (++i < len) { + self.queue[i].callFulfilled(value); + } + } + return self; +}; +exports.reject = function (self, error) { + self.state = states.REJECTED; + self.outcome = error; + var i = -1; + var len = self.queue.length; + while (++i < len) { + self.queue[i].callRejected(error); + } + return self; +}; + +function getThen(obj) { + // Make sure we only access the accessor once as required by the spec + var then = obj && obj.then; + if (obj && typeof obj === 'object' && typeof then === 'function') { + return function appyThen() { + then.apply(obj, arguments); + }; + } +} +},{"./resolveThenable":107,"./states":108,"./tryCatch":109}],101:[function(_dereq_,module,exports){ +module.exports = exports = _dereq_('./promise'); + +exports.resolve = _dereq_('./resolve'); +exports.reject = _dereq_('./reject'); +exports.all = _dereq_('./all'); +exports.race = _dereq_('./race'); +},{"./all":99,"./promise":102,"./race":104,"./reject":105,"./resolve":106}],102:[function(_dereq_,module,exports){ +'use strict'; + +var unwrap = _dereq_('./unwrap'); +var INTERNAL = _dereq_('./INTERNAL'); +var resolveThenable = _dereq_('./resolveThenable'); +var states = _dereq_('./states'); +var QueueItem = _dereq_('./queueItem'); + +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); + } +} + +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)); + } + + return promise; +}; + +},{"./INTERNAL":98,"./queueItem":103,"./resolveThenable":107,"./states":108,"./unwrap":110}],103:[function(_dereq_,module,exports){ +'use strict'; +var handlers = _dereq_('./handlers'); +var unwrap = _dereq_('./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":100,"./unwrap":110}],104:[function(_dereq_,module,exports){ +'use strict'; +var Promise = _dereq_('./promise'); +var reject = _dereq_('./reject'); +var resolve = _dereq_('./resolve'); +var INTERNAL = _dereq_('./INTERNAL'); +var handlers = _dereq_('./handlers'); +module.exports = race; +function race(iterable) { + if (Object.prototype.toString.call(iterable) !== '[object Array]') { + return reject(new TypeError('must be an array')); + } + + var len = iterable.length; + var called = false; + if (!len) { + return resolve([]); + } + + var resolved = 0; + var i = -1; + var promise = new Promise(INTERNAL); + + while (++i < len) { + resolver(iterable[i]); + } + return promise; + function resolver(value) { + resolve(value).then(function (response) { + if (!called) { + called = true; + handlers.resolve(promise, response); + } + }, function (error) { + if (!called) { + called = true; + handlers.reject(promise, error); + } + }); + } +} +},{"./INTERNAL":98,"./handlers":100,"./promise":102,"./reject":105,"./resolve":106}],105:[function(_dereq_,module,exports){ +'use strict'; + +var Promise = _dereq_('./promise'); +var INTERNAL = _dereq_('./INTERNAL'); +var handlers = _dereq_('./handlers'); +module.exports = reject; + +function reject(reason) { + var promise = new Promise(INTERNAL); + return handlers.reject(promise, reason); +} +},{"./INTERNAL":98,"./handlers":100,"./promise":102}],106:[function(_dereq_,module,exports){ +'use strict'; + +var Promise = _dereq_('./promise'); +var INTERNAL = _dereq_('./INTERNAL'); +var handlers = _dereq_('./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":98,"./handlers":100,"./promise":102}],107:[function(_dereq_,module,exports){ +'use strict'; +var handlers = _dereq_('./handlers'); +var tryCatch = _dereq_('./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":100,"./tryCatch":109}],108:[function(_dereq_,module,exports){ +// Lazy man's symbols for states + +exports.REJECTED = ['REJECTED']; +exports.FULFILLED = ['FULFILLED']; +exports.PENDING = ['PENDING']; +},{}],109:[function(_dereq_,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; +} +},{}],110:[function(_dereq_,module,exports){ +'use strict'; + +var immediate = _dereq_('immediate'); +var handlers = _dereq_('./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":100,"immediate":111}],111:[function(_dereq_,module,exports){ +'use strict'; +var types = [ + _dereq_('./nextTick'), + _dereq_('./mutation.js'), + _dereq_('./messageChannel'), + _dereq_('./stateChange'), + _dereq_('./timeout') +]; +var draining; +var queue = []; +//named nextTick for less confusing stack traces +function nextTick() { + draining = true; + var i, oldQueue; + var len = queue.length; + while (len) { + oldQueue = queue; + queue = []; + i = -1; + while (++i < len) { + oldQueue[i](); + } + len = queue.length; + } + draining = false; +} +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; + } +} +module.exports = immediate; +function immediate(task) { + if (queue.push(task) === 1 && !draining) { + scheduleDrain(); + } +} +},{"./messageChannel":112,"./mutation.js":113,"./nextTick":16,"./stateChange":114,"./timeout":115}],112:[function(_dereq_,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 : {}) +},{}],113:[function(_dereq_,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 : {}) +},{}],114:[function(_dereq_,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 <script> 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 : {}) +},{}],115:[function(_dereq_,module,exports){ +'use strict'; +exports.test = function () { + return true; +}; + +exports.install = function (t) { + return function () { + setTimeout(t, 0); + }; +}; +},{}],116:[function(_dereq_,module,exports){ +"use strict"; + +// Extends method +// (taken from http://code.jquery.com/jquery-1.9.0.js) +// Populate the class2type map +var class2type = {}; + +var types = [ + "Boolean", "Number", "String", "Function", "Array", + "Date", "RegExp", "Object", "Error" +]; +for (var i = 0; i < types.length; i++) { + var typename = types[i]; + class2type["[object " + typename + "]"] = typename.toLowerCase(); +} + +var core_toString = class2type.toString; +var core_hasOwn = class2type.hasOwnProperty; + +function type(obj) { + if (obj === null) { + return String(obj); + } + return typeof obj === "object" || typeof obj === "function" ? + class2type[core_toString.call(obj)] || "object" : + typeof obj; +} + +function isWindow(obj) { + return obj !== null && obj === obj.window; +} + +function isPlainObject(obj) { + // Must be an Object. + // Because of IE, we also have to check the presence of + // the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if (!obj || type(obj) !== "object" || obj.nodeType || isWindow(obj)) { + return false; + } + + try { + // Not own constructor property must be Object + if (obj.constructor && + !core_hasOwn.call(obj, "constructor") && + !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + var key; + for (key in obj) {} + + return key === undefined || core_hasOwn.call(obj, key); +} + + +function isFunction(obj) { + return type(obj) === "function"; +} + +var isArray = Array.isArray || function (obj) { + return type(obj) === "array"; +}; + +function extend() { + // originally extend() was recursive, but this ended up giving us + // "call stack exceeded", so it's been unrolled to use a literal stack + // (see https://github.com/pouchdb/pouchdb/issues/2543) + var stack = []; + var i = -1; + var len = arguments.length; + var args = new Array(len); + while (++i < len) { + args[i] = arguments[i]; + } + var container = {}; + stack.push({args: args, result: {container: container, key: 'key'}}); + var next; + while ((next = stack.pop())) { + extendInner(stack, next.args, next.result); + } + return container.key; +} + +function extendInner(stack, args, result) { + var options, name, src, copy, copyIsArray, clone, + target = args[0] || {}, + i = 1, + length = args.length, + deep = false, + numericStringRegex = /\d+/, + optionsIsArray; + + // Handle a deep copy situation + if (typeof target === "boolean") { + deep = target; + target = args[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if (typeof target !== "object" && !isFunction(target)) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if (length === i) { + /* jshint validthis: true */ + target = this; + --i; + } + + for (; i < length; i++) { + // Only deal with non-null/undefined values + if ((options = args[i]) != null) { + optionsIsArray = isArray(options); + // Extend the base object + for (name in options) { + //if (options.hasOwnProperty(name)) { + if (!(name in Object.prototype)) { + if (optionsIsArray && !numericStringRegex.test(name)) { + continue; + } + + src = target[name]; + copy = options[name]; + + // Prevent never-ending loop + if (target === copy) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if (deep && copy && (isPlainObject(copy) || + (copyIsArray = isArray(copy)))) { + if (copyIsArray) { + copyIsArray = false; + clone = src && isArray(src) ? src : []; + + } else { + clone = src && isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + stack.push({ + args: [deep, clone, copy], + result: { + container: target, + key: name + } + }); + + // Don't bring in undefined values + } else if (copy !== undefined) { + if (!(isArray(options) && isFunction(copy))) { + target[name] = copy; + } + } + } + } + } + } + + // "Return" the modified object by setting the key + // on the given container + result.container[result.key] = target; +} + + +module.exports = extend; + + + +},{}],117:[function(_dereq_,module,exports){ +/*jshint bitwise:false*/ +/*global unescape*/ + +(function (factory) { + if (typeof exports === 'object') { + // Node/CommonJS + module.exports = factory(); + } else if (typeof define === 'function' && define.amd) { + // AMD + define(factory); + } else { + // Browser globals (with support for web workers) + var glob; + try { + glob = window; + } catch (e) { + glob = self; + } + + glob.SparkMD5 = factory(); + } +}(function (undefined) { + + 'use strict'; + + //////////////////////////////////////////////////////////////////////////// + + /* + * Fastest md5 implementation around (JKM md5) + * Credits: Joseph Myers + * + * @see http://www.myersdaily.org/joseph/javascript/md5-text.html + * @see http://jsperf.com/md5-shootout/7 + */ + + /* this function is much faster, + so if possible we use it. Some IEs + are the only ones I know of that + need the idiotic second function, + generated by an if clause. */ + var add32 = function (a, b) { + return (a + b) & 0xFFFFFFFF; + }, + + cmn = function (q, a, b, x, s, t) { + a = add32(add32(a, q), add32(x, t)); + return add32((a << s) | (a >>> (32 - s)), b); + }, + + ff = function (a, b, c, d, x, s, t) { + return cmn((b & c) | ((~b) & d), a, b, x, s, t); + }, + + gg = function (a, b, c, d, x, s, t) { + return cmn((b & d) | (c & (~d)), a, b, x, s, t); + }, + + hh = function (a, b, c, d, x, s, t) { + return cmn(b ^ c ^ d, a, b, x, s, t); + }, + + ii = function (a, b, c, d, x, s, t) { + return cmn(c ^ (b | (~d)), a, b, x, s, t); + }, + + md5cycle = function (x, k) { + var a = x[0], + b = x[1], + c = x[2], + d = x[3]; + + a = ff(a, b, c, d, k[0], 7, -680876936); + d = ff(d, a, b, c, k[1], 12, -389564586); + c = ff(c, d, a, b, k[2], 17, 606105819); + b = ff(b, c, d, a, k[3], 22, -1044525330); + a = ff(a, b, c, d, k[4], 7, -176418897); + d = ff(d, a, b, c, k[5], 12, 1200080426); + c = ff(c, d, a, b, k[6], 17, -1473231341); + b = ff(b, c, d, a, k[7], 22, -45705983); + a = ff(a, b, c, d, k[8], 7, 1770035416); + d = ff(d, a, b, c, k[9], 12, -1958414417); + c = ff(c, d, a, b, k[10], 17, -42063); + b = ff(b, c, d, a, k[11], 22, -1990404162); + a = ff(a, b, c, d, k[12], 7, 1804603682); + d = ff(d, a, b, c, k[13], 12, -40341101); + c = ff(c, d, a, b, k[14], 17, -1502002290); + b = ff(b, c, d, a, k[15], 22, 1236535329); + + a = gg(a, b, c, d, k[1], 5, -165796510); + d = gg(d, a, b, c, k[6], 9, -1069501632); + c = gg(c, d, a, b, k[11], 14, 643717713); + b = gg(b, c, d, a, k[0], 20, -373897302); + a = gg(a, b, c, d, k[5], 5, -701558691); + d = gg(d, a, b, c, k[10], 9, 38016083); + c = gg(c, d, a, b, k[15], 14, -660478335); + b = gg(b, c, d, a, k[4], 20, -405537848); + a = gg(a, b, c, d, k[9], 5, 568446438); + d = gg(d, a, b, c, k[14], 9, -1019803690); + c = gg(c, d, a, b, k[3], 14, -187363961); + b = gg(b, c, d, a, k[8], 20, 1163531501); + a = gg(a, b, c, d, k[13], 5, -1444681467); + d = gg(d, a, b, c, k[2], 9, -51403784); + c = gg(c, d, a, b, k[7], 14, 1735328473); + b = gg(b, c, d, a, k[12], 20, -1926607734); + + a = hh(a, b, c, d, k[5], 4, -378558); + d = hh(d, a, b, c, k[8], 11, -2022574463); + c = hh(c, d, a, b, k[11], 16, 1839030562); + b = hh(b, c, d, a, k[14], 23, -35309556); + a = hh(a, b, c, d, k[1], 4, -1530992060); + d = hh(d, a, b, c, k[4], 11, 1272893353); + c = hh(c, d, a, b, k[7], 16, -155497632); + b = hh(b, c, d, a, k[10], 23, -1094730640); + a = hh(a, b, c, d, k[13], 4, 681279174); + d = hh(d, a, b, c, k[0], 11, -358537222); + c = hh(c, d, a, b, k[3], 16, -722521979); + b = hh(b, c, d, a, k[6], 23, 76029189); + a = hh(a, b, c, d, k[9], 4, -640364487); + d = hh(d, a, b, c, k[12], 11, -421815835); + c = hh(c, d, a, b, k[15], 16, 530742520); + b = hh(b, c, d, a, k[2], 23, -995338651); + + a = ii(a, b, c, d, k[0], 6, -198630844); + d = ii(d, a, b, c, k[7], 10, 1126891415); + c = ii(c, d, a, b, k[14], 15, -1416354905); + b = ii(b, c, d, a, k[5], 21, -57434055); + a = ii(a, b, c, d, k[12], 6, 1700485571); + d = ii(d, a, b, c, k[3], 10, -1894986606); + c = ii(c, d, a, b, k[10], 15, -1051523); + b = ii(b, c, d, a, k[1], 21, -2054922799); + a = ii(a, b, c, d, k[8], 6, 1873313359); + d = ii(d, a, b, c, k[15], 10, -30611744); + c = ii(c, d, a, b, k[6], 15, -1560198380); + b = ii(b, c, d, a, k[13], 21, 1309151649); + a = ii(a, b, c, d, k[4], 6, -145523070); + d = ii(d, a, b, c, k[11], 10, -1120210379); + c = ii(c, d, a, b, k[2], 15, 718787259); + b = ii(b, c, d, a, k[9], 21, -343485551); + + x[0] = add32(a, x[0]); + x[1] = add32(b, x[1]); + x[2] = add32(c, x[2]); + x[3] = add32(d, x[3]); + }, + + /* there needs to be support for Unicode here, + * unless we pretend that we can redefine the MD-5 + * algorithm for multi-byte characters (perhaps + * by adding every four 16-bit characters and + * shortening the sum to 32 bits). Otherwise + * I suggest performing MD-5 as if every character + * was two bytes--e.g., 0040 0025 = @%--but then + * how will an ordinary MD-5 sum be matched? + * There is no way to standardize text to something + * like UTF-8 before transformation; speed cost is + * utterly prohibitive. The JavaScript standard + * itself needs to look at this: it should start + * providing access to strings as preformed UTF-8 + * 8-bit unsigned value arrays. + */ + md5blk = function (s) { + var md5blks = [], + i; /* Andy King said do it this way. */ + + for (i = 0; i < 64; i += 4) { + md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); + } + return md5blks; + }, + + md5blk_array = function (a) { + var md5blks = [], + i; /* Andy King said do it this way. */ + + for (i = 0; i < 64; i += 4) { + md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24); + } + return md5blks; + }, + + md51 = function (s) { + var n = s.length, + state = [1732584193, -271733879, -1732584194, 271733878], + i, + length, + tail, + tmp, + lo, + hi; + + for (i = 64; i <= n; i += 64) { + md5cycle(state, md5blk(s.substring(i - 64, i))); + } + s = s.substring(i - 64); + length = s.length; + tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3); + } + tail[i >> 2] |= 0x80 << ((i % 4) << 3); + if (i > 55) { + md5cycle(state, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + + // Beware that the final length might not fit in 32 bits so we take care of that + tmp = n * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + + tail[14] = lo; + tail[15] = hi; + + md5cycle(state, tail); + return state; + }, + + md51_array = function (a) { + var n = a.length, + state = [1732584193, -271733879, -1732584194, 271733878], + i, + length, + tail, + tmp, + lo, + hi; + + for (i = 64; i <= n; i += 64) { + md5cycle(state, md5blk_array(a.subarray(i - 64, i))); + } + + // Not sure if it is a bug, however IE10 will always produce a sub array of length 1 + // containing the last element of the parent array if the sub array specified starts + // beyond the length of the parent array - weird. + // https://connect.microsoft.com/IE/feedback/details/771452/typed-array-subarray-issue + a = (i - 64) < n ? a.subarray(i - 64) : new Uint8Array(0); + + length = a.length; + tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= a[i] << ((i % 4) << 3); + } + + tail[i >> 2] |= 0x80 << ((i % 4) << 3); + if (i > 55) { + md5cycle(state, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + + // Beware that the final length might not fit in 32 bits so we take care of that + tmp = n * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + + tail[14] = lo; + tail[15] = hi; + + md5cycle(state, tail); + + return state; + }, + + hex_chr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'], + + rhex = function (n) { + var s = '', + j; + for (j = 0; j < 4; j += 1) { + s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]; + } + return s; + }, + + hex = function (x) { + var i; + for (i = 0; i < x.length; i += 1) { + x[i] = rhex(x[i]); + } + return x.join(''); + }, + + md5 = function (s) { + return hex(md51(s)); + }, + + + + //////////////////////////////////////////////////////////////////////////// + + /** + * SparkMD5 OOP implementation. + * + * Use this class to perform an incremental md5, otherwise use the + * static methods instead. + */ + SparkMD5 = function () { + // call reset to init the instance + this.reset(); + }; + + + // In some cases the fast add32 function cannot be used.. + if (md5('hello') !== '5d41402abc4b2a76b9719d911017c592') { + add32 = function (x, y) { + var lsw = (x & 0xFFFF) + (y & 0xFFFF), + msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xFFFF); + }; + } + + + /** + * Appends a string. + * A conversion will be applied if an utf8 string is detected. + * + * @param {String} str The string to be appended + * + * @return {SparkMD5} The instance itself + */ + SparkMD5.prototype.append = function (str) { + // converts the string to utf8 bytes if necessary + if (/[\u0080-\uFFFF]/.test(str)) { + str = unescape(encodeURIComponent(str)); + } + + // then append as binary + this.appendBinary(str); + + return this; + }; + + /** + * Appends a binary string. + * + * @param {String} contents The binary string to be appended + * + * @return {SparkMD5} The instance itself + */ + SparkMD5.prototype.appendBinary = function (contents) { + this._buff += contents; + this._length += contents.length; + + var length = this._buff.length, + i; + + for (i = 64; i <= length; i += 64) { + md5cycle(this._state, md5blk(this._buff.substring(i - 64, i))); + } + + this._buff = this._buff.substr(i - 64); + + return this; + }; + + /** + * Finishes the incremental computation, reseting the internal state and + * returning the result. + * Use the raw parameter to obtain the raw result instead of the hex one. + * + * @param {Boolean} raw True to get the raw result, false to get the hex result + * + * @return {String|Array} The result + */ + SparkMD5.prototype.end = function (raw) { + var buff = this._buff, + length = buff.length, + i, + tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + ret; + + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= buff.charCodeAt(i) << ((i % 4) << 3); + } + + this._finish(tail, length); + ret = !!raw ? this._state : hex(this._state); + + this.reset(); + + return ret; + }; + + /** + * Finish the final calculation based on the tail. + * + * @param {Array} tail The tail (will be modified) + * @param {Number} length The length of the remaining buffer + */ + SparkMD5.prototype._finish = function (tail, length) { + var i = length, + tmp, + lo, + hi; + + tail[i >> 2] |= 0x80 << ((i % 4) << 3); + if (i > 55) { + md5cycle(this._state, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + + // Do the final computation based on the tail and length + // Beware that the final length may not fit in 32 bits so we take care of that + tmp = this._length * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + + tail[14] = lo; + tail[15] = hi; + md5cycle(this._state, tail); + }; + + /** + * Resets the internal state of the computation. + * + * @return {SparkMD5} The instance itself + */ + SparkMD5.prototype.reset = function () { + this._buff = ""; + this._length = 0; + this._state = [1732584193, -271733879, -1732584194, 271733878]; + + return this; + }; + + /** + * Releases memory used by the incremental buffer and other aditional + * resources. If you plan to use the instance again, use reset instead. + */ + SparkMD5.prototype.destroy = function () { + delete this._state; + delete this._buff; + delete this._length; + }; + + + /** + * Performs the md5 hash on a string. + * A conversion will be applied if utf8 string is detected. + * + * @param {String} str The string + * @param {Boolean} raw True to get the raw result, false to get the hex result + * + * @return {String|Array} The result + */ + SparkMD5.hash = function (str, raw) { + // converts the string to utf8 bytes if necessary + if (/[\u0080-\uFFFF]/.test(str)) { + str = unescape(encodeURIComponent(str)); + } + + var hash = md51(str); + + return !!raw ? hash : hex(hash); + }; + + /** + * Performs the md5 hash on a binary string. + * + * @param {String} content The binary string + * @param {Boolean} raw True to get the raw result, false to get the hex result + * + * @return {String|Array} The result + */ + SparkMD5.hashBinary = function (content, raw) { + var hash = md51(content); + + return !!raw ? hash : hex(hash); + }; + + /** + * SparkMD5 OOP implementation for array buffers. + * + * Use this class to perform an incremental md5 ONLY for array buffers. + */ + SparkMD5.ArrayBuffer = function () { + // call reset to init the instance + this.reset(); + }; + + //////////////////////////////////////////////////////////////////////////// + + /** + * Appends an array buffer. + * + * @param {ArrayBuffer} arr The array to be appended + * + * @return {SparkMD5.ArrayBuffer} The instance itself + */ + SparkMD5.ArrayBuffer.prototype.append = function (arr) { + // TODO: we could avoid the concatenation here but the algorithm would be more complex + // if you find yourself needing extra performance, please make a PR. + var buff = this._concatArrayBuffer(this._buff, arr), + length = buff.length, + i; + + this._length += arr.byteLength; + + for (i = 64; i <= length; i += 64) { + md5cycle(this._state, md5blk_array(buff.subarray(i - 64, i))); + } + + // Avoids IE10 weirdness (documented above) + this._buff = (i - 64) < length ? buff.subarray(i - 64) : new Uint8Array(0); + + return this; + }; + + /** + * Finishes the incremental computation, reseting the internal state and + * returning the result. + * Use the raw parameter to obtain the raw result instead of the hex one. + * + * @param {Boolean} raw True to get the raw result, false to get the hex result + * + * @return {String|Array} The result + */ + SparkMD5.ArrayBuffer.prototype.end = function (raw) { + var buff = this._buff, + length = buff.length, + tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + i, + ret; + + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= buff[i] << ((i % 4) << 3); + } + + this._finish(tail, length); + ret = !!raw ? this._state : hex(this._state); + + this.reset(); + + return ret; + }; + + SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish; + + /** + * Resets the internal state of the computation. + * + * @return {SparkMD5.ArrayBuffer} The instance itself + */ + SparkMD5.ArrayBuffer.prototype.reset = function () { + this._buff = new Uint8Array(0); + this._length = 0; + this._state = [1732584193, -271733879, -1732584194, 271733878]; + + return this; + }; + + /** + * Releases memory used by the incremental buffer and other aditional + * resources. If you plan to use the instance again, use reset instead. + */ + SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy; + + /** + * Concats two array buffers, returning a new one. + * + * @param {ArrayBuffer} first The first array buffer + * @param {ArrayBuffer} second The second array buffer + * + * @return {ArrayBuffer} The new array buffer + */ + SparkMD5.ArrayBuffer.prototype._concatArrayBuffer = function (first, second) { + var firstLength = first.length, + result = new Uint8Array(firstLength + second.byteLength); + + result.set(first); + result.set(new Uint8Array(second), firstLength); + + return result; + }; + + /** + * Performs the md5 hash on an array buffer. + * + * @param {ArrayBuffer} arr The array buffer + * @param {Boolean} raw True to get the raw result, false to get the hex result + * + * @return {String|Array} The result + */ + SparkMD5.ArrayBuffer.hash = function (arr, raw) { + var hash = md51_array(new Uint8Array(arr)); + + return !!raw ? hash : hex(hash); + }; + + return SparkMD5; +})); + +},{}],118:[function(_dereq_,module,exports){ +module.exports=_dereq_(26) +},{"./_stream_readable":119,"./_stream_writable":121,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_duplex.js":26,"_process":24,"core-util-is":122,"inherits":44}],119:[function(_dereq_,module,exports){ +module.exports=_dereq_(28) +},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_readable.js":28,"_process":24,"buffer":17,"core-util-is":122,"events":21,"inherits":44,"isarray":123,"stream":36,"string_decoder/":124}],120:[function(_dereq_,module,exports){ +module.exports=_dereq_(29) +},{"./_stream_duplex":118,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_transform.js":29,"core-util-is":122,"inherits":44}],121:[function(_dereq_,module,exports){ +module.exports=_dereq_(30) +},{"./_stream_duplex":118,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_writable.js":30,"_process":24,"buffer":17,"core-util-is":122,"inherits":44,"stream":36}],122:[function(_dereq_,module,exports){ +module.exports=_dereq_(31) +},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/node_modules/core-util-is/lib/util.js":31,"buffer":17}],123:[function(_dereq_,module,exports){ +module.exports=_dereq_(22) +},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/isarray/index.js":22}],124:[function(_dereq_,module,exports){ +module.exports=_dereq_(37) +},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/string_decoder/index.js":37,"buffer":17}],125:[function(_dereq_,module,exports){ +module.exports=_dereq_(34) +},{"./lib/_stream_transform.js":120,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/transform.js":34}],126:[function(_dereq_,module,exports){ +module.exports=_dereq_(54) +},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/has-keys.js":54}],127:[function(_dereq_,module,exports){ +module.exports=_dereq_(55) +},{"./has-keys":126,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/index.js":55,"object-keys":129}],128:[function(_dereq_,module,exports){ +module.exports=_dereq_(56) +},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/foreach.js":56}],129:[function(_dereq_,module,exports){ +module.exports=_dereq_(57) +},{"./shim":131,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/index.js":57}],130:[function(_dereq_,module,exports){ +module.exports=_dereq_(58) +},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/isArguments.js":58}],131:[function(_dereq_,module,exports){ +module.exports=_dereq_(59) +},{"./foreach":128,"./isArguments":130,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/shim.js":59}],132:[function(_dereq_,module,exports){ +var Transform = _dereq_('readable-stream/transform') + , inherits = _dereq_('util').inherits + , xtend = _dereq_('xtend') + + +// a noop _transform function +function noop (chunk, enc, callback) { + callback(null, chunk) +} + + +// create a new export function, used by both the main export and +// the .ctor export, contains common logic for dealing with arguments +function through2 (construct) { + return function (options, transform, flush) { + if (typeof options == 'function') { + flush = transform + transform = options + options = {} + } + + if (typeof transform != 'function') + transform = noop + + if (typeof flush != 'function') + flush = null + + return construct(options, transform, flush) + } +} + + +// main export, just make me a transform stream! +module.exports = through2(function (options, transform, flush) { + var t2 = new Transform(options) + + t2._transform = transform + + if (flush) + t2._flush = flush + + return t2 +}) + + +// make me a reusable prototype that I can `new`, or implicitly `new` +// with a constructor call +module.exports.ctor = through2(function (options, transform, flush) { + function Through2 (override) { + if (!(this instanceof Through2)) + return new Through2(override) + + this.options = xtend(options, override) + + Transform.call(this, this.options) + } + + inherits(Through2, Transform) + + Through2.prototype._transform = transform + + if (flush) + Through2.prototype._flush = flush + + return Through2 +}) + + +module.exports.obj = through2(function (options, transform, flush) { + var t2 = new Transform(xtend({ objectMode: true }, options)) + + t2._transform = transform + + if (flush) + t2._flush = flush + + return t2 +}) + +},{"readable-stream/transform":125,"util":39,"xtend":127}],133:[function(_dereq_,module,exports){ +'use strict'; + +/** + * Stringify/parse functions that don't operate + * recursively, so they avoid call stack exceeded + * errors. + */ +exports.stringify = function stringify(input) { + var queue = []; + queue.push({obj: input}); + + var res = ''; + var next, obj, prefix, val, i, arrayPrefix, keys, k, key, value, objPrefix; + while ((next = queue.pop())) { + obj = next.obj; + prefix = next.prefix || ''; + val = next.val || ''; + res += prefix; + if (val) { + res += val; + } else if (typeof obj !== 'object') { + res += typeof obj === 'undefined' ? null : JSON.stringify(obj); + } else if (obj === null) { + res += 'null'; + } else if (Array.isArray(obj)) { + queue.push({val: ']'}); + for (i = obj.length - 1; i >= 0; i--) { + arrayPrefix = i === 0 ? '' : ','; + queue.push({obj: obj[i], prefix: arrayPrefix}); + } + queue.push({val: '['}); + } else { // object + keys = []; + for (k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + queue.push({val: '}'}); + for (i = keys.length - 1; i >= 0; i--) { + key = keys[i]; + value = obj[key]; + objPrefix = (i > 0 ? ',' : ''); + objPrefix += JSON.stringify(key) + ':'; + queue.push({obj: value, prefix: objPrefix}); + } + queue.push({val: '{'}); + } + } + return res; +}; + +// Convenience function for the parse function. +// This pop function is basically copied from +// pouchCollate.parseIndexableString +function pop(obj, stack, metaStack) { + var lastMetaElement = metaStack[metaStack.length - 1]; + if (obj === lastMetaElement.element) { + // popping a meta-element, e.g. an object whose value is another object + metaStack.pop(); + lastMetaElement = metaStack[metaStack.length - 1]; + } + var element = lastMetaElement.element; + var lastElementIndex = lastMetaElement.index; + if (Array.isArray(element)) { + element.push(obj); + } else if (lastElementIndex === stack.length - 2) { // obj with key+value + var key = stack.pop(); + element[key] = obj; + } else { + stack.push(obj); // obj with key only + } +} + +exports.parse = function (str) { + var stack = []; + var metaStack = []; // stack for arrays and objects + var i = 0; + var collationIndex,parsedNum,numChar; + var parsedString,lastCh,numConsecutiveSlashes,ch; + var arrayElement, objElement; + while (true) { + collationIndex = str[i++]; + if (collationIndex === '}' || + collationIndex === ']' || + typeof collationIndex === 'undefined') { + if (stack.length === 1) { + return stack.pop(); + } else { + pop(stack.pop(), stack, metaStack); + continue; + } + } + switch (collationIndex) { + case ' ': + case '\t': + case '\n': + case ':': + case ',': + break; + case 'n': + i += 3; // 'ull' + pop(null, stack, metaStack); + break; + case 't': + i += 3; // 'rue' + pop(true, stack, metaStack); + break; + case 'f': + i += 4; // 'alse' + pop(false, stack, metaStack); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + parsedNum = ''; + i--; + while (true) { + numChar = str[i++]; + if (/[\d\.\-e\+]/.test(numChar)) { + parsedNum += numChar; + } else { + i--; + break; + } + } + pop(parseFloat(parsedNum), stack, metaStack); + break; + case '"': + parsedString = ''; + lastCh = void 0; + numConsecutiveSlashes = 0; + while (true) { + ch = str[i++]; + if (ch !== '"' || (lastCh === '\\' && + numConsecutiveSlashes % 2 === 1)) { + parsedString += ch; + lastCh = ch; + if (lastCh === '\\') { + numConsecutiveSlashes++; + } else { + numConsecutiveSlashes = 0; + } + } else { + break; + } + } + pop(JSON.parse('"' + parsedString + '"'), stack, metaStack); + break; + case '[': + arrayElement = { element: [], index: stack.length }; + stack.push(arrayElement.element); + metaStack.push(arrayElement); + break; + case '{': + objElement = { element: {}, index: stack.length }; + stack.push(objElement.element); + metaStack.push(objElement); + break; + default: + throw new Error( + 'unexpectedly reached end of input: ' + collationIndex); + } + } +}; + +},{}],"adapter-config":[function(_dereq_,module,exports){ +(function (global){ +'use strict'; + +module.exports = { + name: 'localstorage', + valid: function () { + return 'localStorage' in global; + }, + use_prefix: true +}; +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],"leveldown":[function(_dereq_,module,exports){ +(function (Buffer){ +module.exports = Level + +var IDB = _dereq_('idb-wrapper') +var AbstractLevelDOWN = _dereq_('abstract-leveldown').AbstractLevelDOWN +var util = _dereq_('util') +var Iterator = _dereq_('./iterator') +var isBuffer = _dereq_('isbuffer') +var xtend = _dereq_('xtend') +var toBuffer = _dereq_('typedarray-to-buffer') + +function Level(location) { + if (!(this instanceof Level)) return new Level(location) + if (!location) throw new Error("constructor requires at least a location argument") + this.IDBOptions = {} + this.location = location +} + +util.inherits(Level, AbstractLevelDOWN) + +Level.prototype._open = function(options, callback) { + var self = this + + var idbOpts = { + storeName: this.location, + autoIncrement: false, + keyPath: null, + onStoreReady: function () { + callback && callback(null, self.idb) + }, + onError: function(err) { + callback && callback(err) + } + } + + xtend(idbOpts, options) + this.IDBOptions = idbOpts + this.idb = new IDB(idbOpts) +} + +Level.prototype._get = function (key, options, callback) { + this.idb.get(key, function (value) { + if (value === undefined) { + // 'NotFound' error, consistent with LevelDOWN API + return callback(new Error('NotFound')) + } + // by default return buffers, unless explicitly told not to + var asBuffer = true + if (options.asBuffer === false) asBuffer = false + if (options.raw) asBuffer = false + if (asBuffer) { + if (value instanceof Uint8Array) value = toBuffer(value) + else value = new Buffer(String(value)) + } + return callback(null, value, key) + }, callback) +} + +Level.prototype._del = function(id, options, callback) { + this.idb.remove(id, callback, callback) +} + +Level.prototype._put = function (key, value, options, callback) { + if (value instanceof ArrayBuffer) { + value = toBuffer(new Uint8Array(value)) + } + var obj = this.convertEncoding(key, value, options) + if (Buffer.isBuffer(obj.value)) { + obj.value = new Uint8Array(value.toArrayBuffer()) + } + this.idb.put(obj.key, obj.value, function() { callback() }, callback) +} + +Level.prototype.convertEncoding = function(key, value, options) { + if (options.raw) return {key: key, value: value} + if (value) { + var stringed = value.toString() + if (stringed === 'NaN') value = 'NaN' + } + var valEnc = options.valueEncoding + var obj = {key: key, value: value} + if (value && (!valEnc || valEnc !== 'binary')) { + if (typeof obj.value !== 'object') { + obj.value = stringed + } + } + return obj +} + +Level.prototype.iterator = function (options) { + if (typeof options !== 'object') options = {} + return new Iterator(this.idb, options) +} + +Level.prototype._batch = function (array, options, callback) { + var op + var i + var k + var copiedOp + var currentOp + var modified = [] + + if (array.length === 0) return setTimeout(callback, 0) + + for (i = 0; i < array.length; i++) { + copiedOp = {} + currentOp = array[i] + modified[i] = copiedOp + + var converted = this.convertEncoding(currentOp.key, currentOp.value, options) + currentOp.key = converted.key + currentOp.value = converted.value + + for (k in currentOp) { + if (k === 'type' && currentOp[k] == 'del') { + copiedOp[k] = 'remove' + } else { + copiedOp[k] = currentOp[k] + } + } + } + + return this.idb.batch(modified, function(){ callback() }, callback) +} + +Level.prototype._close = function (callback) { + this.idb.db.close() + callback() +} + +Level.prototype._approximateSize = function (start, end, callback) { + var err = new Error('Not implemented') + if (callback) + return callback(err) + + throw err +} + +Level.prototype._isBuffer = function (obj) { + return Buffer.isBuffer(obj) +} + +Level.destroy = function (db, callback) { + if (typeof db === 'object') { + var prefix = db.IDBOptions.storePrefix || 'IDBWrapper-' + var dbname = db.location + } else { + var prefix = 'IDBWrapper-' + var dbname = db + } + var request = indexedDB.deleteDatabase(prefix + dbname) + request.onsuccess = function() { + callback() + } + request.onerror = function(err) { + callback(err) + } +} + +var checkKeyValue = Level.prototype._checkKeyValue = function (obj, type) { + if (obj === null || obj === undefined) + return new Error(type + ' cannot be `null` or `undefined`') + if (obj === null || obj === undefined) + return new Error(type + ' cannot be `null` or `undefined`') + if (isBuffer(obj) && obj.byteLength === 0) + return new Error(type + ' cannot be an empty ArrayBuffer') + if (String(obj) === '') + return new Error(type + ' cannot be an empty String') + if (obj.length === 0) + return new Error(type + ' cannot be an empty Array') +} + +}).call(this,_dereq_("buffer").Buffer) +},{"./iterator":45,"abstract-leveldown":48,"buffer":17,"idb-wrapper":50,"isbuffer":51,"typedarray-to-buffer":53,"util":39,"xtend":55}]},{},[11]); +
diff --git a/dist/pouchdb.localstorage.min.js b/dist/pouchdb.localstorage.min.js new file mode 100644 index 0000000..147896b --- /dev/null +++ b/dist/pouchdb.localstorage.min.js
@@ -0,0 +1,13 @@ +// PouchDB localStorage plugin 3.2.0 +// Based on localstorage-down: https://github.com/No9/localstorage-down +// +// (c) 2012-2014 Dale Harvey and the PouchDB team +// PouchDB may be freely distributed under the Apache license, version 2.0. +// For all details and documentation: +// http://pouchdb.com +require=function e(t,r,n){function o(s,a){if(!r[s]){if(!t[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(i)return i(s,!0);var c=new Error("Cannot find module '"+s+"'");throw c.code="MODULE_NOT_FOUND",c}var f=r[s]={exports:{}};t[s][0].call(f.exports,function(e){var r=t[s][1][e];return o(r?r:e)},f,f.exports,e,t,r,n)}return r[s].exports}for(var i="function"==typeof require&&require,s=0;s<n.length;s++)o(n[s]);return o}({"./lib/deps/migrate":[function(e,t,r){(function(e){"use strict";r.toSublevel=function(t,r,n){e.nextTick(function(){n()})},r.localAndMetaStores=function(t,r,n){e.nextTick(function(){n()})}}).call(this,e("_process"))},{_process:24}],1:[function(e,t){(function(r,n){"use strict";function o(e,t){return h.Promise.all(e.map(function(e){if(e.doc&&e.doc._attachments){var r=Object.keys(e.doc._attachments);return h.Promise.all(r.map(function(r){var n=e.doc._attachments[r];if(!("data"in n))return new h.Promise(function(o,i){t.binaryStore.get(n.digest,function(t,s){var a="";return t&&"NotFoundError"!==t.name?i(t):(t||(a=h.btoa(s)),e.doc._attachments[r]=h.extend(h.pick(n,["digest","content_type"]),{data:a}),void o())})})}))}}))}function i(e){var t=h.filterChange(e),r=e.doc_ids&&new h.Set(e.doc_ids);return function(e){return r&&!r.has(e.id)?!1:t(e)}}function s(e,t){function v(){q.docStore=U.sublevel(g,{valueEncoding:R}),q.bySeqStore=U.sublevel(m,{valueEncoding:"json"}),q.attachmentStore=U.sublevel(b,{valueEncoding:"json"}),q.binaryStore=U.sublevel(_,{valueEncoding:"binary"}),q.localStore=U.sublevel(w,{valueEncoding:"json"}),q.metaStore=U.sublevel(E,{valueEncoding:"json"}),p.localAndMetaStores(U,q,function(){q.metaStore.get(S,function(e,n){"undefined"==typeof U._updateSeq&&(U._updateSeq=n||0),q.metaStore.get(A,function(e,n){U._docCountQueue.docCount=e?0:n,I(function(e){e&&M.emit("error",e),q.metaStore.get(j,function(e,n){P=e?h.uuid():n,q.metaStore.put(j,P,function(){r.nextTick(function(){t(null,M)})})})})})})})}function I(e){return U._docCountQueue.running||!U._docCountQueue.queue.length||-1===U._docCountQueue.docCount?T(0,e):U._docCountQueue.docCount}function N(){if(!U._docCountQueue.running&&U._docCountQueue.queue.length&&-1!==U._docCountQueue.docCount){U._docCountQueue.running=!0;var e=U._docCountQueue.queue.shift();return U.isClosed()?e.callback(new Error("database is closed")):void q.metaStore.get(A,function(t,r){function n(t){U._docCountQueue.docCount=r,e.callback(t,r),U._docCountQueue.running=!1,N()}r=t?0:r,0===e.delta?n():q.metaStore.put(A,r+e.delta,n)})}}function T(e,t){U._docCountQueue.queue.push({delta:e,callback:t}),N()}function L(e){return h.getArguments(function(t){var n=t[t.length-1];t[t.length-1]=h.getArguments(function(e){n.apply(null,e),r.nextTick(function(){U._writeQueue.shift(),U._writeQueue.length&&U._writeQueue.peekFront()()})}),U._writeQueue.push(function(){e.apply(null,t)}),1===U._writeQueue.length&&U._writeQueue.peekFront()()})}function D(e){return("0000000000000000"+e).slice(-16)}function B(e){return parseInt(e,10)}function C(e,t){var r=e.data;if(r._id=e.metadata.id,"_rev"in r){if(r._rev!==e.metadata.rev)return t(new Error("wrong doc returned"))}else r._rev=e.metadata.rev;t(null,{doc:r,metadata:e.metadata})}e=h.clone(e);var P,U,M=this,q={},F=e.name;"undefined"==typeof e.createIfMissing&&(e.createIfMissing=!0);var V=e.db||u;"function"!=typeof V.destroy&&(V.destroy=function(e,t){t()});var W;k.has(V.name)?W=k.get(V.name):(W=new h.Map,k.set(V.name,W)),W.has(F)?(U=W.get(F),v()):W.set(F,c(a(F,e,function(r){return r?(W["delete"](F),t(r)):(U=W.get(F),U._docCountQueue={queue:[],running:!1,docCount:-1},U._writeQueue=new y,void(e.db||e.noMigrate?v():p.toSublevel(F,U,v)))}))),M.type=function(){return"leveldb"},M._id=function(e){e(null,P)},M._info=function(e){I(function(t,r){return t?e(t):void q.metaStore.get(S,function(t,n){return t&&(n=U._updateSeq),e(null,{doc_count:r,update_seq:n})})})},M._get=function(e,t,r){function n(e){o.push(e)}t=h.clone(t);var o=[];U.on("pouchdb-id-"+e,n),q.docStore.get(e,function(i,s){function a(e){u=e}if(U.removeListener("pouchdb-id-"+e,n),i||!s)return r(l.MISSING_DOC);if(h.isDeleted(s)&&!t.rev)return r(l.error(l.MISSING_DOC,"deleted"));var u,c=d.winningRev(s);c=t.rev?t.rev:c;var f=s.rev_map[c],p=o.filter(function(e){return e.metadata.seq===f});return p.length?C(p.pop(),r):(U.on("pouchdb-"+f,a),void q.bySeqStore.get(D(f),function(e,t){if(U.removeListener("pouchdb-"+f,a),u)return C(u,r);if(!t)return r(l.MISSING_DOC);if("_id"in t&&t._id!==s.id)return r(new Error("wrong doc returned"));if(t._id=s.id,"_rev"in t){if(t._rev!==c)return r(new Error("wrong doc returned"))}else t._rev=c;return r(null,{doc:t,metadata:s})}))})},M._getAttachment=function(e,t,o){var i=e.digest;q.binaryStore.get(i,function(i,s){var a;return i&&"NotFoundError"===i.name?(a=t.encode?"":r.browser?h.createBlob([""],{type:e.content_type}):new n(""),o(null,a)):i?o(i):(a=r.browser?t.encode?h.btoa(s):h.createBlob([h.fixBinary(s)],{type:e.content_type}):t.encode?h.btoa(s):s,void o(null,a))})},M._bulkDocs=L(function(e,t,n){function o(e,t){q.attachmentStore.get(e,function(r){if(r){var n=new Error("unknown stub attachment with digest "+e);n.status=412,t(n)}else t()})}function i(e){function t(){++i===r.length&&e(n)}var r=[];if(_.forEach(function(e){e&&e._attachments&&Object.keys(e._attachments).forEach(function(t){var n=e._attachments[t];n.stub&&r.push(n.digest)})}),!r.length)return e();var n,i=0;r.forEach(function(e){o(e,function(e){e&&!n&&(n=e),t()})})}function a(){var e=E;if(!(A>x)){if(e>=w.length)return 0===A?y():void 0;var t=w[e];if(E++,A++,t._id&&h.isLocalId(t._id))return void M[t._deleted?"_removeLocalNoLock":"_putLocalNoLock"](t,function(t){m[e]=t?t:{},A--,a()});if(b.has(t.metadata.id))return m[e]=l.REV_CONFLICT,A--,a();b.add(t.metadata.id),q.docStore.get(t.metadata.id,function(r,n){r?"NotFoundError"===r.name?u(t,e,function(){b["delete"](t.metadata.id),A--,a()}):(r.error=!0,m[e]=r,b["delete"](t.metadata.id),A--,a()):c(n,t,e,function(){b["delete"](t.metadata.id),A--,a()})}),g&&a()}}function u(e,r,n){return"was_delete"in t&&h.isDeleted(e.metadata)?(m[r]=l.MISSING_DOC,n()):void f(e,r,function(t){return t?n(t):h.isDeleted(e.metadata)?n():void T(1,n)})}function c(e,t,r,n){if(h.revExists(e,t.metadata.rev))return m[r]=t,void n();var o=h.isDeleted(e),i=h.isDeleted(t.metadata),s=/^1-/.test(t.metadata.rev);if(o&&!i&&g&&s){var a=t.data;a._rev=e.rev,a._id=t.metadata.id,t=h.parseDoc(a,g)}var u=d.merge(e.rev_tree,t.metadata.rev_tree[0],1e3),c=g&&(o&&i||!o&&g&&"new_leaf"!==u.conflicts||o&&!i&&"new_branch"===u.conflicts);if(c)return m[r]=l.REV_CONFLICT,n();var p=t.metadata.rev;t.metadata.rev_tree=u.tree,t.metadata.rev_map=e.rev_map;var v=0;(g||d.winningRev(t.metadata)===p)&&(v=o===i?0:i>o?-1:1),T(v,function(e){return e?n(e):void f(t,r,n)})}function f(e,t,o){function i(e){f||(e?(f=e,o(f)):d===y.length&&c())}function s(e){d++,i(e)}function a(e,t,r,n){return function(o){v(e,O+o,t,r,n)}}function u(e,t,r){return function(n){h.MD5(n).then(a(e,t,n,r))}}function c(){var r=e.metadata.rev_map[e.metadata.rev];r||(r=++U._updateSeq),e.metadata.rev_map[e.metadata.rev]=e.metadata.seq=r;var n=D(r);U.emit("pouchdb-id-"+e.metadata.id,e),U.emit("pouchdb-"+n,e),U.batch([{key:n,value:e.data,prefix:q.bySeqStore,type:"put",valueEncoding:"json"},{key:e.metadata.id,value:e.metadata,prefix:q.docStore,type:"put",valueEncoding:R}],function(r){return r||(U.emit("pouchdb-id-"+e.metadata.id,e),U.emit("pouchdb-"+n,e)),q.metaStore.put(S,U._updateSeq,function(r){return m[t]=r?r:e,o()})})}var f=null,d=0;e.data._id=e.metadata.id,e.data._rev=e.metadata.rev,h.isDeleted(e.metadata)&&(e.data._deleted=!0);for(var y=e.data._attachments?Object.keys(e.data._attachments):[],g=0;g<y.length;g++){var b=y[g],_=e.data._attachments[b];if(_.stub){var w=e.data._id,E=e.data._rev;p(w,E,_.digest,s)}else{var x;if("string"==typeof _.data)try{x=h.atob(_.data)}catch(k){return void n(h.extend({},l.BAD_ARG,{reason:"Attachments need to be base64 encoded"}))}else{if(r.browser){h.readAsBinaryString(_.data,u(e,b,s));continue}x=_.data}h.MD5(x).then(a(e,b,x,s))}}y.length||c()}function p(e,t,r,n){function o(){return new h.Promise(function(e,t){q.attachmentStore.get(r,function(r,n){return r&&"NotFoundError"!==r.name?t(r):void e(n)})})}function i(n){var o=[e,t].join("@"),i={};return n?n.refs&&(i.refs=n.refs,i.refs[o]=!0):(i.refs={},i.refs[o]=!0),new h.Promise(function(e,t){q.attachmentStore.put(r,i,function(r){return r?t(r):void e(!n)})})}var s=j[r]||h.Promise.resolve();j[r]=s.then(function(){return o().then(i).then(function(e){n(null,e)},n)})}function v(e,t,r,n,o){var i=e.data._attachments[r];delete i.data,i.digest=t,i.length=n.length;var s=e.metadata.id,a=e.metadata.rev;p(s,a,t,function(e,r){return e?o(e):0===n.length?o(e):r?void q.binaryStore.put(t,n,function(e){o(e)}):o(e)})}function y(){var e=m.map(function(e){if(!Object.keys(e).length)return{ok:!0};if(e.error)return e;var t=e.metadata,r=d.winningRev(t);return{ok:!0,id:t.id,rev:r}});s.Changes.notify(F),r.nextTick(function(){n(null,e)})}var g=t.new_edits,m=new Array(e.docs.length),b=new h.Set,_=e.docs,w=_.map(function(e){if(e._id&&h.isLocalId(e._id))return e;var t=h.parseDoc(e,g);return t.metadata&&!t.metadata.rev_map&&(t.metadata.rev_map={}),t}),E=0,k=w.filter(function(e){return e.error});if(k.length)return n(k[0]);var A=0,j={};i(function(e){return e?n(e):void a()})}),M._allDocs=function(e,t){e=h.clone(e),I(function(r,n){if(r)return t(r);var i={},s=e.skip||0;if(e.startkey&&(i.start=e.startkey),e.endkey&&(i.end=e.endkey),e.key&&(i.start=i.end=e.key),e.descending){i.reverse=!0;var a=i.start;i.start=i.end,i.end=a}var u;if(u="number"==typeof e.limit?e.limit:-1,0===u||"start"in i&&"end"in i&&i.start>i.end)return t(null,{total_rows:n,offset:e.skip,rows:[]});var c=[],l=q.docStore.readStream(i),p=f(function(t,r,n){function o(t,r){var o={id:t.id,key:t.id,value:{rev:d.winningRev(t)}};if(e.include_docs){o.doc=r,o.doc._rev=o.value.rev,e.conflicts&&(o.doc._conflicts=d.collectConflicts(t));for(var i in o.doc._attachments)o.doc._attachments.hasOwnProperty(i)&&(o.doc._attachments[i].stub=!0)}if(e.inclusive_end===!1&&t.id===e.endkey)return n();if(h.isDeleted(t)){if("ok"!==e.deleted)return n();o.value.deleted=!0,o.doc=null}c.push(o),n()}if(h.isDeleted(t.value)){if("ok"!==e.deleted)return void n()}else{if(s-->0)return void n();if(0===u--)return l.unpipe(),l.destroy(),void n()}var i=t.value;if(e.include_docs){var a=i.rev_map[d.winningRev(i)];q.bySeqStore.get(D(a),function(e,t){o(i,t)})}else o(i)},function(r){h.Promise.resolve().then(function(){return e.attachments&&o(c,q)}).then(function(){t(null,{total_rows:n,offset:e.skip,rows:c})},t),r()}).on("unpipe",function(){p.end()});l.on("error",t),l.pipe(p)})},M._changes=function(e){function t(){e.done=!0,v&&e.limit&&e.limit<u.length&&(u.length=e.limit),g.unpipe(m),g.destroy(),e.continuous||e.cancelled||h.Promise.resolve().then(function(){return e.include_docs&&e.attachments?o(u,q):void 0}).then(function(){e.complete(null,{results:u,last_seq:c})})}if(e=h.clone(e),e.continuous){var r=F+":"+h.uuid();return s.Changes.addListener(F,r,M,e),s.Changes.notify(F),{cancel:function(){s.Changes.removeListener(F,r)}}}var n,a=e.descending,u=[],c=0,l=0,p={reverse:a};"limit"in e&&e.limit>0&&(n=e.limit),p.reverse||(p.start=D(e.since?e.since+1:0));var v,y=i(e);v="returnDocs"in e?e.returnDocs:!0;var g=q.bySeqStore.readStream(p),m=f(function(r,i,s){return n&&l>=n?(t(),s()):e.cancelled||e.done?s():void q.docStore.get(r.value._id,function(t,n){if(e.cancelled||e.done||U.isClosed()||h.isLocalId(n.id))return s();var i=r.value;i._rev=d.winningRev(n);var a=e.processChange(i,n,e);a.seq=n.seq,c<n.seq&&(c=n.seq),B(r.key)===n.rev_map[a.doc._rev]&&y(a)&&(l++,e.attachments&&e.include_docs?o([a],q).then(function(){e.onChange(a)}):e.onChange(a),v&&u.push(a)),s()})},function(t){return e.cancelled?t():(v&&e.limit&&e.limit<u.length&&(u.length=e.limit),void t())}).on("unpipe",function(){m.end(),t()});return g.pipe(m),{cancel:function(){e.cancelled=!0,t()}}},M._close=function(e){return U.isClosed()?e(l.NOT_OPEN):void U.close(function(t){t?e(t):(W["delete"](F),e())})},M._getRevisionTree=function(e,t){q.docStore.get(e,function(e,r){e?t(l.MISSING_DOC):t(null,r.rev_tree)})},M._doCompaction=L(function(e,t,r){return t.length?void q.docStore.get(e,function(n,o){function i(e){if(e&&(f=e),++p===t.length){if(f)return r(e);a()}}function s(e){return e?r(e):void U.batch(c,r)}function a(){function r(e){e&&(o=e),++i===n.length&&s(o)}var n=Object.keys(l);if(!n.length)return s();var o,i=0,a=new h.Map;t.forEach(function(t){a.set(e+"@"+t,!0)}),n.forEach(function(e){q.attachmentStore.get(e,function(t,n){if(t)return"NotFoundError"===t.name?r():r(t);var o=Object.keys(n.refs||{}).filter(function(e){return!a.has(e)}),i={};o.forEach(function(e){i[e]=!0}),o.length?c.push({key:e,type:"put",valueEncoding:"json",value:{refs:i},prefix:q.attachmentStore}):c=c.concat([{key:e,type:"del",prefix:q.attachmentStore},{key:e,type:"del",prefix:q.binaryStore}]),r()})})}if(n)return r(n);var u=o.rev_map;d.traverseRevTree(o.rev_tree,function(e,r,n,o,i){var s=r+"-"+n;-1!==t.indexOf(s)&&(i.status="missing")});var c=[];c.push({key:o.id,value:o,type:"put",valueEncoding:R,prefix:q.docStore});var f,l={},p=0;t.forEach(function(e){var t=u[e];t&&(c.push({key:D(t),type:"del",prefix:q.bySeqStore}),q.bySeqStore.get(D(t),function(e,t){if(e)return"NotFoundError"===e.name?i():i(e);var r=Object.keys(t._attachments||{});r.forEach(function(e){var r=t._attachments[e].digest;l[r]=!0}),i()}))})}):r()}),M._getLocal=function(e,t){q.localStore.get(e,function(e,r){e?t(l.MISSING_DOC):t(null,r)})},M._putLocal=L(function(e,t){M._putLocalNoLock(e,t)}),M._putLocalNoLock=function(e,t){delete e._revisions;var r=e._rev,n=e._id;q.localStore.get(n,function(o,i){return o&&r?t(l.REV_CONFLICT):i&&i._rev!==r?t(l.REV_CONFLICT):(e._rev=r?"0-"+(parseInt(r.split("-")[1],10)+1):"0-1",void q.localStore.put(n,e,function(r){if(r)return t(r);var n={ok:!0,id:e._id,rev:e._rev};t(null,n)}))})},M._removeLocal=L(function(e,t){M._removeLocalNoLock(e,t)}),M._removeLocalNoLock=function(e,t){q.localStore.get(e._id,function(r,n){return r?t(r):n._rev!==e._rev?t(l.REV_CONFLICT):void q.localStore.del(e._id,function(r){if(r)return t(r);var n={ok:!0,id:e._id,rev:"0-0"};t(null,n)})})}}var a=e("levelup"),u=e("leveldown"),c=e("level-sublevel"),f=e("through2").obj,l=e("../deps/errors"),d=e("../merge"),h=e("../utils"),p=e("../deps/migrate"),v=e("vuvuzela"),y=e("double-ended-queue"),g="document-store",m="by-sequence",b="attach-store",_="attach-binary-store",w="local-store",E="meta-store",x=50,k=new h.Map,S="_local_last_update_seq",A="_local_doc_count",j="_local_uuid",O="md5-",R={encode:v.stringify,decode:v.parse,buffer:!1,type:"cheap-json"};s.valid=function(){return r&&!r.browser},s.destroy=h.toPromise(function(e,t,n){function o(e,t){"function"==typeof a.destroy?a.destroy(e,t):r.nextTick(n)}t=h.clone(t);var i,a=t.db||u;return k.has(a.name)?(i=k.get(a.name),void(i.has(e)?(s.Changes.removeAllListeners(e),i.get(e).close(function(){i["delete"](e),o(e,n)})):o(e,n))):o(e,n)}),s.use_prefix=!1,s.Changes=new h.Changes,t.exports=s}).call(this,e("_process"),e("buffer").Buffer)},{"../deps/errors":5,"../deps/migrate":7,"../merge":10,"../utils":13,_process:24,buffer:17,"double-ended-queue":43,"level-sublevel":61,leveldown:"leveldown",levelup:75,through2:132,vuvuzela:133}],2:[function(e,t){"use strict";function r(e,t){function r(t,r,n){if(e.binary||e.json||!e.processData||"string"==typeof t){if(!e.binary&&e.json&&"string"==typeof t)try{t=JSON.parse(t)}catch(o){return n(o)}}else t=JSON.stringify(t);Array.isArray(t)&&(t=t.map(function(e){var t;return e.ok?e:e.error&&"conflict"===e.error?(t=i.REV_CONFLICT,t.id=e.id,t):e.error&&"forbidden"===e.error?(t=i.FORBIDDEN,t.id=e.id,t.reason=e.reason,t):e.missing?(t=i.MISSING_DOC,t.missing=e.missing,t):e})),n(null,t,r)}function a(e,t){var r,n,o,s;try{r=JSON.parse(e.responseText);for(s in i)if(i.hasOwnProperty(s)&&i[s].name===r.error){o=i[s];break}o||(o=i.UNKNOWN_ERROR,e.status&&(o.status=e.status),e.statusText&&(e.name=e.statusText)),n=i.error(o,r.reason)}catch(a){for(var s in i)if(i.hasOwnProperty(s)&&i[s].status===e.status){o=i[s];break}o||(o=i.UNKNOWN_ERROR,e.status&&(o.status=e.status),e.statusText&&(e.name=e.statusText)),n=i.error(o)}e.withCredentials&&0===e.status&&(n.status=405,n.statusText="Method Not Allowed"),t(n)}var u=!1,c=s.getArguments(function(e){u||(t.apply(this,e),u=!0)});"function"==typeof e&&(c=e,e={}),e=s.clone(e);var f={method:"GET",headers:{},json:!0,processData:!0,timeout:1e4,cache:!1};if(e=s.extend(!0,f,e),"GET"===e.method&&!e.cache){var l=-1!==e.url.indexOf("?");e.url+=(l?"&":"?")+"_nonce="+s.uuid(16)}var d,h;h=e.xhr?new e.xhr:new XMLHttpRequest,h.open(e.method,e.url),h.withCredentials=!0,e.json&&(e.headers.Accept="application/json",e.headers["Content-Type"]=e.headers["Content-Type"]||"application/json",e.body&&e.processData&&"string"!=typeof e.body&&(e.body=JSON.stringify(e.body))),e.binary&&(h.responseType="arraybuffer");var p=function(e,t,r){var n="";if(r){var o=new Date;o.setTime(o.getTime()+24*r*60*60*1e3),n="; expires="+o.toGMTString()}document.cookie=e+"="+t+n+"; path=/"};for(var v in e.headers)if("Cookie"===v){var y=e.headers[v].split("=");p(y[0],y[1],10)}else h.setRequestHeader(v,e.headers[v]);"body"in e||(e.body=null);var g=function(){u||(h.abort(),a(h,c))};return h.onreadystatechange=function(){if(4===h.readyState&&!u)if(clearTimeout(d),h.status>=200&&h.status<300){var t;t=e.binary?o([h.response||""],{type:h.getResponseHeader("Content-Type")}):h.responseText,r(t,h,c)}else a(h,c)},e.timeout>0&&(d=setTimeout(g,e.timeout),h.onprogress=function(){clearTimeout(d),d=setTimeout(g,e.timeout)},"undefined"==typeof n&&(n=-1!==Object.keys(h).indexOf("upload")),n&&(h.upload.onprogress=h.onprogress)),e.body&&e.body instanceof Blob?s.readAsBinaryString(e.body,function(e){h.send(s.fixBinary(e))}):h.send(e.body),{abort:g}}var n,o=e("./blob.js"),i=e("./errors"),s=e("../utils");t.exports=r},{"../utils":13,"./blob.js":3,"./errors":5}],3:[function(e,t){(function(e){"use strict";function r(t,r){t=t||[],r=r||{};try{return new Blob(t,r)}catch(n){if("TypeError"!==n.name)throw n;for(var o=e.BlobBuilder||e.MSBlobBuilder||e.MozBlobBuilder||e.WebKitBlobBuilder,i=new o,s=0;s<t.length;s+=1)i.append(t[s]);return i.getBlob(r.type)}}t.exports=r}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],4:[function(e,t,r){"use strict";function n(){this.store={}}function o(e){if(this.store=new n,e&&Array.isArray(e))for(var t=0,r=e.length;r>t;t++)this.add(e[t])}r.Map=n,r.Set=o,n.prototype.mangle=function(e){if("string"!=typeof e)throw new TypeError("key must be a string but Got "+e);return"$"+e},n.prototype.unmangle=function(e){return e.substring(1)},n.prototype.get=function(e){var t=this.mangle(e);return t in this.store?this.store[t]:void 0},n.prototype.set=function(e,t){var r=this.mangle(e);return this.store[r]=t,!0},n.prototype.has=function(e){var t=this.mangle(e);return t in this.store},n.prototype["delete"]=function(e){var t=this.mangle(e);return t in this.store?(delete this.store[t],!0):!1},n.prototype.forEach=function(e){var t=this,r=Object.keys(t.store);r.forEach(function(r){var n=t.store[r];r=t.unmangle(r),e(n,r)})},o.prototype.add=function(e){return this.store.set(e,!0)},o.prototype.has=function(e){return this.store.has(e)},o.prototype["delete"]=function(e){return this.store["delete"](e)}},{}],5:[function(e,t,r){"use strict";function n(e){this.status=e.status,this.name=e.error,this.message=e.reason,this.error=!0}n.prototype__proto__=Error.prototype,n.prototype.toString=function(){return JSON.stringify({status:this.status,name:this.name,message:this.message})},r.UNAUTHORIZED=new n({status:401,error:"unauthorized",reason:"Name or password is incorrect."}),r.MISSING_BULK_DOCS=new n({status:400,error:"bad_request",reason:"Missing JSON list of 'docs'"}),r.MISSING_DOC=new n({status:404,error:"not_found",reason:"missing"}),r.REV_CONFLICT=new n({status:409,error:"conflict",reason:"Document update conflict"}),r.INVALID_ID=new n({status:400,error:"invalid_id",reason:"_id field must contain a string"}),r.MISSING_ID=new n({status:412,error:"missing_id",reason:"_id is required for puts"}),r.RESERVED_ID=new n({status:400,error:"bad_request",reason:"Only reserved document ids may start with underscore."}),r.NOT_OPEN=new n({status:412,error:"precondition_failed",reason:"Database not open"}),r.UNKNOWN_ERROR=new n({status:500,error:"unknown_error",reason:"Database encountered an unknown error"}),r.BAD_ARG=new n({status:500,error:"badarg",reason:"Some query argument is invalid"}),r.INVALID_REQUEST=new n({status:400,error:"invalid_request",reason:"Request was invalid"}),r.QUERY_PARSE_ERROR=new n({status:400,error:"query_parse_error",reason:"Some query parameter is invalid"}),r.DOC_VALIDATION=new n({status:500,error:"doc_validation",reason:"Bad special document member"}),r.BAD_REQUEST=new n({status:400,error:"bad_request",reason:"Something wrong with the request"}),r.NOT_AN_OBJECT=new n({status:400,error:"bad_request",reason:"Document must be a JSON object"}),r.DB_MISSING=new n({status:404,error:"not_found",reason:"Database not found"}),r.IDB_ERROR=new n({status:500,error:"indexed_db_went_bad",reason:"unknown"}),r.WSQ_ERROR=new n({status:500,error:"web_sql_went_bad",reason:"unknown"}),r.LDB_ERROR=new n({status:500,error:"levelDB_went_went_bad",reason:"unknown"}),r.FORBIDDEN=new n({status:403,error:"forbidden",reason:"Forbidden by design doc validate_doc_update function"}),r.error=function(e,t,r){function n(){this.message=t,r&&(this.name=r)}return n.prototype=e,new n(t)}},{}],6:[function(e,t){(function(r,n){"use strict";function o(e,t,r){if("function"==typeof e.slice)return t?r?e.slice(t,r):e.slice(t):e.slice();t=Math.floor(t||0),r=Math.floor(r||0);var n=e.byteLength;if(t=0>t?Math.max(t+n,0):Math.min(n,t),r=0>r?Math.max(r+n,0):Math.min(n,r),0>=r-t)return new ArrayBuffer(0);var o=new ArrayBuffer(r-t),i=new Uint8Array(o),s=new Uint8Array(e,t,r-t);return i.set(s),o}function i(e){var t=[255&e,e>>>8&255,e>>>16&255,e>>>24&255];return t.map(function(e){return String.fromCharCode(e)}).join("")}function s(e){for(var t="",r=0;r<e.length;r++)t+=i(e[r]);return n.btoa(t)}var a=e("crypto"),u=e("spark-md5"),c=n.setImmediate||n.setTimeout,f=32768;t.exports=function(e,t){function n(e,t,r,n){d?e.appendBinary(t.substring(r,n)):e.append(o(t,r,n))}function i(){var r=y*p,o=r+p;if(r+p>=e.size&&(o=e.size),y++,v>y)n(g,e,r,o),c(i);else{n(g,e,r,o);var a=g.end(!0),u=s(a);t(null,u),g.destroy()}}if(!r.browser){var l=a.createHash("md5").update(e).digest("base64");return void t(null,l)}var d="string"==typeof e,h=d?e.length:e.byteLength,p=Math.min(f,h),v=Math.ceil(h/p),y=0,g=d?new u:new u.ArrayBuffer;i()}}).call(this,e("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{_process:24,crypto:16,"spark-md5":117}],7:[function(e,t,r){"use strict";function n(e){return("0000000000000000"+e).slice(-16)}var o=e("fs"),i=e("path"),s=e("../utils"),a=e("../merge"),u=e("levelup"),c=e("through2").obj,f=e("leveldown"),l=["document-store","by-sequence","attach-store","attach-binary-store"],d="_local_last_update_seq",h="_local_doc_count",p="_local_uuid";r.toSublevel=function(e,t,r){function n(e,r,n){var o,a=i.join(s,e);o=3===r?{valueEncoding:"binary"}:{valueEncoding:"json"};var c=t.sublevel(e,o),f=u(a,o),l=f.createReadStream(),d=c.createWriteStream();l.on("end",function(){f.close(function(e){n(e,a)})}),l.pipe(d)}var s=i.resolve(e);o.unlink(s+".uuid",function(e){if(e)return r();var t=4,i=[];l.forEach(function(e,a){n(e,a,function(e,n){return e?r(e):(i.push(n),void(--t||i.forEach(function(e){f.destroy(e,function(){++t===i.length&&o.rmdir(s,r)})})))})})})},r.localAndMetaStores=function(e,t,r){var o=[];t.bySeqStore.get(p,function(i,u){return i?r():(o.push({key:p,value:u,prefix:t.metaStore,type:"put",valueEncoding:"json"}),o.push({key:p,prefix:t.bySeqStore,type:"del"}),void t.bySeqStore.get(h,function(i,u){u&&(o.push({key:h,value:u,prefix:t.metaStore,type:"put",valueEncoding:"json"}),o.push({key:h,prefix:t.bySeqStore,type:"del"})),t.bySeqStore.get(d,function(i,u){u&&(o.push({key:d,value:u,prefix:t.metaStore,type:"put",valueEncoding:"json"}),o.push({key:d,prefix:t.bySeqStore,type:"del"}));var f={};t.docStore.createReadStream({startKey:"_",endKey:"_ÿ"}).pipe(c(function(e,r,i){if(!s.isLocalId(e.key))return i();o.push({key:e.key,prefix:t.docStore,type:"del"});var u=a.winningRev(e.value);Object.keys(e.value.rev_map).forEach(function(t){"winner"!==t&&this.push(n(e.value.rev_map[t]))},this);var c=e.value.rev_map[u];t.bySeqStore.get(n(c),function(r,n){r||o.push({key:e.key,value:n,prefix:t.localStore,type:"put",valueEncoding:"json"}),i()})})).pipe(c(function(e,r,n){return f[e]?n():(f[e]=!0,void t.bySeqStore.get(e,function(r,i){return r||!s.isLocalId(i._id)?n():(o.push({key:e,prefix:t.bySeqStore,type:"del"}),void n())}))},function(){e.batch(o,r)}))})}))})}},{"../merge":10,"../utils":13,fs:15,leveldown:"leveldown",levelup:75,path:23,through2:132}],8:[function(e,t){"use strict";function r(e){for(var t=n,r=t.parser[t.strictMode?"strict":"loose"].exec(e),o={},i=14;i--;){var s=t.key[i],a=r[i]||"",u=-1!==["user","password"].indexOf(s);o[s]=u?decodeURIComponent(a):a}return o[t.q.name]={},o[t.key[12]].replace(t.q.parser,function(e,r,n){r&&(o[t.q.name][r]=n)}),o}var n={strictMode:!1,key:["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],q:{name:"queryKey",parser:/(?:^|&)([^&=]*)=?([^&]*)/g},parser:{strict:/^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,loose:/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/}};t.exports=r},{}],9:[function(e,t){"use strict";function r(e){return 0|Math.random()*e}function n(e,t){t=t||o.length;var n="",i=-1;if(e){for(;++i<e;)n+=o[r(t)];return n}for(;++i<36;)switch(i){case 8:case 13:case 18:case 23:n+="-";break;case 19:n+=o[3&r(16)|8];break;default:n+=o[r(16)]}return n}var o="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split("");t.exports=n},{}],10:[function(e,t){"use strict";function r(e){for(var t,r=e.shift(),n=[r.id,r.opts,[]],o=n;e.length;)r=e.shift(),t=[r.id,r.opts,[]],o[2].push(t),o=t;return n}function n(e,t){for(var r=[{tree1:e,tree2:t}],n=!1;r.length>0;){var o=r.pop(),i=o.tree1,s=o.tree2;(i[1].status||s[1].status)&&(i[1].status="available"===i[1].status||"available"===s[1].status?"available":"missing");for(var a=0;a<s[2].length;a++)if(i[2][0]){for(var u=!1,c=0;c<i[2].length;c++)i[2][c][0]===s[2][a][0]&&(r.push({tree1:i[2][c],tree2:s[2][a]}),u=!0);u||(n="new_branch",i[2].push(s[2][a]),i[2].sort())}else n="new_leaf",i[2][0]=s[2][a]}return{conflicts:n,tree:e}}function o(e,t,r){var o,i=[],s=!1,a=!1;return e.length?(e.forEach(function(e){if(e.pos===t.pos&&e.ids[0]===t.ids[0])o=n(e.ids,t.ids),i.push({pos:e.pos,ids:o.tree}),s=s||o.conflicts,a=!0;else if(r!==!0){var u=e.pos<t.pos?e:t,c=e.pos<t.pos?t:e,f=c.pos-u.pos,l=[],d=[];for(d.push({ids:u.ids,diff:f,parent:null,parentIdx:null});d.length>0;){var h=d.pop();0!==h.diff?h.ids&&h.ids[2].forEach(function(e,t){d.push({ids:e,diff:h.diff-1,parent:h.ids,parentIdx:t})}):h.ids[0]===c.ids[0]&&l.push(h)}var p=l[0];p?(o=n(p.ids,c.ids),p.parent[2][p.parentIdx]=o.tree,i.push({pos:u.pos,ids:u.ids}),s=s||o.conflicts,a=!0):i.push(e)}else i.push(e)}),a||i.push(t),i.sort(function(e,t){return e.pos-t.pos}),{tree:i,conflicts:s||"internal_node"}):{tree:[t],conflicts:"new_leaf"}}function i(e,t){var n=a.rootToLeaf(e).map(function(e){var n=e.ids.slice(-t);return{pos:e.pos+(e.ids.length-n.length),ids:r(n)}});return n.reduce(function(e,t){return o(e,t,!0).tree},[n.shift()])}var s=e("pouchdb-extend"),a={};a.merge=function(e,t,r){e=s(!0,[],e),t=s(!0,{},t);var n=o(e,t);return{tree:i(n.tree,r),conflicts:n.conflicts}},a.winningRev=function(e){var t=[];return a.traverseRevTree(e.rev_tree,function(e,r,n,o,i){e&&t.push({pos:r,id:n,deleted:!!i.deleted})}),t.sort(function(e,t){return e.deleted!==t.deleted?e.deleted>t.deleted?1:-1:e.pos!==t.pos?t.pos-e.pos:e.id<t.id?1:-1}),t[0].pos+"-"+t[0].id},a.traverseRevTree=function(e,t){for(var r,n=e.slice();r=n.pop();)for(var o=r.pos,i=r.ids,s=i[2],a=t(0===s.length,o,i[0],r.ctx,i[1]),u=0,c=s.length;c>u;u++)n.push({pos:o+1,ids:s[u],ctx:a})},a.collectLeaves=function(e){var t=[];return a.traverseRevTree(e,function(e,r,n,o,i){e&&t.unshift({rev:r+"-"+n,pos:r,opts:i})}),t.sort(function(e,t){return t.pos-e.pos}),t.map(function(e){delete e.pos}),t},a.collectConflicts=function(e){var t=a.winningRev(e),r=a.collectLeaves(e.rev_tree),n=[];return r.forEach(function(e){e.rev===t||e.opts.deleted||n.push(e.rev)}),n},a.rootToLeaf=function(e){var t=[];return a.traverseRevTree(e,function(e,r,n,o,i){if(o=o?o.slice(0):[],o.push({id:n,opts:i}),e){var s=r+1-o.length;t.unshift({pos:s,ids:o})}return o}),t},t.exports=a},{"pouchdb-extend":116}],11:[function(e){(function(t){"use strict";var r=e("adapter-config"),n=r.name,o=e("./levelalt")(r),i=t.PouchDB||e("pouchdb");i.adapter(n,o),i.preferredAdapters.push(n)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./levelalt":12,"adapter-config":"adapter-config",pouchdb:"pouchdb"}],12:[function(e,t){"use strict";function r(e){function t(e,t){var r=i.extend({db:o},e);n.call(this,r,t)}return t.valid=function(){return e.valid()},t.use_prefix=e.use_prefix,t.destroy=i.toPromise(function(e,t,r){"function"==typeof t&&(r=t,t={});var s=i.extend({db:o},t);return n.destroy(e,s,r)}),t}var n=e("../adapters/leveldb"),o=e("leveldown"),i=e("../utils");t.exports=r},{"../adapters/leveldb":1,"../utils":13,leveldown:"leveldown"}],13:[function(e,t,r){(function(t,n){function o(e){var t={};return e.forEach(function(e){t[e]=!0}),t}function i(){return"undefined"!=typeof chrome&&"undefined"!=typeof chrome.storage&&"undefined"!=typeof chrome.storage.local}function s(){if(!(this instanceof s))return new s;var e=this;f.call(this),this.isChrome=i(),this.listeners={},this.hasLocal=!1,this.isChrome||(this.hasLocal=r.hasLocalStorage()),this.isChrome?chrome.storage.onChanged.addListener(function(t){null!=t.db_name&&e.emit(t.dbName.newValue)}):this.hasLocal&&(n.addEventListener?n.addEventListener("storage",function(t){e.emit(t.key)}):n.attachEvent("storage",function(t){e.emit(t.key)}))}var a=e("./merge");r.extend=e("pouchdb-extend"),r.ajax=e("./deps/ajax"),r.createBlob=e("./deps/blob"),r.uuid=e("./deps/uuid"),r.getArguments=e("argsarray");var u=e("./deps/buffer"),c=e("./deps/errors"),f=e("events").EventEmitter,l=e("./deps/collections");r.Map=l.Map,r.Set=l.Set,r.Promise="function"==typeof n.Promise?n.Promise:e("bluebird");var d=r.Promise,h=o(["_id","_rev","_attachments","_deleted","_revisions","_revs_info","_conflicts","_deleted_conflicts","_local_seq","_rev_tree","_replication_id","_replication_state","_replication_state_time","_replication_state_reason","_replication_stats"]),p=o(["_attachments","_replication_id","_replication_state","_replication_state_time","_replication_state_reason","_replication_stats"]);r.lastIndexOf=function(e,t){for(var r=e.length-1;r>=0;r--)if(e.charAt(r)===t)return r;return-1},r.clone=function(e){return r.extend(!0,{},e)},r.pick=function(e,t){for(var r={},n=0,o=t.length;o>n;n++){var i=t[n];r[i]=e[i]}return r},r.inherits=e("inherits"),r.invalidIdError=function(e){var t;if(e?"string"!=typeof e?(t=new TypeError(c.INVALID_ID.message),t.status=400):/^_/.test(e)&&!/^_(design|local)/.test(e)&&(t=new TypeError(c.RESERVED_ID.message),t.status=400):(t=new TypeError(c.MISSING_ID.message),t.status=412),t)throw t},r.call=r.getArguments(function(e){if(e.length){var t=e.shift();"function"==typeof t&&t.apply(this,e)}}),r.isLocalId=function(e){return/^_local/.test(e)},r.isDeleted=function(e,t){t||(t=a.winningRev(e)); +var r=t.indexOf("-");-1!==r&&(t=t.substring(r+1));var n=!1;return a.traverseRevTree(e.rev_tree,function(e,r,o,i,s){o===t&&(n=!!s.deleted)}),n},r.revExists=function(e,t){var r=!1;return a.traverseRevTree(e.rev_tree,function(e,n,o){n+"-"+o===t&&(r=!0)}),r},r.filterChange=function(e){var t={},r=e.filter&&"function"==typeof e.filter;return t.query=e.query_params,function(n){if(e.filter&&r&&!e.filter.call(this,n.doc,t))return!1;if(e.include_docs){if(!e.attachments)for(var o in n.doc._attachments)n.doc._attachments.hasOwnProperty(o)&&(n.doc._attachments[o].stub=!0)}else delete n.doc;return!0}},r.parseDoc=function(e,t){var n,o,i,s,a={status:"available"};if(e._deleted&&(a.deleted=!0),t)if(e._id||(e._id=r.uuid()),o=r.uuid(32,16).toLowerCase(),e._rev){if(i=/^(\d+)-(.+)$/.exec(e._rev),!i)return s=new Error("bad_request"),s.message="Invalid rev format",s.error=!0,s;e._rev_tree=[{pos:parseInt(i[1],10),ids:[i[2],{status:"missing"},[[o,a,[]]]]}],n=parseInt(i[1],10)+1}else e._rev_tree=[{pos:1,ids:[o,a,[]]}],n=1;else if(e._revisions&&(e._rev_tree=[{pos:e._revisions.start-e._revisions.ids.length+1,ids:e._revisions.ids.reduce(function(e,t){return null===e?[t,a,[]]:[t,{status:"missing"},[e]]},null)}],n=e._revisions.start,o=e._revisions.ids[0]),!e._rev_tree){if(i=/^(\d+)-(.+)$/.exec(e._rev),!i)return s=new Error("bad_request"),s.message="Invalid rev format",s.error=!0,s;n=parseInt(i[1],10),o=i[2],e._rev_tree=[{pos:parseInt(i[1],10),ids:[i[2],a,[]]}]}r.invalidIdError(e._id),e._rev=[n,o].join("-");var u={metadata:{},data:{}};for(var f in e)if(e.hasOwnProperty(f)){var l="_"===f[0];if(l&&!h[f])throw s=new Error(c.DOC_VALIDATION.message+": "+f),s.status=c.DOC_VALIDATION.status,s;l&&!p[f]?u.metadata[f.slice(1)]=e[f]:u.data[f]=e[f]}return u},r.isCordova=function(){return"undefined"!=typeof cordova||"undefined"!=typeof PhoneGap||"undefined"!=typeof phonegap},r.hasLocalStorage=function(){if(i())return!1;try{return n.localStorage}catch(e){return!1}},r.Changes=s,r.inherits(s,f),s.prototype.addListener=function(e,t,n,o){function i(){n.changes({include_docs:o.include_docs,attachments:o.attachments,conflicts:o.conflicts,continuous:!1,descending:!1,filter:o.filter,doc_ids:o.doc_ids,view:o.view,since:o.since,query_params:o.query_params,onChange:function(e){e.seq>o.since&&!o.cancelled&&(o.since=e.seq,r.call(o.onChange,e))}})}this.listeners[t]||(this.listeners[t]=i,this.on(e,i))},s.prototype.removeListener=function(e,t){t in this.listeners&&f.prototype.removeListener.call(this,e,this.listeners[t])},s.prototype.notifyLocalWindows=function(e){this.isChrome?chrome.storage.local.set({dbName:e}):this.hasLocal&&(localStorage[e]="a"===localStorage[e]?"b":"a")},s.prototype.notify=function(e){this.emit(e),this.notifyLocalWindows(e)},r.atob=t.browser&&"atob"in n?function(e){return atob(e)}:function(e){var t=new u(e,"base64");if(t.toString("base64")!==e)throw"Cannot base64 encode full string";return t.toString("binary")},r.btoa=t.browser&&"btoa"in n?function(e){return btoa(e)}:function(e){return new u(e,"binary").toString("base64")},r.fixBinary=function(e){if(!t.browser)return e;for(var r=e.length,n=new ArrayBuffer(r),o=new Uint8Array(n),i=0;r>i;i++)o[i]=e.charCodeAt(i);return n},r.readAsBinaryString=function(e,t){var n=new FileReader,o="function"==typeof n.readAsBinaryString;n.onloadend=function(e){var n=e.target.result||"";return o?t(n):void t(r.arrayBufferToBinaryString(n))},o?n.readAsBinaryString(e):n.readAsArrayBuffer(e)},r.once=function(e){var t=!1;return r.getArguments(function(r){if(t)throw new Error("once called more than once");t=!0,e.apply(this,r)})},r.toPromise=function(e){return r.getArguments(function(n){var o,i=this,s="function"==typeof n[n.length-1]?n.pop():!1;s&&(o=function(e,r){t.nextTick(function(){s(e,r)})});var a=new d(function(t,o){var s;try{var a=r.once(function(e,r){e?o(e):t(r)});n.push(a),s=e.apply(i,n),s&&"function"==typeof s.then&&t(s)}catch(u){o(u)}});return o&&a.then(function(e){o(null,e)},o),a.cancel=function(){return this},a})},r.adapterFun=function(t,n){function o(e,t,r){if(i.enabled){for(var n=[e._db_name,t],o=0;o<r.length-1;o++)n.push(r[o]);i.apply(null,n);var s=r[r.length-1];r[r.length-1]=function(r,n){var o=[e._db_name,t];o=o.concat(r?["error",r]:["success",n]),i.apply(null,o),s(r,n)}}}var i=e("debug")("pouchdb:api");return r.toPromise(r.getArguments(function(e){if(this._closed)return d.reject(new Error("database is closed"));var i=this;return o(i,t,e),this.taskqueue.isReady?n.apply(this,e):new r.Promise(function(r,n){i.taskqueue.addTask(function(o){o?n(o):r(i[t].apply(i,e))})})}))},r.arrayBufferToBinaryString=function(e){for(var t="",r=new Uint8Array(e),n=r.byteLength,o=0;n>o;o++)t+=String.fromCharCode(r[o]);return t},r.cancellableFun=function(e,t,n){n=n?r.clone(!0,{},n):{};var o=new f,i=n.complete||function(){},s=n.complete=r.once(function(e,t){e?i(e):(o.emit("end",t),i(null,t)),o.removeAllListeners()}),a=n.onChange||function(){},u=0;t.on("destroyed",function(){o.removeAllListeners()}),n.onChange=function(e){a(e),e.seq<=u||(u=e.seq,o.emit("change",e),e.deleted?o.emit("delete",e):1===e.changes.length&&"1-"===e.changes[0].rev.slice(0,1)?o.emit("create",e):o.emit("update",e))};var c=new d(function(e,t){n.complete=function(r,n){r?t(r):e(n)}});return c.then(function(e){s(null,e)},s),c.cancel=function(){c.isCancelled=!0,t.taskqueue.isReady&&n.complete(null,{status:"cancelled"})},t.taskqueue.isReady?e(t,n,c):t.taskqueue.addTask(function(){c.isCancelled?n.complete(null,{status:"cancelled"}):e(t,n,c)}),c.on=o.on.bind(o),c.once=o.once.bind(o),c.addListener=o.addListener.bind(o),c.removeListener=o.removeListener.bind(o),c.removeAllListeners=o.removeAllListeners.bind(o),c.setMaxListeners=o.setMaxListeners.bind(o),c.listeners=o.listeners.bind(o),c.emit=o.emit.bind(o),c},r.MD5=r.toPromise(e("./deps/md5")),r.explain404=function(e){t.browser&&"console"in n&&"info"in console&&console.info("The above 404 is totally normal. "+e)},r.parseUri=e("./deps/parse-uri"),r.compare=function(e,t){return t>e?-1:e>t?1:0},r.updateDoc=function(e,t,n,o,i,s,u){if(r.revExists(e,t.metadata.rev))return n[o]=t,i();var f=r.isDeleted(e),l=r.isDeleted(t.metadata),d=/^1-/.test(t.metadata.rev);if(f&&!l&&u&&d){var h=t.data;h._rev=a.winningRev(e),h._id=t.metadata.id,t=r.parseDoc(h,u)}var p=a.merge(e.rev_tree,t.metadata.rev_tree[0],1e3),v=u&&(f&&l||!f&&"new_leaf"!==p.conflicts||f&&!l&&"new_branch"===p.conflicts);if(v){var y=c.REV_CONFLICT;return n[o]=y,i()}t.metadata.rev_tree=p.tree;var g=a.winningRev(t.metadata);l=r.isDeleted(t.metadata,g),s(t,g,l,i,!0,o)},r.processDocs=function(e,t,n,o,i,s,u){function f(e,t,n){var o=a.winningRev(e.metadata),f=r.isDeleted(e.metadata,o);return"was_delete"in u&&f?(i[t]=c.MISSING_DOC,n()):void s(e,o,f,n,!1,t)}if(e.length){var l=u.new_edits,d=new r.Map;e.forEach(function(e,n){if(e._id&&r.isLocalId(e._id))return void t[e._deleted?"_removeLocal":"_putLocal"](e,{ctx:o},function(e){i[n]=e?e:{}});var s=e.metadata.id;d.has(s)?d.get(s).push([e,n]):d.set(s,[[e,n]])}),d.forEach(function(e,t){function o(){++u<e.length&&a()}function a(){var a=e[u],c=a[0],d=a[1];n.has(t)?r.updateDoc(n.get(t),c,i,d,o,s,l):f(c,d,o)}var u=0;a()})}},r.preprocessAttachments=function(e,t,n){function o(e){try{return r.atob(e)}catch(t){var n=c.error(c.BAD_ARG,"Attachments need to be base64 encoded");return{error:n}}}function i(e,n){if(e.stub)return n();if("string"==typeof e.data){var i=o(e.data);if(i.error)return n(i.error);e.length=i.length,e.data="blob"===t?r.createBlob([r.fixBinary(i)],{type:e.content_type}):"base64"===t?r.btoa(i):i,r.MD5(i).then(function(t){e.digest="md5-"+t,n()})}else r.readAsBinaryString(e.data,function(o){"binary"===t?e.data=o:"base64"===t&&(e.data=r.btoa(o)),r.MD5(o).then(function(t){e.digest="md5-"+t,e.length=o.length,n()})})}function s(){u++,e.length===u&&(a?n(a):n())}if(!e.length)return n();var a,u=0;e.forEach(function(e){function t(e){a=e,n++,n===r.length&&s()}var r=e.data&&e.data._attachments?Object.keys(e.data._attachments):[],n=0;if(!r.length)return s();for(var o in e.data._attachments)e.data._attachments.hasOwnProperty(o)&&i(e.data._attachments[o],t)})}}).call(this,e("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./deps/ajax":2,"./deps/blob":3,"./deps/buffer":16,"./deps/collections":4,"./deps/errors":5,"./deps/md5":6,"./deps/parse-uri":8,"./deps/uuid":9,"./merge":10,_process:24,argsarray:14,bluebird:101,debug:40,events:21,inherits:44,"pouchdb-extend":116}],14:[function(e,t){"use strict";function r(e){return function(){var t=arguments.length;if(t){for(var r=[],n=-1;++n<t;)r[n]=arguments[n];return e.call(this,r)}return e.call(this,[])}}t.exports=r},{}],15:[function(){},{}],16:[function(e,t){t.exports=e(15)},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/lib/_empty.js":15}],17:[function(e,t,r){function n(e,t,r){if(!(this instanceof n))return new n(e,t,r);var o,i=typeof e;if("number"===i)o=e>0?e>>>0:0;else if("string"===i)"base64"===t&&(e=x(e)),o=n.byteLength(e,t);else{if("object"!==i||null===e)throw new TypeError("must start with number, buffer, array or string");"Buffer"===e.type&&B(e.data)&&(e=e.data),o=+e.length>0?Math.floor(+e.length):0}if(this.length>C)throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+C.toString(16)+" bytes");var s;n.TYPED_ARRAY_SUPPORT?s=n._augment(new Uint8Array(o)):(s=this,s.length=o,s._isBuffer=!0);var a;if(n.TYPED_ARRAY_SUPPORT&&"number"==typeof e.byteLength)s._set(e);else if(S(e))if(n.isBuffer(e))for(a=0;o>a;a++)s[a]=e.readUInt8(a);else for(a=0;o>a;a++)s[a]=(e[a]%256+256)%256;else if("string"===i)s.write(e,0,t);else if("number"===i&&!n.TYPED_ARRAY_SUPPORT&&!r)for(a=0;o>a;a++)s[a]=0;return s}function o(e,t,r,n){r=Number(r)||0;var o=e.length-r;n?(n=Number(n),n>o&&(n=o)):n=o;var i=t.length;if(i%2!==0)throw new Error("Invalid hex string");n>i/2&&(n=i/2);for(var s=0;n>s;s++){var a=parseInt(t.substr(2*s,2),16);if(isNaN(a))throw new Error("Invalid hex string");e[r+s]=a}return s}function i(e,t,r,n){var o=N(j(t),e,r,n);return o}function s(e,t,r,n){var o=N(O(t),e,r,n);return o}function a(e,t,r,n){return s(e,t,r,n)}function u(e,t,r,n){var o=N(I(t),e,r,n);return o}function c(e,t,r,n){var o=N(R(t),e,r,n);return o}function f(e,t,r){return L.fromByteArray(0===t&&r===e.length?e:e.slice(t,r))}function l(e,t,r){var n="",o="";r=Math.min(e.length,r);for(var i=t;r>i;i++)e[i]<=127?(n+=T(o)+String.fromCharCode(e[i]),o=""):o+="%"+e[i].toString(16);return n+T(o)}function d(e,t,r){var n="";r=Math.min(e.length,r);for(var o=t;r>o;o++)n+=String.fromCharCode(e[o]);return n}function h(e,t,r){return d(e,t,r)}function p(e,t,r){var n=e.length;(!t||0>t)&&(t=0),(!r||0>r||r>n)&&(r=n);for(var o="",i=t;r>i;i++)o+=A(e[i]);return o}function v(e,t,r){for(var n=e.slice(t,r),o="",i=0;i<n.length;i+=2)o+=String.fromCharCode(n[i]+256*n[i+1]);return o}function y(e,t,r){if(e%1!==0||0>e)throw new RangeError("offset is not uint");if(e+t>r)throw new RangeError("Trying to access beyond buffer length")}function g(e,t,r,o,i,s){if(!n.isBuffer(e))throw new TypeError("buffer must be a Buffer instance");if(t>i||s>t)throw new TypeError("value is out of bounds");if(r+o>e.length)throw new TypeError("index out of range")}function m(e,t,r,n){0>t&&(t=65535+t+1);for(var o=0,i=Math.min(e.length-r,2);i>o;o++)e[r+o]=(t&255<<8*(n?o:1-o))>>>8*(n?o:1-o)}function b(e,t,r,n){0>t&&(t=4294967295+t+1);for(var o=0,i=Math.min(e.length-r,4);i>o;o++)e[r+o]=t>>>8*(n?o:3-o)&255}function _(e,t,r,n,o,i){if(t>o||i>t)throw new TypeError("value is out of bounds");if(r+n>e.length)throw new TypeError("index out of range")}function w(e,t,r,n,o){return o||_(e,t,r,4,3.4028234663852886e38,-3.4028234663852886e38),D.write(e,t,r,n,23,4),r+4}function E(e,t,r,n,o){return o||_(e,t,r,8,1.7976931348623157e308,-1.7976931348623157e308),D.write(e,t,r,n,52,8),r+8}function x(e){for(e=k(e).replace(U,"");e.length%4!==0;)e+="=";return e}function k(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}function S(e){return B(e)||n.isBuffer(e)||e&&"object"==typeof e&&"number"==typeof e.length}function A(e){return 16>e?"0"+e.toString(16):e.toString(16)}function j(e){for(var t=[],r=0;r<e.length;r++){var n=e.charCodeAt(r);if(127>=n)t.push(n);else{var o=r;n>=55296&&57343>=n&&r++;for(var i=encodeURIComponent(e.slice(o,r+1)).substr(1).split("%"),s=0;s<i.length;s++)t.push(parseInt(i[s],16))}}return t}function O(e){for(var t=[],r=0;r<e.length;r++)t.push(255&e.charCodeAt(r));return t}function R(e){for(var t,r,n,o=[],i=0;i<e.length;i++)t=e.charCodeAt(i),r=t>>8,n=t%256,o.push(n),o.push(r);return o}function I(e){return L.toByteArray(e)}function N(e,t,r,n){for(var o=0;n>o&&!(o+r>=t.length||o>=e.length);o++)t[o+r]=e[o];return o}function T(e){try{return decodeURIComponent(e)}catch(t){return String.fromCharCode(65533)}}var L=e("base64-js"),D=e("ieee754"),B=e("is-array");r.Buffer=n,r.SlowBuffer=n,r.INSPECT_MAX_BYTES=50,n.poolSize=8192;var C=1073741823;n.TYPED_ARRAY_SUPPORT=function(){try{var e=new ArrayBuffer(0),t=new Uint8Array(e);return t.foo=function(){return 42},42===t.foo()&&"function"==typeof t.subarray&&0===new Uint8Array(1).subarray(1,1).byteLength}catch(r){return!1}}(),n.isBuffer=function(e){return!(null==e||!e._isBuffer)},n.compare=function(e,t){if(!n.isBuffer(e)||!n.isBuffer(t))throw new TypeError("Arguments must be Buffers");for(var r=e.length,o=t.length,i=0,s=Math.min(r,o);s>i&&e[i]===t[i];i++);return i!==s&&(r=e[i],o=t[i]),o>r?-1:r>o?1:0},n.isEncoding=function(e){switch(String(e).toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"raw":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return!0;default:return!1}},n.concat=function(e,t){if(!B(e))throw new TypeError("Usage: Buffer.concat(list[, length])");if(0===e.length)return new n(0);if(1===e.length)return e[0];var r;if(void 0===t)for(t=0,r=0;r<e.length;r++)t+=e[r].length;var o=new n(t),i=0;for(r=0;r<e.length;r++){var s=e[r];s.copy(o,i),i+=s.length}return o},n.byteLength=function(e,t){var r;switch(e+="",t||"utf8"){case"ascii":case"binary":case"raw":r=e.length;break;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":r=2*e.length;break;case"hex":r=e.length>>>1;break;case"utf8":case"utf-8":r=j(e).length;break;case"base64":r=I(e).length;break;default:r=e.length}return r},n.prototype.length=void 0,n.prototype.parent=void 0,n.prototype.toString=function(e,t,r){var n=!1;if(t>>>=0,r=void 0===r||1/0===r?this.length:r>>>0,e||(e="utf8"),0>t&&(t=0),r>this.length&&(r=this.length),t>=r)return"";for(;;)switch(e){case"hex":return p(this,t,r);case"utf8":case"utf-8":return l(this,t,r);case"ascii":return d(this,t,r);case"binary":return h(this,t,r);case"base64":return f(this,t,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return v(this,t,r);default:if(n)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),n=!0}},n.prototype.equals=function(e){if(!n.isBuffer(e))throw new TypeError("Argument must be a Buffer");return 0===n.compare(this,e)},n.prototype.inspect=function(){var e="",t=r.INSPECT_MAX_BYTES;return this.length>0&&(e=this.toString("hex",0,t).match(/.{2}/g).join(" "),this.length>t&&(e+=" ... ")),"<Buffer "+e+">"},n.prototype.compare=function(e){if(!n.isBuffer(e))throw new TypeError("Argument must be a Buffer");return n.compare(this,e)},n.prototype.get=function(e){return console.log(".get() is deprecated. Access using array indexes instead."),this.readUInt8(e)},n.prototype.set=function(e,t){return console.log(".set() is deprecated. Access using array indexes instead."),this.writeUInt8(e,t)},n.prototype.write=function(e,t,r,n){if(isFinite(t))isFinite(r)||(n=r,r=void 0);else{var f=n;n=t,t=r,r=f}t=Number(t)||0;var l=this.length-t;r?(r=Number(r),r>l&&(r=l)):r=l,n=String(n||"utf8").toLowerCase();var d;switch(n){case"hex":d=o(this,e,t,r);break;case"utf8":case"utf-8":d=i(this,e,t,r);break;case"ascii":d=s(this,e,t,r);break;case"binary":d=a(this,e,t,r);break;case"base64":d=u(this,e,t,r);break;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":d=c(this,e,t,r);break;default:throw new TypeError("Unknown encoding: "+n)}return d},n.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}},n.prototype.slice=function(e,t){var r=this.length;if(e=~~e,t=void 0===t?r:~~t,0>e?(e+=r,0>e&&(e=0)):e>r&&(e=r),0>t?(t+=r,0>t&&(t=0)):t>r&&(t=r),e>t&&(t=e),n.TYPED_ARRAY_SUPPORT)return n._augment(this.subarray(e,t));for(var o=t-e,i=new n(o,void 0,!0),s=0;o>s;s++)i[s]=this[s+e];return i},n.prototype.readUInt8=function(e,t){return t||y(e,1,this.length),this[e]},n.prototype.readUInt16LE=function(e,t){return t||y(e,2,this.length),this[e]|this[e+1]<<8},n.prototype.readUInt16BE=function(e,t){return t||y(e,2,this.length),this[e]<<8|this[e+1]},n.prototype.readUInt32LE=function(e,t){return t||y(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},n.prototype.readUInt32BE=function(e,t){return t||y(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},n.prototype.readInt8=function(e,t){return t||y(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},n.prototype.readInt16LE=function(e,t){t||y(e,2,this.length);var r=this[e]|this[e+1]<<8;return 32768&r?4294901760|r:r},n.prototype.readInt16BE=function(e,t){t||y(e,2,this.length);var r=this[e+1]|this[e]<<8;return 32768&r?4294901760|r:r},n.prototype.readInt32LE=function(e,t){return t||y(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},n.prototype.readInt32BE=function(e,t){return t||y(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},n.prototype.readFloatLE=function(e,t){return t||y(e,4,this.length),D.read(this,e,!0,23,4)},n.prototype.readFloatBE=function(e,t){return t||y(e,4,this.length),D.read(this,e,!1,23,4)},n.prototype.readDoubleLE=function(e,t){return t||y(e,8,this.length),D.read(this,e,!0,52,8)},n.prototype.readDoubleBE=function(e,t){return t||y(e,8,this.length),D.read(this,e,!1,52,8)},n.prototype.writeUInt8=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,1,255,0),n.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=e,t+1},n.prototype.writeUInt16LE=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,2,65535,0),n.TYPED_ARRAY_SUPPORT?(this[t]=e,this[t+1]=e>>>8):m(this,e,t,!0),t+2},n.prototype.writeUInt16BE=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,2,65535,0),n.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=e):m(this,e,t,!1),t+2},n.prototype.writeUInt32LE=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,4,4294967295,0),n.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=e):b(this,e,t,!0),t+4},n.prototype.writeUInt32BE=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,4,4294967295,0),n.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=e):b(this,e,t,!1),t+4},n.prototype.writeInt8=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,1,127,-128),n.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),0>e&&(e=255+e+1),this[t]=e,t+1},n.prototype.writeInt16LE=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,2,32767,-32768),n.TYPED_ARRAY_SUPPORT?(this[t]=e,this[t+1]=e>>>8):m(this,e,t,!0),t+2},n.prototype.writeInt16BE=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,2,32767,-32768),n.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=e):m(this,e,t,!1),t+2},n.prototype.writeInt32LE=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,4,2147483647,-2147483648),n.TYPED_ARRAY_SUPPORT?(this[t]=e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):b(this,e,t,!0),t+4},n.prototype.writeInt32BE=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,4,2147483647,-2147483648),0>e&&(e=4294967295+e+1),n.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=e):b(this,e,t,!1),t+4},n.prototype.writeFloatLE=function(e,t,r){return w(this,e,t,!0,r)},n.prototype.writeFloatBE=function(e,t,r){return w(this,e,t,!1,r)},n.prototype.writeDoubleLE=function(e,t,r){return E(this,e,t,!0,r)},n.prototype.writeDoubleBE=function(e,t,r){return E(this,e,t,!1,r)},n.prototype.copy=function(e,t,r,o){var i=this;if(r||(r=0),o||0===o||(o=this.length),t||(t=0),o!==r&&0!==e.length&&0!==i.length){if(r>o)throw new TypeError("sourceEnd < sourceStart");if(0>t||t>=e.length)throw new TypeError("targetStart out of bounds");if(0>r||r>=i.length)throw new TypeError("sourceStart out of bounds");if(0>o||o>i.length)throw new TypeError("sourceEnd out of bounds");o>this.length&&(o=this.length),e.length-t<o-r&&(o=e.length-t+r);var s=o-r;if(1e3>s||!n.TYPED_ARRAY_SUPPORT)for(var a=0;s>a;a++)e[a+t]=this[a+r];else e._set(this.subarray(r,r+s),t)}},n.prototype.fill=function(e,t,r){if(e||(e=0),t||(t=0),r||(r=this.length),t>r)throw new TypeError("end < start");if(r!==t&&0!==this.length){if(0>t||t>=this.length)throw new TypeError("start out of bounds");if(0>r||r>this.length)throw new TypeError("end out of bounds");var n;if("number"==typeof e)for(n=t;r>n;n++)this[n]=e;else{var o=j(e.toString()),i=o.length;for(n=t;r>n;n++)this[n]=o[n%i]}return this}},n.prototype.toArrayBuffer=function(){if("undefined"!=typeof Uint8Array){if(n.TYPED_ARRAY_SUPPORT)return new n(this).buffer;for(var e=new Uint8Array(this.length),t=0,r=e.length;r>t;t+=1)e[t]=this[t];return e.buffer}throw new TypeError("Buffer.toArrayBuffer not supported in this browser")};var P=n.prototype;n._augment=function(e){return e.constructor=n,e._isBuffer=!0,e._get=e.get,e._set=e.set,e.get=P.get,e.set=P.set,e.write=P.write,e.toString=P.toString,e.toLocaleString=P.toString,e.toJSON=P.toJSON,e.equals=P.equals,e.compare=P.compare,e.copy=P.copy,e.slice=P.slice,e.readUInt8=P.readUInt8,e.readUInt16LE=P.readUInt16LE,e.readUInt16BE=P.readUInt16BE,e.readUInt32LE=P.readUInt32LE,e.readUInt32BE=P.readUInt32BE,e.readInt8=P.readInt8,e.readInt16LE=P.readInt16LE,e.readInt16BE=P.readInt16BE,e.readInt32LE=P.readInt32LE,e.readInt32BE=P.readInt32BE,e.readFloatLE=P.readFloatLE,e.readFloatBE=P.readFloatBE,e.readDoubleLE=P.readDoubleLE,e.readDoubleBE=P.readDoubleBE,e.writeUInt8=P.writeUInt8,e.writeUInt16LE=P.writeUInt16LE,e.writeUInt16BE=P.writeUInt16BE,e.writeUInt32LE=P.writeUInt32LE,e.writeUInt32BE=P.writeUInt32BE,e.writeInt8=P.writeInt8,e.writeInt16LE=P.writeInt16LE,e.writeInt16BE=P.writeInt16BE,e.writeInt32LE=P.writeInt32LE,e.writeInt32BE=P.writeInt32BE,e.writeFloatLE=P.writeFloatLE,e.writeFloatBE=P.writeFloatBE,e.writeDoubleLE=P.writeDoubleLE,e.writeDoubleBE=P.writeDoubleBE,e.fill=P.fill,e.inspect=P.inspect,e.toArrayBuffer=P.toArrayBuffer,e};var U=/[^+\/0-9A-z]/g},{"base64-js":18,ieee754:19,"is-array":20}],18:[function(e,t,r){var n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";!function(e){"use strict";function t(e){var t=e.charCodeAt(0);return t===s?62:t===a?63:u>t?-1:u+10>t?t-u+26+26:f+26>t?t-f:c+26>t?t-c+26:void 0}function r(e){function r(e){c[l++]=e}var n,o,s,a,u,c;if(e.length%4>0)throw new Error("Invalid string. Length must be a multiple of 4");var f=e.length;u="="===e.charAt(f-2)?2:"="===e.charAt(f-1)?1:0,c=new i(3*e.length/4-u),s=u>0?e.length-4:e.length;var l=0;for(n=0,o=0;s>n;n+=4,o+=3)a=t(e.charAt(n))<<18|t(e.charAt(n+1))<<12|t(e.charAt(n+2))<<6|t(e.charAt(n+3)),r((16711680&a)>>16),r((65280&a)>>8),r(255&a);return 2===u?(a=t(e.charAt(n))<<2|t(e.charAt(n+1))>>4,r(255&a)):1===u&&(a=t(e.charAt(n))<<10|t(e.charAt(n+1))<<4|t(e.charAt(n+2))>>2,r(a>>8&255),r(255&a)),c}function o(e){function t(e){return n.charAt(e)}function r(e){return t(e>>18&63)+t(e>>12&63)+t(e>>6&63)+t(63&e)}var o,i,s,a=e.length%3,u="";for(o=0,s=e.length-a;s>o;o+=3)i=(e[o]<<16)+(e[o+1]<<8)+e[o+2],u+=r(i);switch(a){case 1:i=e[e.length-1],u+=t(i>>2),u+=t(i<<4&63),u+="==";break;case 2:i=(e[e.length-2]<<8)+e[e.length-1],u+=t(i>>10),u+=t(i>>4&63),u+=t(i<<2&63),u+="="}return u}var i="undefined"!=typeof Uint8Array?Uint8Array:Array,s="+".charCodeAt(0),a="/".charCodeAt(0),u="0".charCodeAt(0),c="a".charCodeAt(0),f="A".charCodeAt(0);e.toByteArray=r,e.fromByteArray=o}("undefined"==typeof r?this.base64js={}:r)},{}],19:[function(e,t,r){r.read=function(e,t,r,n,o){var i,s,a=8*o-n-1,u=(1<<a)-1,c=u>>1,f=-7,l=r?o-1:0,d=r?-1:1,h=e[t+l];for(l+=d,i=h&(1<<-f)-1,h>>=-f,f+=a;f>0;i=256*i+e[t+l],l+=d,f-=8);for(s=i&(1<<-f)-1,i>>=-f,f+=n;f>0;s=256*s+e[t+l],l+=d,f-=8);if(0===i)i=1-c;else{if(i===u)return s?0/0:1/0*(h?-1:1);s+=Math.pow(2,n),i-=c}return(h?-1:1)*s*Math.pow(2,i-n)},r.write=function(e,t,r,n,o,i){var s,a,u,c=8*i-o-1,f=(1<<c)-1,l=f>>1,d=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,h=n?0:i-1,p=n?1:-1,v=0>t||0===t&&0>1/t?1:0;for(t=Math.abs(t),isNaN(t)||1/0===t?(a=isNaN(t)?1:0,s=f):(s=Math.floor(Math.log(t)/Math.LN2),t*(u=Math.pow(2,-s))<1&&(s--,u*=2),t+=s+l>=1?d/u:d*Math.pow(2,1-l),t*u>=2&&(s++,u/=2),s+l>=f?(a=0,s=f):s+l>=1?(a=(t*u-1)*Math.pow(2,o),s+=l):(a=t*Math.pow(2,l-1)*Math.pow(2,o),s=0));o>=8;e[r+h]=255&a,h+=p,a/=256,o-=8);for(s=s<<o|a,c+=o;c>0;e[r+h]=255&s,h+=p,s/=256,c-=8);e[r+h-p]|=128*v}},{}],20:[function(e,t){var r=Array.isArray,n=Object.prototype.toString;t.exports=r||function(e){return!!e&&"[object Array]"==n.call(e)}},{}],21:[function(e,t){function r(){this._events=this._events||{},this._maxListeners=this._maxListeners||void 0}function n(e){return"function"==typeof e}function o(e){return"number"==typeof e}function i(e){return"object"==typeof e&&null!==e}function s(e){return void 0===e}t.exports=r,r.EventEmitter=r,r.prototype._events=void 0,r.prototype._maxListeners=void 0,r.defaultMaxListeners=10,r.prototype.setMaxListeners=function(e){if(!o(e)||0>e||isNaN(e))throw TypeError("n must be a positive number");return this._maxListeners=e,this},r.prototype.emit=function(e){var t,r,o,a,u,c;if(this._events||(this._events={}),"error"===e&&(!this._events.error||i(this._events.error)&&!this._events.error.length)){if(t=arguments[1],t instanceof Error)throw t;throw TypeError('Uncaught, unspecified "error" event.')}if(r=this._events[e],s(r))return!1;if(n(r))switch(arguments.length){case 1:r.call(this);break;case 2:r.call(this,arguments[1]);break;case 3:r.call(this,arguments[1],arguments[2]);break;default:for(o=arguments.length,a=new Array(o-1),u=1;o>u;u++)a[u-1]=arguments[u];r.apply(this,a)}else if(i(r)){for(o=arguments.length,a=new Array(o-1),u=1;o>u;u++)a[u-1]=arguments[u];for(c=r.slice(),o=c.length,u=0;o>u;u++)c[u].apply(this,a)}return!0},r.prototype.addListener=function(e,t){var o;if(!n(t))throw TypeError("listener must be a function");if(this._events||(this._events={}),this._events.newListener&&this.emit("newListener",e,n(t.listener)?t.listener:t),this._events[e]?i(this._events[e])?this._events[e].push(t):this._events[e]=[this._events[e],t]:this._events[e]=t,i(this._events[e])&&!this._events[e].warned){var o;o=s(this._maxListeners)?r.defaultMaxListeners:this._maxListeners,o&&o>0&&this._events[e].length>o&&(this._events[e].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[e].length),"function"==typeof console.trace&&console.trace())}return this},r.prototype.on=r.prototype.addListener,r.prototype.once=function(e,t){function r(){this.removeListener(e,r),o||(o=!0,t.apply(this,arguments))}if(!n(t))throw TypeError("listener must be a function");var o=!1;return r.listener=t,this.on(e,r),this},r.prototype.removeListener=function(e,t){var r,o,s,a;if(!n(t))throw TypeError("listener must be a function");if(!this._events||!this._events[e])return this;if(r=this._events[e],s=r.length,o=-1,r===t||n(r.listener)&&r.listener===t)delete this._events[e],this._events.removeListener&&this.emit("removeListener",e,t);else if(i(r)){for(a=s;a-->0;)if(r[a]===t||r[a].listener&&r[a].listener===t){o=a;break}if(0>o)return this;1===r.length?(r.length=0,delete this._events[e]):r.splice(o,1),this._events.removeListener&&this.emit("removeListener",e,t)}return this},r.prototype.removeAllListeners=function(e){var t,r;if(!this._events)return this;if(!this._events.removeListener)return 0===arguments.length?this._events={}:this._events[e]&&delete this._events[e],this;if(0===arguments.length){for(t in this._events)"removeListener"!==t&&this.removeAllListeners(t);return this.removeAllListeners("removeListener"),this._events={},this}if(r=this._events[e],n(r))this.removeListener(e,r);else for(;r.length;)this.removeListener(e,r[r.length-1]);return delete this._events[e],this},r.prototype.listeners=function(e){var t;return t=this._events&&this._events[e]?n(this._events[e])?[this._events[e]]:this._events[e].slice():[]},r.listenerCount=function(e,t){var r;return r=e._events&&e._events[t]?n(e._events[t])?1:e._events[t].length:0}},{}],22:[function(e,t){t.exports=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)}},{}],23:[function(e,t,r){(function(e){function t(e,t){for(var r=0,n=e.length-1;n>=0;n--){var o=e[n];"."===o?e.splice(n,1):".."===o?(e.splice(n,1),r++):r&&(e.splice(n,1),r--)}if(t)for(;r--;r)e.unshift("..");return e}function n(e,t){if(e.filter)return e.filter(t);for(var r=[],n=0;n<e.length;n++)t(e[n],n,e)&&r.push(e[n]);return r}var o=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/,i=function(e){return o.exec(e).slice(1)};r.resolve=function(){for(var r="",o=!1,i=arguments.length-1;i>=-1&&!o;i--){var s=i>=0?arguments[i]:e.cwd();if("string"!=typeof s)throw new TypeError("Arguments to path.resolve must be strings");s&&(r=s+"/"+r,o="/"===s.charAt(0))}return r=t(n(r.split("/"),function(e){return!!e}),!o).join("/"),(o?"/":"")+r||"."},r.normalize=function(e){var o=r.isAbsolute(e),i="/"===s(e,-1);return e=t(n(e.split("/"),function(e){return!!e}),!o).join("/"),e||o||(e="."),e&&i&&(e+="/"),(o?"/":"")+e},r.isAbsolute=function(e){return"/"===e.charAt(0)},r.join=function(){var e=Array.prototype.slice.call(arguments,0);return r.normalize(n(e,function(e){if("string"!=typeof e)throw new TypeError("Arguments to path.join must be strings");return e}).join("/"))},r.relative=function(e,t){function n(e){for(var t=0;t<e.length&&""===e[t];t++);for(var r=e.length-1;r>=0&&""===e[r];r--);return t>r?[]:e.slice(t,r-t+1)}e=r.resolve(e).substr(1),t=r.resolve(t).substr(1);for(var o=n(e.split("/")),i=n(t.split("/")),s=Math.min(o.length,i.length),a=s,u=0;s>u;u++)if(o[u]!==i[u]){a=u;break}for(var c=[],u=a;u<o.length;u++)c.push("..");return c=c.concat(i.slice(a)),c.join("/")},r.sep="/",r.delimiter=":",r.dirname=function(e){var t=i(e),r=t[0],n=t[1];return r||n?(n&&(n=n.substr(0,n.length-1)),r+n):"."},r.basename=function(e,t){var r=i(e)[2];return t&&r.substr(-1*t.length)===t&&(r=r.substr(0,r.length-t.length)),r},r.extname=function(e){return i(e)[3]};var s="b"==="ab".substr(-1)?function(e,t,r){return e.substr(t,r)}:function(e,t,r){return 0>t&&(t=e.length+t),e.substr(t,r)}}).call(this,e("_process"))},{_process:24}],24:[function(e,t){function r(){}var n=t.exports={};n.nextTick=function(){var e="undefined"!=typeof window&&window.setImmediate,t="undefined"!=typeof window&&window.MutationObserver,r="undefined"!=typeof window&&window.postMessage&&window.addEventListener;if(e)return function(e){return window.setImmediate(e)};var n=[];if(t){var o=document.createElement("div"),i=new MutationObserver(function(){var e=n.slice();n.length=0,e.forEach(function(e){e()})});return i.observe(o,{attributes:!0}),function(e){n.length||o.setAttribute("yes","no"),n.push(e)}}return r?(window.addEventListener("message",function(e){var t=e.source;if((t===window||null===t)&&"process-tick"===e.data&&(e.stopPropagation(),n.length>0)){var r=n.shift();r()}},!0),function(e){n.push(e),window.postMessage("process-tick","*")}):function(e){setTimeout(e,0)}}(),n.title="browser",n.browser=!0,n.env={},n.argv=[],n.on=r,n.addListener=r,n.once=r,n.off=r,n.removeListener=r,n.removeAllListeners=r,n.emit=r,n.binding=function(){throw new Error("process.binding is not supported")},n.cwd=function(){return"/"},n.chdir=function(){throw new Error("process.chdir is not supported")}},{}],25:[function(e,t){t.exports=e("./lib/_stream_duplex.js")},{"./lib/_stream_duplex.js":26}],26:[function(e,t){(function(r){function n(e){return this instanceof n?(u.call(this,e),c.call(this,e),e&&e.readable===!1&&(this.readable=!1),e&&e.writable===!1&&(this.writable=!1),this.allowHalfOpen=!0,e&&e.allowHalfOpen===!1&&(this.allowHalfOpen=!1),void this.once("end",o)):new n(e)}function o(){this.allowHalfOpen||this._writableState.ended||r.nextTick(this.end.bind(this)) +}function i(e,t){for(var r=0,n=e.length;n>r;r++)t(e[r],r)}t.exports=n;var s=Object.keys||function(e){var t=[];for(var r in e)t.push(r);return t},a=e("core-util-is");a.inherits=e("inherits");var u=e("./_stream_readable"),c=e("./_stream_writable");a.inherits(n,u),i(s(c.prototype),function(e){n.prototype[e]||(n.prototype[e]=c.prototype[e])})}).call(this,e("_process"))},{"./_stream_readable":28,"./_stream_writable":30,_process:24,"core-util-is":31,inherits:44}],27:[function(e,t){function r(e){return this instanceof r?void n.call(this,e):new r(e)}t.exports=r;var n=e("./_stream_transform"),o=e("core-util-is");o.inherits=e("inherits"),o.inherits(r,n),r.prototype._transform=function(e,t,r){r(null,e)}},{"./_stream_transform":29,"core-util-is":31,inherits:44}],28:[function(e,t){(function(r){function n(t){t=t||{};var r=t.highWaterMark;this.highWaterMark=r||0===r?r:16384,this.highWaterMark=~~this.highWaterMark,this.buffer=[],this.length=0,this.pipes=null,this.pipesCount=0,this.flowing=!1,this.ended=!1,this.endEmitted=!1,this.reading=!1,this.calledRead=!1,this.sync=!0,this.needReadable=!1,this.emittedReadable=!1,this.readableListening=!1,this.objectMode=!!t.objectMode,this.defaultEncoding=t.defaultEncoding||"utf8",this.ranOut=!1,this.awaitDrain=0,this.readingMore=!1,this.decoder=null,this.encoding=null,t.encoding&&(O||(O=e("string_decoder/").StringDecoder),this.decoder=new O(t.encoding),this.encoding=t.encoding)}function o(e){return this instanceof o?(this._readableState=new n(e,this),this.readable=!0,void A.call(this)):new o(e)}function i(e,t,r,n,o){var i=c(t,r);if(i)e.emit("error",i);else if(null===r||void 0===r)t.reading=!1,t.ended||f(e,t);else if(t.objectMode||r&&r.length>0)if(t.ended&&!o){var a=new Error("stream.push() after EOF");e.emit("error",a)}else if(t.endEmitted&&o){var a=new Error("stream.unshift() after end event");e.emit("error",a)}else!t.decoder||o||n||(r=t.decoder.write(r)),t.length+=t.objectMode?1:r.length,o?t.buffer.unshift(r):(t.reading=!1,t.buffer.push(r)),t.needReadable&&l(e),h(e,t);else o||(t.reading=!1);return s(t)}function s(e){return!e.ended&&(e.needReadable||e.length<e.highWaterMark||0===e.length)}function a(e){if(e>=R)e=R;else{e--;for(var t=1;32>t;t<<=1)e|=e>>t;e++}return e}function u(e,t){return 0===t.length&&t.ended?0:t.objectMode?0===e?0:1:null===e||isNaN(e)?t.flowing&&t.buffer.length?t.buffer[0].length:t.length:0>=e?0:(e>t.highWaterMark&&(t.highWaterMark=a(e)),e>t.length?t.ended?t.length:(t.needReadable=!0,0):e)}function c(e,t){var r=null;return k.isBuffer(t)||"string"==typeof t||null===t||void 0===t||e.objectMode||(r=new TypeError("Invalid non-string/buffer chunk")),r}function f(e,t){if(t.decoder&&!t.ended){var r=t.decoder.end();r&&r.length&&(t.buffer.push(r),t.length+=t.objectMode?1:r.length)}t.ended=!0,t.length>0?l(e):_(e)}function l(e){var t=e._readableState;t.needReadable=!1,t.emittedReadable||(t.emittedReadable=!0,t.sync?r.nextTick(function(){d(e)}):d(e))}function d(e){e.emit("readable")}function h(e,t){t.readingMore||(t.readingMore=!0,r.nextTick(function(){p(e,t)}))}function p(e,t){for(var r=t.length;!t.reading&&!t.flowing&&!t.ended&&t.length<t.highWaterMark&&(e.read(0),r!==t.length);)r=t.length;t.readingMore=!1}function v(e){return function(){var t=e._readableState;t.awaitDrain--,0===t.awaitDrain&&y(e)}}function y(e){function t(e){var t=e.write(r);!1===t&&n.awaitDrain++}var r,n=e._readableState;for(n.awaitDrain=0;n.pipesCount&&null!==(r=e.read());)if(1===n.pipesCount?t(n.pipes,0,null):w(n.pipes,t),e.emit("data",r),n.awaitDrain>0)return;return 0===n.pipesCount?(n.flowing=!1,void(S.listenerCount(e,"data")>0&&m(e))):void(n.ranOut=!0)}function g(){this._readableState.ranOut&&(this._readableState.ranOut=!1,y(this))}function m(e,t){var n=e._readableState;if(n.flowing)throw new Error("Cannot switch to old mode now.");var o=t||!1,i=!1;e.readable=!0,e.pipe=A.prototype.pipe,e.on=e.addListener=A.prototype.on,e.on("readable",function(){i=!0;for(var t;!o&&null!==(t=e.read());)e.emit("data",t);null===t&&(i=!1,e._readableState.needReadable=!0)}),e.pause=function(){o=!0,this.emit("pause")},e.resume=function(){o=!1,i?r.nextTick(function(){e.emit("readable")}):this.read(0),this.emit("resume")},e.emit("readable")}function b(e,t){var r,n=t.buffer,o=t.length,i=!!t.decoder,s=!!t.objectMode;if(0===n.length)return null;if(0===o)r=null;else if(s)r=n.shift();else if(!e||e>=o)r=i?n.join(""):k.concat(n,o),n.length=0;else if(e<n[0].length){var a=n[0];r=a.slice(0,e),n[0]=a.slice(e)}else if(e===n[0].length)r=n.shift();else{r=i?"":new k(e);for(var u=0,c=0,f=n.length;f>c&&e>u;c++){var a=n[0],l=Math.min(e-u,a.length);i?r+=a.slice(0,l):a.copy(r,u,0,l),l<a.length?n[0]=a.slice(l):n.shift(),u+=l}}return r}function _(e){var t=e._readableState;if(t.length>0)throw new Error("endReadable called on non-empty stream");!t.endEmitted&&t.calledRead&&(t.ended=!0,r.nextTick(function(){t.endEmitted||0!==t.length||(t.endEmitted=!0,e.readable=!1,e.emit("end"))}))}function w(e,t){for(var r=0,n=e.length;n>r;r++)t(e[r],r)}function E(e,t){for(var r=0,n=e.length;n>r;r++)if(e[r]===t)return r;return-1}t.exports=o;var x=e("isarray"),k=e("buffer").Buffer;o.ReadableState=n;var S=e("events").EventEmitter;S.listenerCount||(S.listenerCount=function(e,t){return e.listeners(t).length});var A=e("stream"),j=e("core-util-is");j.inherits=e("inherits");var O;j.inherits(o,A),o.prototype.push=function(e,t){var r=this._readableState;return"string"!=typeof e||r.objectMode||(t=t||r.defaultEncoding,t!==r.encoding&&(e=new k(e,t),t="")),i(this,r,e,t,!1)},o.prototype.unshift=function(e){var t=this._readableState;return i(this,t,e,"",!0)},o.prototype.setEncoding=function(t){O||(O=e("string_decoder/").StringDecoder),this._readableState.decoder=new O(t),this._readableState.encoding=t};var R=8388608;o.prototype.read=function(e){var t=this._readableState;t.calledRead=!0;var r,n=e;if(("number"!=typeof e||e>0)&&(t.emittedReadable=!1),0===e&&t.needReadable&&(t.length>=t.highWaterMark||t.ended))return l(this),null;if(e=u(e,t),0===e&&t.ended)return r=null,t.length>0&&t.decoder&&(r=b(e,t),t.length-=r.length),0===t.length&&_(this),r;var o=t.needReadable;return t.length-e<=t.highWaterMark&&(o=!0),(t.ended||t.reading)&&(o=!1),o&&(t.reading=!0,t.sync=!0,0===t.length&&(t.needReadable=!0),this._read(t.highWaterMark),t.sync=!1),o&&!t.reading&&(e=u(n,t)),r=e>0?b(e,t):null,null===r&&(t.needReadable=!0,e=0),t.length-=e,0!==t.length||t.ended||(t.needReadable=!0),t.ended&&!t.endEmitted&&0===t.length&&_(this),r},o.prototype._read=function(){this.emit("error",new Error("not implemented"))},o.prototype.pipe=function(e,t){function n(e){e===f&&i()}function o(){e.end()}function i(){e.removeListener("close",a),e.removeListener("finish",u),e.removeListener("drain",p),e.removeListener("error",s),e.removeListener("unpipe",n),f.removeListener("end",o),f.removeListener("end",i),(!e._writableState||e._writableState.needDrain)&&p()}function s(t){c(),e.removeListener("error",s),0===S.listenerCount(e,"error")&&e.emit("error",t)}function a(){e.removeListener("finish",u),c()}function u(){e.removeListener("close",a),c()}function c(){f.unpipe(e)}var f=this,l=this._readableState;switch(l.pipesCount){case 0:l.pipes=e;break;case 1:l.pipes=[l.pipes,e];break;default:l.pipes.push(e)}l.pipesCount+=1;var d=(!t||t.end!==!1)&&e!==r.stdout&&e!==r.stderr,h=d?o:i;l.endEmitted?r.nextTick(h):f.once("end",h),e.on("unpipe",n);var p=v(f);return e.on("drain",p),e._events&&e._events.error?x(e._events.error)?e._events.error.unshift(s):e._events.error=[s,e._events.error]:e.on("error",s),e.once("close",a),e.once("finish",u),e.emit("pipe",f),l.flowing||(this.on("readable",g),l.flowing=!0,r.nextTick(function(){y(f)})),e},o.prototype.unpipe=function(e){var t=this._readableState;if(0===t.pipesCount)return this;if(1===t.pipesCount)return e&&e!==t.pipes?this:(e||(e=t.pipes),t.pipes=null,t.pipesCount=0,this.removeListener("readable",g),t.flowing=!1,e&&e.emit("unpipe",this),this);if(!e){var r=t.pipes,n=t.pipesCount;t.pipes=null,t.pipesCount=0,this.removeListener("readable",g),t.flowing=!1;for(var o=0;n>o;o++)r[o].emit("unpipe",this);return this}var o=E(t.pipes,e);return-1===o?this:(t.pipes.splice(o,1),t.pipesCount-=1,1===t.pipesCount&&(t.pipes=t.pipes[0]),e.emit("unpipe",this),this)},o.prototype.on=function(e,t){var r=A.prototype.on.call(this,e,t);if("data"!==e||this._readableState.flowing||m(this),"readable"===e&&this.readable){var n=this._readableState;n.readableListening||(n.readableListening=!0,n.emittedReadable=!1,n.needReadable=!0,n.reading?n.length&&l(this,n):this.read(0))}return r},o.prototype.addListener=o.prototype.on,o.prototype.resume=function(){m(this),this.read(0),this.emit("resume")},o.prototype.pause=function(){m(this,!0),this.emit("pause")},o.prototype.wrap=function(e){var t=this._readableState,r=!1,n=this;e.on("end",function(){if(t.decoder&&!t.ended){var e=t.decoder.end();e&&e.length&&n.push(e)}n.push(null)}),e.on("data",function(o){if(t.decoder&&(o=t.decoder.write(o)),(!t.objectMode||null!==o&&void 0!==o)&&(t.objectMode||o&&o.length)){var i=n.push(o);i||(r=!0,e.pause())}});for(var o in e)"function"==typeof e[o]&&"undefined"==typeof this[o]&&(this[o]=function(t){return function(){return e[t].apply(e,arguments)}}(o));var i=["error","close","destroy","pause","resume"];return w(i,function(t){e.on(t,n.emit.bind(n,t))}),n._read=function(){r&&(r=!1,e.resume())},n},o._fromList=b}).call(this,e("_process"))},{_process:24,buffer:17,"core-util-is":31,events:21,inherits:44,isarray:22,stream:36,"string_decoder/":37}],29:[function(e,t){function r(e,t){this.afterTransform=function(e,r){return n(t,e,r)},this.needTransform=!1,this.transforming=!1,this.writecb=null,this.writechunk=null}function n(e,t,r){var n=e._transformState;n.transforming=!1;var o=n.writecb;if(!o)return e.emit("error",new Error("no writecb in Transform class"));n.writechunk=null,n.writecb=null,null!==r&&void 0!==r&&e.push(r),o&&o(t);var i=e._readableState;i.reading=!1,(i.needReadable||i.length<i.highWaterMark)&&e._read(i.highWaterMark)}function o(e){if(!(this instanceof o))return new o(e);s.call(this,e);var t=(this._transformState=new r(e,this),this);this._readableState.needReadable=!0,this._readableState.sync=!1,this.once("finish",function(){"function"==typeof this._flush?this._flush(function(e){i(t,e)}):i(t)})}function i(e,t){if(t)return e.emit("error",t);var r=e._writableState,n=(e._readableState,e._transformState);if(r.length)throw new Error("calling transform done when ws.length != 0");if(n.transforming)throw new Error("calling transform done when still transforming");return e.push(null)}t.exports=o;var s=e("./_stream_duplex"),a=e("core-util-is");a.inherits=e("inherits"),a.inherits(o,s),o.prototype.push=function(e,t){return this._transformState.needTransform=!1,s.prototype.push.call(this,e,t)},o.prototype._transform=function(){throw new Error("not implemented")},o.prototype._write=function(e,t,r){var n=this._transformState;if(n.writecb=r,n.writechunk=e,n.writeencoding=t,!n.transforming){var o=this._readableState;(n.needTransform||o.needReadable||o.length<o.highWaterMark)&&this._read(o.highWaterMark)}},o.prototype._read=function(){var e=this._transformState;null!==e.writechunk&&e.writecb&&!e.transforming?(e.transforming=!0,this._transform(e.writechunk,e.writeencoding,e.afterTransform)):e.needTransform=!0}},{"./_stream_duplex":26,"core-util-is":31,inherits:44}],30:[function(e,t){(function(r){function n(e,t,r){this.chunk=e,this.encoding=t,this.callback=r}function o(e,t){e=e||{};var r=e.highWaterMark;this.highWaterMark=r||0===r?r:16384,this.objectMode=!!e.objectMode,this.highWaterMark=~~this.highWaterMark,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1;var n=e.decodeStrings===!1;this.decodeStrings=!n,this.defaultEncoding=e.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(e){h(t,e)},this.writecb=null,this.writelen=0,this.buffer=[],this.errorEmitted=!1}function i(t){var r=e("./_stream_duplex");return this instanceof i||this instanceof r?(this._writableState=new o(t,this),this.writable=!0,void E.call(this)):new i(t)}function s(e,t,n){var o=new Error("write after end");e.emit("error",o),r.nextTick(function(){n(o)})}function a(e,t,n,o){var i=!0;if(!_.isBuffer(n)&&"string"!=typeof n&&null!==n&&void 0!==n&&!t.objectMode){var s=new TypeError("Invalid non-string/buffer chunk");e.emit("error",s),r.nextTick(function(){o(s)}),i=!1}return i}function u(e,t,r){return e.objectMode||e.decodeStrings===!1||"string"!=typeof t||(t=new _(t,r)),t}function c(e,t,r,o,i){r=u(t,r,o),_.isBuffer(r)&&(o="buffer");var s=t.objectMode?1:r.length;t.length+=s;var a=t.length<t.highWaterMark;return a||(t.needDrain=!0),t.writing?t.buffer.push(new n(r,o,i)):f(e,t,s,r,o,i),a}function f(e,t,r,n,o,i){t.writelen=r,t.writecb=i,t.writing=!0,t.sync=!0,e._write(n,o,t.onwrite),t.sync=!1}function l(e,t,n,o,i){n?r.nextTick(function(){i(o)}):i(o),e._writableState.errorEmitted=!0,e.emit("error",o)}function d(e){e.writing=!1,e.writecb=null,e.length-=e.writelen,e.writelen=0}function h(e,t){var n=e._writableState,o=n.sync,i=n.writecb;if(d(n),t)l(e,n,o,t,i);else{var s=g(e,n);s||n.bufferProcessing||!n.buffer.length||y(e,n),o?r.nextTick(function(){p(e,n,s,i)}):p(e,n,s,i)}}function p(e,t,r,n){r||v(e,t),n(),r&&m(e,t)}function v(e,t){0===t.length&&t.needDrain&&(t.needDrain=!1,e.emit("drain"))}function y(e,t){t.bufferProcessing=!0;for(var r=0;r<t.buffer.length;r++){var n=t.buffer[r],o=n.chunk,i=n.encoding,s=n.callback,a=t.objectMode?1:o.length;if(f(e,t,a,o,i,s),t.writing){r++;break}}t.bufferProcessing=!1,r<t.buffer.length?t.buffer=t.buffer.slice(r):t.buffer.length=0}function g(e,t){return t.ending&&0===t.length&&!t.finished&&!t.writing}function m(e,t){var r=g(e,t);return r&&(t.finished=!0,e.emit("finish")),r}function b(e,t,n){t.ending=!0,m(e,t),n&&(t.finished?r.nextTick(n):e.once("finish",n)),t.ended=!0}t.exports=i;var _=e("buffer").Buffer;i.WritableState=o;var w=e("core-util-is");w.inherits=e("inherits");var E=e("stream");w.inherits(i,E),i.prototype.pipe=function(){this.emit("error",new Error("Cannot pipe. Not readable."))},i.prototype.write=function(e,t,r){var n=this._writableState,o=!1;return"function"==typeof t&&(r=t,t=null),_.isBuffer(e)?t="buffer":t||(t=n.defaultEncoding),"function"!=typeof r&&(r=function(){}),n.ended?s(this,n,r):a(this,n,e,r)&&(o=c(this,n,e,t,r)),o},i.prototype._write=function(e,t,r){r(new Error("not implemented"))},i.prototype.end=function(e,t,r){var n=this._writableState;"function"==typeof e?(r=e,e=null,t=null):"function"==typeof t&&(r=t,t=null),"undefined"!=typeof e&&null!==e&&this.write(e,t),n.ending||n.finished||b(this,n,r)}}).call(this,e("_process"))},{"./_stream_duplex":26,_process:24,buffer:17,"core-util-is":31,inherits:44,stream:36}],31:[function(e,t,r){(function(e){function t(e){return Array.isArray(e)}function n(e){return"boolean"==typeof e}function o(e){return null===e}function i(e){return null==e}function s(e){return"number"==typeof e}function a(e){return"string"==typeof e}function u(e){return"symbol"==typeof e}function c(e){return void 0===e}function f(e){return l(e)&&"[object RegExp]"===g(e)}function l(e){return"object"==typeof e&&null!==e}function d(e){return l(e)&&"[object Date]"===g(e)}function h(e){return l(e)&&("[object Error]"===g(e)||e instanceof Error)}function p(e){return"function"==typeof e}function v(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||"undefined"==typeof e}function y(t){return e.isBuffer(t)}function g(e){return Object.prototype.toString.call(e)}r.isArray=t,r.isBoolean=n,r.isNull=o,r.isNullOrUndefined=i,r.isNumber=s,r.isString=a,r.isSymbol=u,r.isUndefined=c,r.isRegExp=f,r.isObject=l,r.isDate=d,r.isError=h,r.isFunction=p,r.isPrimitive=v,r.isBuffer=y}).call(this,e("buffer").Buffer)},{buffer:17}],32:[function(e,t){t.exports=e("./lib/_stream_passthrough.js")},{"./lib/_stream_passthrough.js":27}],33:[function(e,t,r){var n=e("stream");r=t.exports=e("./lib/_stream_readable.js"),r.Stream=n,r.Readable=r,r.Writable=e("./lib/_stream_writable.js"),r.Duplex=e("./lib/_stream_duplex.js"),r.Transform=e("./lib/_stream_transform.js"),r.PassThrough=e("./lib/_stream_passthrough.js")},{"./lib/_stream_duplex.js":26,"./lib/_stream_passthrough.js":27,"./lib/_stream_readable.js":28,"./lib/_stream_transform.js":29,"./lib/_stream_writable.js":30,stream:36}],34:[function(e,t){t.exports=e("./lib/_stream_transform.js")},{"./lib/_stream_transform.js":29}],35:[function(e,t){t.exports=e("./lib/_stream_writable.js")},{"./lib/_stream_writable.js":30}],36:[function(e,t){function r(){n.call(this)}t.exports=r;var n=e("events").EventEmitter,o=e("inherits");o(r,n),r.Readable=e("readable-stream/readable.js"),r.Writable=e("readable-stream/writable.js"),r.Duplex=e("readable-stream/duplex.js"),r.Transform=e("readable-stream/transform.js"),r.PassThrough=e("readable-stream/passthrough.js"),r.Stream=r,r.prototype.pipe=function(e,t){function r(t){e.writable&&!1===e.write(t)&&c.pause&&c.pause()}function o(){c.readable&&c.resume&&c.resume()}function i(){f||(f=!0,e.end())}function s(){f||(f=!0,"function"==typeof e.destroy&&e.destroy())}function a(e){if(u(),0===n.listenerCount(this,"error"))throw e}function u(){c.removeListener("data",r),e.removeListener("drain",o),c.removeListener("end",i),c.removeListener("close",s),c.removeListener("error",a),e.removeListener("error",a),c.removeListener("end",u),c.removeListener("close",u),e.removeListener("close",u)}var c=this;c.on("data",r),e.on("drain",o),e._isStdio||t&&t.end===!1||(c.on("end",i),c.on("close",s));var f=!1;return c.on("error",a),e.on("error",a),c.on("end",u),c.on("close",u),e.on("close",u),e.emit("pipe",c),e}},{events:21,inherits:44,"readable-stream/duplex.js":25,"readable-stream/passthrough.js":32,"readable-stream/readable.js":33,"readable-stream/transform.js":34,"readable-stream/writable.js":35}],37:[function(e,t,r){function n(e){if(e&&!u(e))throw new Error("Unknown encoding: "+e)}function o(e){return e.toString(this.encoding)}function i(e){this.charReceived=e.length%2,this.charLength=this.charReceived?2:0}function s(e){this.charReceived=e.length%3,this.charLength=this.charReceived?3:0}var a=e("buffer").Buffer,u=a.isEncoding||function(e){switch(e&&e.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}},c=r.StringDecoder=function(e){switch(this.encoding=(e||"utf8").toLowerCase().replace(/[-_]/,""),n(e),this.encoding){case"utf8":this.surrogateSize=3;break;case"ucs2":case"utf16le":this.surrogateSize=2,this.detectIncompleteChar=i;break;case"base64":this.surrogateSize=3,this.detectIncompleteChar=s;break;default:return void(this.write=o)}this.charBuffer=new a(6),this.charReceived=0,this.charLength=0};c.prototype.write=function(e){for(var t="";this.charLength;){var r=e.length>=this.charLength-this.charReceived?this.charLength-this.charReceived:e.length;if(e.copy(this.charBuffer,this.charReceived,0,r),this.charReceived+=r,this.charReceived<this.charLength)return"";e=e.slice(r,e.length),t=this.charBuffer.slice(0,this.charLength).toString(this.encoding);var n=t.charCodeAt(t.length-1);if(!(n>=55296&&56319>=n)){if(this.charReceived=this.charLength=0,0===e.length)return t;break}this.charLength+=this.surrogateSize,t=""}this.detectIncompleteChar(e);var o=e.length;this.charLength&&(e.copy(this.charBuffer,0,e.length-this.charReceived,o),o-=this.charReceived),t+=e.toString(this.encoding,0,o);var o=t.length-1,n=t.charCodeAt(o);if(n>=55296&&56319>=n){var i=this.surrogateSize;return this.charLength+=i,this.charReceived+=i,this.charBuffer.copy(this.charBuffer,i,0,i),e.copy(this.charBuffer,0,0,i),t.substring(0,o)}return t},c.prototype.detectIncompleteChar=function(e){for(var t=e.length>=3?3:e.length;t>0;t--){var r=e[e.length-t];if(1==t&&r>>5==6){this.charLength=2;break}if(2>=t&&r>>4==14){this.charLength=3;break}if(3>=t&&r>>3==30){this.charLength=4;break}}this.charReceived=t},c.prototype.end=function(e){var t="";if(e&&e.length&&(t=this.write(e)),this.charReceived){var r=this.charReceived,n=this.charBuffer,o=this.encoding;t+=n.slice(0,r).toString(o)}return t}},{buffer:17}],38:[function(e,t){t.exports=function(e){return e&&"object"==typeof e&&"function"==typeof e.copy&&"function"==typeof e.fill&&"function"==typeof e.readUInt8}},{}],39:[function(e,t,r){(function(t,n){function o(e,t){var n={seen:[],stylize:s};return arguments.length>=3&&(n.depth=arguments[2]),arguments.length>=4&&(n.colors=arguments[3]),v(t)?n.showHidden=t:t&&r._extend(n,t),w(n.showHidden)&&(n.showHidden=!1),w(n.depth)&&(n.depth=2),w(n.colors)&&(n.colors=!1),w(n.customInspect)&&(n.customInspect=!0),n.colors&&(n.stylize=i),u(n,e,n.depth)}function i(e,t){var r=o.styles[t];return r?"["+o.colors[r][0]+"m"+e+"["+o.colors[r][1]+"m":e}function s(e){return e}function a(e){var t={};return e.forEach(function(e){t[e]=!0}),t}function u(e,t,n){if(e.customInspect&&t&&A(t.inspect)&&t.inspect!==r.inspect&&(!t.constructor||t.constructor.prototype!==t)){var o=t.inspect(n,e);return b(o)||(o=u(e,o,n)),o}var i=c(e,t);if(i)return i;var s=Object.keys(t),v=a(s);if(e.showHidden&&(s=Object.getOwnPropertyNames(t)),S(t)&&(s.indexOf("message")>=0||s.indexOf("description")>=0))return f(t);if(0===s.length){if(A(t)){var y=t.name?": "+t.name:"";return e.stylize("[Function"+y+"]","special")}if(E(t))return e.stylize(RegExp.prototype.toString.call(t),"regexp");if(k(t))return e.stylize(Date.prototype.toString.call(t),"date");if(S(t))return f(t)}var g="",m=!1,_=["{","}"];if(p(t)&&(m=!0,_=["[","]"]),A(t)){var w=t.name?": "+t.name:"";g=" [Function"+w+"]"}if(E(t)&&(g=" "+RegExp.prototype.toString.call(t)),k(t)&&(g=" "+Date.prototype.toUTCString.call(t)),S(t)&&(g=" "+f(t)),0===s.length&&(!m||0==t.length))return _[0]+g+_[1];if(0>n)return E(t)?e.stylize(RegExp.prototype.toString.call(t),"regexp"):e.stylize("[Object]","special");e.seen.push(t);var x;return x=m?l(e,t,n,v,s):s.map(function(r){return d(e,t,n,v,r,m)}),e.seen.pop(),h(x,g,_)}function c(e,t){if(w(t))return e.stylize("undefined","undefined");if(b(t)){var r="'"+JSON.stringify(t).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return e.stylize(r,"string")}return m(t)?e.stylize(""+t,"number"):v(t)?e.stylize(""+t,"boolean"):y(t)?e.stylize("null","null"):void 0}function f(e){return"["+Error.prototype.toString.call(e)+"]"}function l(e,t,r,n,o){for(var i=[],s=0,a=t.length;a>s;++s)i.push(N(t,String(s))?d(e,t,r,n,String(s),!0):"");return o.forEach(function(o){o.match(/^\d+$/)||i.push(d(e,t,r,n,o,!0))}),i}function d(e,t,r,n,o,i){var s,a,c;if(c=Object.getOwnPropertyDescriptor(t,o)||{value:t[o]},c.get?a=c.set?e.stylize("[Getter/Setter]","special"):e.stylize("[Getter]","special"):c.set&&(a=e.stylize("[Setter]","special")),N(n,o)||(s="["+o+"]"),a||(e.seen.indexOf(c.value)<0?(a=y(r)?u(e,c.value,null):u(e,c.value,r-1),a.indexOf("\n")>-1&&(a=i?a.split("\n").map(function(e){return" "+e}).join("\n").substr(2):"\n"+a.split("\n").map(function(e){return" "+e}).join("\n"))):a=e.stylize("[Circular]","special")),w(s)){if(i&&o.match(/^\d+$/))return a;s=JSON.stringify(""+o),s.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(s=s.substr(1,s.length-2),s=e.stylize(s,"name")):(s=s.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),s=e.stylize(s,"string"))}return s+": "+a}function h(e,t,r){var n=0,o=e.reduce(function(e,t){return n++,t.indexOf("\n")>=0&&n++,e+t.replace(/\u001b\[\d\d?m/g,"").length+1},0);return o>60?r[0]+(""===t?"":t+"\n ")+" "+e.join(",\n ")+" "+r[1]:r[0]+t+" "+e.join(", ")+" "+r[1]}function p(e){return Array.isArray(e)}function v(e){return"boolean"==typeof e}function y(e){return null===e}function g(e){return null==e}function m(e){return"number"==typeof e}function b(e){return"string"==typeof e}function _(e){return"symbol"==typeof e}function w(e){return void 0===e}function E(e){return x(e)&&"[object RegExp]"===O(e)}function x(e){return"object"==typeof e&&null!==e}function k(e){return x(e)&&"[object Date]"===O(e)}function S(e){return x(e)&&("[object Error]"===O(e)||e instanceof Error)}function A(e){return"function"==typeof e}function j(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||"undefined"==typeof e}function O(e){return Object.prototype.toString.call(e)}function R(e){return 10>e?"0"+e.toString(10):e.toString(10)}function I(){var e=new Date,t=[R(e.getHours()),R(e.getMinutes()),R(e.getSeconds())].join(":");return[e.getDate(),B[e.getMonth()],t].join(" ")}function N(e,t){return Object.prototype.hasOwnProperty.call(e,t)}var T=/%[sdj%]/g;r.format=function(e){if(!b(e)){for(var t=[],r=0;r<arguments.length;r++)t.push(o(arguments[r]));return t.join(" ")}for(var r=1,n=arguments,i=n.length,s=String(e).replace(T,function(e){if("%"===e)return"%";if(r>=i)return e;switch(e){case"%s":return String(n[r++]);case"%d":return Number(n[r++]);case"%j":try{return JSON.stringify(n[r++])}catch(t){return"[Circular]"}default:return e}}),a=n[r];i>r;a=n[++r])s+=y(a)||!x(a)?" "+a:" "+o(a);return s},r.deprecate=function(e,o){function i(){if(!s){if(t.throwDeprecation)throw new Error(o);t.traceDeprecation?console.trace(o):console.error(o),s=!0}return e.apply(this,arguments)}if(w(n.process))return function(){return r.deprecate(e,o).apply(this,arguments)};if(t.noDeprecation===!0)return e;var s=!1;return i};var L,D={};r.debuglog=function(e){if(w(L)&&(L=t.env.NODE_DEBUG||""),e=e.toUpperCase(),!D[e])if(new RegExp("\\b"+e+"\\b","i").test(L)){var n=t.pid;D[e]=function(){var t=r.format.apply(r,arguments);console.error("%s %d: %s",e,n,t)}}else D[e]=function(){};return D[e]},r.inspect=o,o.colors={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},o.styles={special:"cyan",number:"yellow","boolean":"yellow",undefined:"grey","null":"bold",string:"green",date:"magenta",regexp:"red"},r.isArray=p,r.isBoolean=v,r.isNull=y,r.isNullOrUndefined=g,r.isNumber=m,r.isString=b,r.isSymbol=_,r.isUndefined=w,r.isRegExp=E,r.isObject=x,r.isDate=k,r.isError=S,r.isFunction=A,r.isPrimitive=j,r.isBuffer=e("./support/isBuffer");var B=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];r.log=function(){console.log("%s - %s",I(),r.format.apply(r,arguments))},r.inherits=e("inherits"),r._extend=function(e,t){if(!t||!x(t))return e;for(var r=Object.keys(t),n=r.length;n--;)e[r[n]]=t[r[n]];return e}}).call(this,e("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./support/isBuffer":38,_process:24,inherits:44}],40:[function(e,t,r){function n(){return"WebkitAppearance"in document.documentElement.style||window.console&&(console.firebug||console.exception&&console.table)||navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)&&parseInt(RegExp.$1,10)>=31}function o(){var e=arguments,t=this.useColors;if(e[0]=(t?"%c":"")+this.namespace+(t?" %c":" ")+e[0]+(t?"%c ":" ")+"+"+r.humanize(this.diff),!t)return e;var n="color: "+this.color;e=[e[0],n,"color: inherit"].concat(Array.prototype.slice.call(e,1));var o=0,i=0;return e[0].replace(/%[a-z%]/g,function(e){"%"!==e&&(o++,"%c"===e&&(i=o))}),e.splice(i,0,n),e}function i(){return"object"==typeof console&&"function"==typeof console.log&&Function.prototype.apply.call(console.log,console,arguments)}function s(e){try{null==e?localStorage.removeItem("debug"):localStorage.debug=e}catch(t){}}function a(){var e;try{e=localStorage.debug}catch(t){}return e}r=t.exports=e("./debug"),r.log=i,r.formatArgs=o,r.save=s,r.load=a,r.useColors=n,r.colors=["lightseagreen","forestgreen","goldenrod","dodgerblue","darkorchid","crimson"],r.formatters.j=function(e){return JSON.stringify(e)},r.enable(a())},{"./debug":41}],41:[function(e,t,r){function n(){return r.colors[f++%r.colors.length]}function o(e){function t(){}function o(){var e=o,t=+new Date,i=t-(c||t);e.diff=i,e.prev=c,e.curr=t,c=t,null==e.useColors&&(e.useColors=r.useColors()),null==e.color&&e.useColors&&(e.color=n());var s=Array.prototype.slice.call(arguments);s[0]=r.coerce(s[0]),"string"!=typeof s[0]&&(s=["%o"].concat(s));var a=0;s[0]=s[0].replace(/%([a-z%])/g,function(t,n){if("%"===t)return t;a++;var o=r.formatters[n];if("function"==typeof o){var i=s[a];t=o.call(e,i),s.splice(a,1),a--}return t}),"function"==typeof r.formatArgs&&(s=r.formatArgs.apply(e,s));var u=o.log||r.log||console.log.bind(console);u.apply(e,s)}t.enabled=!1,o.enabled=!0;var i=r.enabled(e)?o:t;return i.namespace=e,i}function i(e){r.save(e);for(var t=(e||"").split(/[\s,]+/),n=t.length,o=0;n>o;o++)t[o]&&(e=t[o].replace(/\*/g,".*?"),"-"===e[0]?r.skips.push(new RegExp("^"+e.substr(1)+"$")):r.names.push(new RegExp("^"+e+"$")))}function s(){r.enable("")}function a(e){var t,n;for(t=0,n=r.skips.length;n>t;t++)if(r.skips[t].test(e))return!1;for(t=0,n=r.names.length;n>t;t++)if(r.names[t].test(e))return!0;return!1}function u(e){return e instanceof Error?e.stack||e.message:e}r=t.exports=o,r.coerce=u,r.disable=s,r.enable=i,r.enabled=a,r.humanize=e("ms"),r.names=[],r.skips=[],r.formatters={};var c,f=0},{ms:42}],42:[function(e,t){function r(e){var t=/^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(e);if(t){var r=parseFloat(t[1]),n=(t[2]||"ms").toLowerCase();switch(n){case"years":case"year":case"y":return r*f;case"days":case"day":case"d":return r*c;case"hours":case"hour":case"h":return r*u;case"minutes":case"minute":case"m":return r*a;case"seconds":case"second":case"s":return r*s;case"ms":return r}}}function n(e){return e>=c?Math.round(e/c)+"d":e>=u?Math.round(e/u)+"h":e>=a?Math.round(e/a)+"m":e>=s?Math.round(e/s)+"s":e+"ms"}function o(e){return i(e,c,"day")||i(e,u,"hour")||i(e,a,"minute")||i(e,s,"second")||e+" ms"}function i(e,t,r){return t>e?void 0:1.5*t>e?Math.floor(e/t)+" "+r:Math.ceil(e/t)+" "+r+"s"}var s=1e3,a=60*s,u=60*a,c=24*u,f=365.25*c;t.exports=function(e,t){return t=t||{},"string"==typeof e?r(e):t.long?o(e):n(e)}},{}],43:[function(e,t){"use strict";function r(e){if(this._capacity=i(e),this._length=0,this._front=0,this._makeCapacity(),s(e)){for(var t=e.length,r=0;t>r;++r)this[r]=e[r];this._length=t}}function n(e,t,r,n,o){for(var i=0;o>i;++i)r[i+n]=e[i+t]}function o(e){return e>>>=0,e-=1,e|=e>>1,e|=e>>2,e|=e>>4,e|=e>>8,e|=e>>16,e+1}function i(e){if("number"!=typeof e){if(!s(e))return 16;e=e.length}return o(Math.min(Math.max(16,e),1073741824))}r.prototype.toArray=function(){for(var e=this._length,t=new Array(e),r=this._front,n=this._capacity,o=0;e>o;++o)t[o]=this[r+o&n-1];return t},r.prototype.push=function(e){var t=arguments.length,r=this._length;if(t>1){var n=this._capacity;if(r+t>n){for(var o=0;t>o;++o){this._checkCapacity(r+1);var i=this._front+r&this._capacity-1;this[i]=arguments[o],r++,this._length=r}return r}for(var i=this._front,o=0;t>o;++o)this[i+r&n-1]=arguments[o],i++;return this._length=r+t,r+t}if(0===t)return r;this._checkCapacity(r+1);var o=this._front+r&this._capacity-1;return this[o]=e,this._length=r+1,r+1},r.prototype.pop=function(){var e=this._length;if(0===e)return void 0;var t=this._front+e-1&this._capacity-1,r=this[t];return this[t]=void 0,this._length=e-1,r},r.prototype.shift=function(){var e=this._length;if(0===e)return void 0;var t=this._front,r=this[t];return this[t]=void 0,this._front=t+1&this._capacity-1,this._length=e-1,r},r.prototype.unshift=function(e){var t=this._length,r=arguments.length;if(r>1){var n=this._capacity;if(t+r>n){for(var o=r-1;o>=0;o--){this._checkCapacity(t+1);var n=this._capacity,i=(this._front-1&n-1^n)-n;this[i]=arguments[o],t++,this._length=t,this._front=i}return t}for(var s=this._front,o=r-1;o>=0;o--){var i=(s-1&n-1^n)-n;this[i]=arguments[o],s=i}return this._front=s,this._length=t+r,t+r}if(0===r)return t;this._checkCapacity(t+1);var n=this._capacity,o=(this._front-1&n-1^n)-n;return this[o]=e,this._length=t+1,this._front=o,t+1},r.prototype.peekBack=function(){var e=this._length;if(0===e)return void 0;var t=this._front+e-1&this._capacity-1;return this[t]},r.prototype.peekFront=function(){return 0===this._length?void 0:this[this._front] +},r.prototype.get=function(e){var t=e;if(t!==(0|t))return void 0;var r=this._length;return 0>t&&(t+=r),0>t||t>=r?void 0:this[this._front+t&this._capacity-1]},r.prototype.isEmpty=function(){return 0===this._length},r.prototype.clear=function(){this._length=0,this._front=0,this._makeCapacity()},r.prototype.toString=function(){return this.toArray().toString()},r.prototype.valueOf=r.prototype.toString,r.prototype.removeFront=r.prototype.shift,r.prototype.removeBack=r.prototype.pop,r.prototype.insertFront=r.prototype.unshift,r.prototype.insertBack=r.prototype.push,r.prototype.enqueue=r.prototype.push,r.prototype.dequeue=r.prototype.shift,r.prototype.toJSON=r.prototype.toArray,Object.defineProperty(r.prototype,"length",{get:function(){return this._length},set:function(){throw new RangeError("")}}),r.prototype._makeCapacity=function(){for(var e=this._capacity,t=0;e>t;++t)this[t]=void 0},r.prototype._checkCapacity=function(e){this._capacity<e&&this._resizeTo(i(1.5*this._capacity+16))},r.prototype._resizeTo=function(e){var t=this._front,r=this._capacity,o=new Array(r),i=this._length;if(n(this,0,o,0,r),this._capacity=e,this._makeCapacity(),this._front=0,r>=t+i)n(o,t,this,0,i);else{var s=i-(t+i&r-1);n(o,t,this,0,s),n(o,0,this,s,i-s)}};var s=Array.isArray;t.exports=r},{}],44:[function(e,t){t.exports="function"==typeof Object.create?function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:function(e,t){e.super_=t;var r=function(){};r.prototype=t.prototype,e.prototype=new r,e.prototype.constructor=e}},{}],45:[function(e,t){function r(e,t){t||(t={}),this.options=t,o.call(this,e),this._order=t.reverse?"DESC":"ASC",this._limit=t.limit,this._count=0,this._done=!1;var r=i.lowerBound(t),n=i.upperBound(t);this._keyRange=r||n?this.db.makeKeyRange({lower:r,upper:n,excludeLower:i.lowerBoundExclusive(t),excludeUpper:i.upperBoundExclusive(t)}):null,this.callback=null}var n=e("util"),o=e("abstract-leveldown").AbstractIterator,i=e("ltgt");t.exports=r,n.inherits(r,o),r.prototype.createIterator=function(){var e=this;e.iterator=e.db.iterate(function(){e.onItem.apply(e,arguments)},{keyRange:e._keyRange,autoContinue:!1,order:e._order,onError:function(e){console.log("horrible error",e)}})},r.prototype.onItem=function(e,t){if(!t&&this.callback)return this.callback(),void(this.callback=!1);var r=!0;this._limit&&this._limit>0&&this._count++>=this._limit&&(r=!1),r&&this.callback(!1,t.key,t.value),t&&t["continue"]()},r.prototype._next=function(e){return e?(this._started||(this.createIterator(),this._started=!0),void(this.callback=e)):new Error("next() requires a callback argument")}},{"abstract-leveldown":48,ltgt:52,util:39}],46:[function(e,t){(function(e){function r(e){this._db=e,this._operations=[],this._written=!1}r.prototype._checkWritten=function(){if(this._written)throw new Error("write() already called on this batch")},r.prototype.put=function(e,t){this._checkWritten();var r=this._db._checkKeyValue(e,"key",this._db._isBuffer);if(r)throw r;if(r=this._db._checkKeyValue(t,"value",this._db._isBuffer))throw r;return this._db._isBuffer(e)||(e=String(e)),this._db._isBuffer(t)||(t=String(t)),"function"==typeof this._put?this._put(e,t):this._operations.push({type:"put",key:e,value:t}),this},r.prototype.del=function(e){this._checkWritten();var t=this._db._checkKeyValue(e,"key",this._db._isBuffer);if(t)throw t;return this._db._isBuffer(e)||(e=String(e)),"function"==typeof this._del?this._del(e):this._operations.push({type:"del",key:e}),this},r.prototype.clear=function(){return this._checkWritten(),this._operations=[],"function"==typeof this._clear&&this._clear(),this},r.prototype.write=function(t,r){if(this._checkWritten(),"function"==typeof t&&(r=t),"function"!=typeof r)throw new Error("write() requires a callback argument");return"object"!=typeof t&&(t={}),this._written=!0,"function"==typeof this._write?this._write(r):"function"==typeof this._db._batch?this._db._batch(this._operations,t,r):void e.nextTick(r)},t.exports=r}).call(this,e("_process"))},{_process:24}],47:[function(e,t){(function(e){function r(e){this.db=e,this._ended=!1,this._nexting=!1}r.prototype.next=function(t){var r=this;if("function"!=typeof t)throw new Error("next() requires a callback argument");return r._ended?t(new Error("cannot call next() after end()")):r._nexting?t(new Error("cannot call next() before previous next() has completed")):(r._nexting=!0,"function"==typeof r._next?r._next(function(){r._nexting=!1,t.apply(null,arguments)}):void e.nextTick(function(){r._nexting=!1,t()}))},r.prototype.end=function(t){if("function"!=typeof t)throw new Error("end() requires a callback argument");return this._ended?t(new Error("end() already called on iterator")):(this._ended=!0,"function"==typeof this._end?this._end(t):void e.nextTick(t))},t.exports=r}).call(this,e("_process"))},{_process:24}],48:[function(e,t){(function(r,n){function o(e){if(!arguments.length||void 0===e)throw new Error("constructor requires at least a location argument");if("string"!=typeof e)throw new Error("constructor requires a location string argument");this.location=e}var i=e("xtend"),s=e("./abstract-iterator"),a=e("./abstract-chained-batch");o.prototype.open=function(e,t){if("function"==typeof e&&(t=e),"function"!=typeof t)throw new Error("open() requires a callback argument");return"object"!=typeof e&&(e={}),"function"==typeof this._open?this._open(e,t):void r.nextTick(t)},o.prototype.close=function(e){if("function"!=typeof e)throw new Error("close() requires a callback argument");return"function"==typeof this._close?this._close(e):void r.nextTick(e)},o.prototype.get=function(e,t,n){var o;if("function"==typeof t&&(n=t),"function"!=typeof n)throw new Error("get() requires a callback argument");return(o=this._checkKeyValue(e,"key",this._isBuffer))?n(o):(this._isBuffer(e)||(e=String(e)),"object"!=typeof t&&(t={}),"function"==typeof this._get?this._get(e,t,n):void r.nextTick(function(){n(new Error("NotFound"))}))},o.prototype.put=function(e,t,n,o){var i;if("function"==typeof n&&(o=n),"function"!=typeof o)throw new Error("put() requires a callback argument");return(i=this._checkKeyValue(e,"key",this._isBuffer))?o(i):(i=this._checkKeyValue(t,"value",this._isBuffer))?o(i):(this._isBuffer(e)||(e=String(e)),this._isBuffer(t)||r.browser||(t=String(t)),"object"!=typeof n&&(n={}),"function"==typeof this._put?this._put(e,t,n,o):void r.nextTick(o))},o.prototype.del=function(e,t,n){var o;if("function"==typeof t&&(n=t),"function"!=typeof n)throw new Error("del() requires a callback argument");return(o=this._checkKeyValue(e,"key",this._isBuffer))?n(o):(this._isBuffer(e)||(e=String(e)),"object"!=typeof t&&(t={}),"function"==typeof this._del?this._del(e,t,n):void r.nextTick(n))},o.prototype.batch=function(e,t,n){if(!arguments.length)return this._chainedBatch();if("function"==typeof t&&(n=t),"function"!=typeof n)throw new Error("batch(array) requires a callback argument");if(!Array.isArray(e))return n(new Error("batch(array) requires an array argument"));"object"!=typeof t&&(t={});for(var o,i,s=0,a=e.length;a>s;s++)if(o=e[s],"object"==typeof o){if(i=this._checkKeyValue(o.type,"type",this._isBuffer))return n(i);if(i=this._checkKeyValue(o.key,"key",this._isBuffer))return n(i);if("put"==o.type&&(i=this._checkKeyValue(o.value,"value",this._isBuffer)))return n(i)}return"function"==typeof this._batch?this._batch(e,t,n):void r.nextTick(n)},o.prototype.approximateSize=function(e,t,n){if(null==e||null==t||"function"==typeof e||"function"==typeof t)throw new Error("approximateSize() requires valid `start`, `end` and `callback` arguments");if("function"!=typeof n)throw new Error("approximateSize() requires a callback argument");return this._isBuffer(e)||(e=String(e)),this._isBuffer(t)||(t=String(t)),"function"==typeof this._approximateSize?this._approximateSize(e,t,n):void r.nextTick(function(){n(null,0)})},o.prototype._setupIteratorOptions=function(e){var t=this;return e=i(e),["start","end","gt","gte","lt","lte"].forEach(function(r){e[r]&&t._isBuffer(e[r])&&0===e[r].length&&delete e[r]}),e.reverse=!!e.reverse,e.reverse&&e.lt&&(e.start=e.lt),e.reverse&&e.lte&&(e.start=e.lte),!e.reverse&&e.gt&&(e.start=e.gt),!e.reverse&&e.gte&&(e.start=e.gte),(e.reverse&&e.lt&&!e.lte||!e.reverse&&e.gt&&!e.gte)&&(e.exclusiveStart=!0),e},o.prototype.iterator=function(e){return"object"!=typeof e&&(e={}),e=this._setupIteratorOptions(e),"function"==typeof this._iterator?this._iterator(e):new s(this)},o.prototype._chainedBatch=function(){return new a(this)},o.prototype._isBuffer=function(e){return n.isBuffer(e)},o.prototype._checkKeyValue=function(e,t){if(null===e||void 0===e)return new Error(t+" cannot be `null` or `undefined`");if(this._isBuffer(e)){if(0===e.length)return new Error(t+" cannot be an empty Buffer")}else if(""===String(e))return new Error(t+" cannot be an empty String")},t.exports.AbstractLevelDOWN=o,t.exports.AbstractIterator=s,t.exports.AbstractChainedBatch=a}).call(this,e("_process"),e("buffer").Buffer)},{"./abstract-chained-batch":46,"./abstract-iterator":47,_process:24,buffer:17,xtend:49}],49:[function(e,t){function r(){for(var e={},t=0;t<arguments.length;t++){var r=arguments[t];for(var n in r)r.hasOwnProperty(n)&&(e[n]=r[n])}return e}t.exports=r},{}],50:[function(e,t){!function(e,r,n){"function"==typeof define?define(r):"undefined"!=typeof t&&t.exports?t.exports=r():n[e]=r()}("IDBStore",function(){"use strict";var e=function(e){throw e},t={storeName:"Store",storePrefix:"IDBWrapper-",dbVersion:1,keyPath:"id",autoIncrement:!0,onStoreReady:function(){},onError:e,indexes:[]},r=function(e,r){"undefined"==typeof r&&"function"==typeof e&&(r=e),"[object Object]"!=Object.prototype.toString.call(e)&&(e={});for(var n in t)this[n]="undefined"!=typeof e[n]?e[n]:t[n];this.dbName=this.storePrefix+this.storeName,this.dbVersion=parseInt(this.dbVersion,10)||1,r&&(this.onStoreReady=r);var o="object"==typeof window?window:self;this.idb=o.indexedDB||o.webkitIndexedDB||o.mozIndexedDB,this.keyRange=o.IDBKeyRange||o.webkitIDBKeyRange||o.mozIDBKeyRange,this.features={hasAutoIncrement:!o.mozIndexedDB},this.consts={READ_ONLY:"readonly",READ_WRITE:"readwrite",VERSION_CHANGE:"versionchange",NEXT:"next",NEXT_NO_DUPLICATE:"nextunique",PREV:"prev",PREV_NO_DUPLICATE:"prevunique"},this.openDB()};r.prototype={constructor:r,version:"1.4.1",db:null,dbName:null,dbVersion:null,store:null,storeName:null,keyPath:null,autoIncrement:null,indexes:null,features:null,onStoreReady:null,onError:null,_insertIdCount:0,openDB:function(){var e=this.idb.open(this.dbName,this.dbVersion),t=!1;e.onerror=function(e){var t=!1;"error"in e.target?t="VersionError"==e.target.error.name:"errorCode"in e.target&&(t=12==e.target.errorCode),this.onError(t?new Error("The version number provided is lower than the existing one."):e)}.bind(this),e.onsuccess=function(e){if(!t){if(this.db)return void this.onStoreReady();if(this.db=e.target.result,"string"==typeof this.db.version)return void this.onError(new Error("The IndexedDB implementation in this browser is outdated. Please upgrade your browser."));if(!this.db.objectStoreNames.contains(this.storeName))return void this.onError(new Error("Something is wrong with the IndexedDB implementation in this browser. Please upgrade your browser."));var r=this.db.transaction([this.storeName],this.consts.READ_ONLY);this.store=r.objectStore(this.storeName);var n=Array.prototype.slice.call(this.getIndexList());this.indexes.forEach(function(e){var r=e.name;if(!r)return t=!0,void this.onError(new Error("Cannot create index: No index name given."));if(this.normalizeIndexData(e),this.hasIndex(r)){var o=this.store.index(r),i=this.indexComplies(o,e);i||(t=!0,this.onError(new Error('Cannot modify index "'+r+'" for current version. Please bump version number to '+(this.dbVersion+1)+"."))),n.splice(n.indexOf(r),1)}else t=!0,this.onError(new Error('Cannot create new index "'+r+'" for current version. Please bump version number to '+(this.dbVersion+1)+"."))},this),n.length&&(t=!0,this.onError(new Error('Cannot delete index(es) "'+n.toString()+'" for current version. Please bump version number to '+(this.dbVersion+1)+"."))),t||this.onStoreReady()}}.bind(this),e.onupgradeneeded=function(e){if(this.db=e.target.result,this.db.objectStoreNames.contains(this.storeName))this.store=e.target.transaction.objectStore(this.storeName);else{var r={autoIncrement:this.autoIncrement};null!==this.keyPath&&(r.keyPath=this.keyPath),this.store=this.db.createObjectStore(this.storeName,r)}var n=Array.prototype.slice.call(this.getIndexList());this.indexes.forEach(function(e){var r=e.name;if(r||(t=!0,this.onError(new Error("Cannot create index: No index name given."))),this.normalizeIndexData(e),this.hasIndex(r)){var o=this.store.index(r),i=this.indexComplies(o,e);i||(this.store.deleteIndex(r),this.store.createIndex(r,e.keyPath,{unique:e.unique,multiEntry:e.multiEntry})),n.splice(n.indexOf(r),1)}else this.store.createIndex(r,e.keyPath,{unique:e.unique,multiEntry:e.multiEntry})},this),n.length&&n.forEach(function(e){this.store.deleteIndex(e)},this)}.bind(this)},deleteDatabase:function(){this.idb.deleteDatabase&&this.idb.deleteDatabase(this.dbName)},put:function(t,r,o,i){null!==this.keyPath&&(i=o,o=r,r=t),i||(i=e),o||(o=n);var s,a=!1,u=null,c=this.db.transaction([this.storeName],this.consts.READ_WRITE);return c.oncomplete=function(){var e=a?o:i;e(u)},c.onabort=i,c.onerror=i,null!==this.keyPath?(this._addIdPropertyIfNeeded(r),s=c.objectStore(this.storeName).put(r)):s=c.objectStore(this.storeName).put(r,t),s.onsuccess=function(e){a=!0,u=e.target.result},s.onerror=i,c},get:function(t,r,o){o||(o=e),r||(r=n);var i=!1,s=null,a=this.db.transaction([this.storeName],this.consts.READ_ONLY);a.oncomplete=function(){var e=i?r:o;e(s)},a.onabort=o,a.onerror=o;var u=a.objectStore(this.storeName).get(t);return u.onsuccess=function(e){i=!0,s=e.target.result},u.onerror=o,a},remove:function(t,r,o){o||(o=e),r||(r=n);var i=!1,s=null,a=this.db.transaction([this.storeName],this.consts.READ_WRITE);a.oncomplete=function(){var e=i?r:o;e(s)},a.onabort=o,a.onerror=o;var u=a.objectStore(this.storeName)["delete"](t);return u.onsuccess=function(e){i=!0,s=e.target.result},u.onerror=o,a},batch:function(t,r,o){o||(o=e),r||(r=n),"[object Array]"!=Object.prototype.toString.call(t)&&o(new Error("dataArray argument must be of type Array."));var i=this.db.transaction([this.storeName],this.consts.READ_WRITE);i.oncomplete=function(){var e=u?r:o;e(u)},i.onabort=o,i.onerror=o;var s=t.length,a=!1,u=!1,c=function(){s--,0!==s||a||(a=!0,u=!0)};return t.forEach(function(e){var t=e.type,r=e.key,n=e.value,s=function(e){i.abort(),a||(a=!0,o(e,t,r))};if("remove"==t){var u=i.objectStore(this.storeName)["delete"](r);u.onsuccess=c,u.onerror=s}else if("put"==t){var f;null!==this.keyPath?(this._addIdPropertyIfNeeded(n),f=i.objectStore(this.storeName).put(n)):f=i.objectStore(this.storeName).put(n,r),f.onsuccess=c,f.onerror=s}},this),i},putBatch:function(e,t,r){var n=e.map(function(e){return{type:"put",value:e}});return this.batch(n,t,r)},removeBatch:function(e,t,r){var n=e.map(function(e){return{type:"remove",key:e}});return this.batch(n,t,r)},getBatch:function(t,r,o,i){o||(o=e),r||(r=n),i||(i="sparse"),"[object Array]"!=Object.prototype.toString.call(t)&&o(new Error("keyArray argument must be of type Array."));var s=this.db.transaction([this.storeName],this.consts.READ_ONLY);s.oncomplete=function(){var e=f?r:o;e(l)},s.onabort=o,s.onerror=o;var a=[],u=t.length,c=!1,f=!1,l=null,d=function(e){e.target.result||"dense"==i?a.push(e.target.result):"sparse"==i&&a.length++,u--,0===u&&(c=!0,f=!0,l=a)};return t.forEach(function(e){var t=function(e){c=!0,l=e,o(e),s.abort()},r=s.objectStore(this.storeName).get(e);r.onsuccess=d,r.onerror=t},this),s},getAll:function(t,r){r||(r=e),t||(t=n);var o=this.db.transaction([this.storeName],this.consts.READ_ONLY),i=o.objectStore(this.storeName);return i.getAll?this._getAllNative(o,i,t,r):this._getAllCursor(o,i,t,r),o},_getAllNative:function(e,t,r,n){var o=!1,i=null;e.oncomplete=function(){var e=o?r:n;e(i)},e.onabort=n,e.onerror=n;var s=t.getAll();s.onsuccess=function(e){o=!0,i=e.target.result},s.onerror=n},_getAllCursor:function(e,t,r,n){var o=[],i=!1,s=null;e.oncomplete=function(){var e=i?r:n;e(s)},e.onabort=n,e.onerror=n;var a=t.openCursor();a.onsuccess=function(e){var t=e.target.result;t?(o.push(t.value),t["continue"]()):(i=!0,s=o)},a.onError=n},clear:function(t,r){r||(r=e),t||(t=n);var o=!1,i=null,s=this.db.transaction([this.storeName],this.consts.READ_WRITE);s.oncomplete=function(){var e=o?t:r;e(i)},s.onabort=r,s.onerror=r;var a=s.objectStore(this.storeName).clear();return a.onsuccess=function(e){o=!0,i=e.target.result},a.onerror=r,s},_addIdPropertyIfNeeded:function(e){this.features.hasAutoIncrement||"undefined"!=typeof e[this.keyPath]||(e[this.keyPath]=this._insertIdCount++ +Date.now())},getIndexList:function(){return this.store.indexNames},hasIndex:function(e){return this.store.indexNames.contains(e)},normalizeIndexData:function(e){e.keyPath=e.keyPath||e.name,e.unique=!!e.unique,e.multiEntry=!!e.multiEntry},indexComplies:function(e,t){var r=["keyPath","unique","multiEntry"].every(function(r){if("multiEntry"==r&&void 0===e[r]&&t[r]===!1)return!0;if("keyPath"==r&&"[object Array]"==Object.prototype.toString.call(t[r])){var n=t.keyPath,o=e.keyPath;if("string"==typeof o)return n.toString()==o;if("function"!=typeof o.contains&&"function"!=typeof o.indexOf)return!1;if(o.length!==n.length)return!1;for(var i=0,s=n.length;s>i;i++)if(!(o.contains&&o.contains(n[i])||o.indexOf(-1!==n[i])))return!1;return!0}return t[r]==e[r]});return r},iterate:function(t,r){r=i({index:null,order:"ASC",autoContinue:!0,filterDuplicates:!1,keyRange:null,writeAccess:!1,onEnd:null,onError:e},r||{});var n="desc"==r.order.toLowerCase()?"PREV":"NEXT";r.filterDuplicates&&(n+="_NO_DUPLICATE");var o=!1,s=this.db.transaction([this.storeName],this.consts[r.writeAccess?"READ_WRITE":"READ_ONLY"]),a=s.objectStore(this.storeName);r.index&&(a=a.index(r.index)),s.oncomplete=function(){return o?void(r.onEnd?r.onEnd():t(null)):void r.onError(null)},s.onabort=r.onError,s.onerror=r.onError;var u=a.openCursor(r.keyRange,this.consts[n]);return u.onerror=r.onError,u.onsuccess=function(e){var n=e.target.result;n?(t(n.value,n,s),r.autoContinue&&n["continue"]()):o=!0},s},query:function(e,t){var r=[];return t=t||{},t.onEnd=function(){e(r)},this.iterate(function(e){r.push(e)},t)},count:function(t,r){r=i({index:null,keyRange:null},r||{});var n=r.onError||e,o=!1,s=null,a=this.db.transaction([this.storeName],this.consts.READ_ONLY);a.oncomplete=function(){var e=o?t:n;e(s)},a.onabort=n,a.onerror=n;var u=a.objectStore(this.storeName);r.index&&(u=u.index(r.index));var c=u.count(r.keyRange);return c.onsuccess=function(e){o=!0,s=e.target.result},c.onError=n,a},makeKeyRange:function(e){var t,r="undefined"!=typeof e.lower,n="undefined"!=typeof e.upper,o="undefined"!=typeof e.only;switch(!0){case o:t=this.keyRange.only(e.only);break;case r&&n:t=this.keyRange.bound(e.lower,e.upper,e.excludeLower,e.excludeUpper);break;case r:t=this.keyRange.lowerBound(e.lower,e.excludeLower);break;case n:t=this.keyRange.upperBound(e.upper,e.excludeUpper);break;default:throw new Error('Cannot create KeyRange. Provide one or both of "lower" or "upper" value, or an "only" value.')}return t}};var n=function(){},o={},i=function(e,t){var r,n;for(r in t)n=t[r],n!==o[r]&&n!==e[r]&&(e[r]=n);return e};return r.version=r.prototype.version,r},this)},{}],51:[function(e,t){function r(e){return n.isBuffer(e)||/\[object (.+Array|Array.+)\]/.test(Object.prototype.toString.call(e))}var n=e("buffer").Buffer;t.exports=r},{buffer:17}],52:[function(e,t,r){(function(e){function t(e,t){return Object.hasOwnProperty.call(e,t)}function n(e){return void 0!==e&&""!==e}function t(e,t){return Object.hasOwnProperty.call(e,t)}function o(e,t){return Object.hasOwnProperty.call(e,t)&&t}function i(e){return e}r.compare=function(t,r){if(e.isBuffer(t)){for(var n=Math.min(t.length,r.length),o=0;n>o;o++){var i=t[o]-r[o];if(i)return i}return t.length-r.length}return r>t?-1:t>r?1:0};var s=r.lowerBoundKey=function(e){return o(e,"gt")||o(e,"gte")||o(e,"min")||(e.reverse?o(e,"end"):o(e,"start"))||void 0},a=r.lowerBound=function(e){var t=s(e);return t&&e[t]};r.lowerBoundInclusive=function(e){return t(e,"gt")?!1:!0},r.upperBoundInclusive=function(e){return t(e,"lt")||!e.minEx?!1:!0};var u=r.lowerBoundExclusive=function(e){return t(e,"gt")||e.minEx?!0:!1},c=r.upperBoundExclusive=function(e){return t(e,"lt")?!0:!1},f=r.upperBoundKey=function(e){return o(e,"lt")||o(e,"lte")||o(e,"max")||(e.reverse?o(e,"start"):o(e,"end"))||void 0},l=r.upperBound=function(e){var t=f(e);return t&&e[t]};r.toLtgt=function(e,t,n,o,s){t=t||{},n=n||i;var a=arguments.length>3,u=r.lowerBoundKey(e),c=r.upperBoundKey(e);return u?"gt"===u?t.gt=n(e.gt):t.gte=n(e[u]):a&&(t.gte=o),c?"lt"===c?t.lt=n(e.lt):t.lte=n(e[c]):a&&(t.lte=s),t.reverse=!!e.reverse,t},r.contains=function(e,t,o){o=o||r.compare;var i=a(e);if(n(i)){var s=o(t,i);if(0>s||0===s&&u(e))return!1}var f=l(e);if(n(f)){var s=o(t,f);if(s>0||0===s&&c(e))return!1}return!0},r.filter=function(e,t){return function(n){return r.contains(e,n,t)}}}).call(this,e("buffer").Buffer)},{buffer:17}],53:[function(e,t){(function(e){t.exports=function(t){return"function"==typeof e._augment&&e.TYPED_ARRAY_SUPPORT?e._augment(t):new e(t)}}).call(this,e("buffer").Buffer)},{buffer:17}],54:[function(e,t){function r(e){return null!==e&&("object"==typeof e||"function"==typeof e)}t.exports=r},{}],55:[function(e,t){function r(){for(var e={},t=0;t<arguments.length;t++){var r=arguments[t];if(o(r))for(var i=n(r),s=0;s<i.length;s++){var a=i[s];e[a]=r[a]}}return e}var n=e("object-keys"),o=e("./has-keys");t.exports=r},{"./has-keys":54,"object-keys":57}],56:[function(e,t){var r=Object.prototype.hasOwnProperty,n=Object.prototype.toString,o=function(e){var t="function"==typeof e&&!(e instanceof RegExp)||"[object Function]"===n.call(e);return t||"undefined"==typeof window||(t=e===window.setTimeout||e===window.alert||e===window.confirm||e===window.prompt),t};t.exports=function(e,t){if(!o(t))throw new TypeError("iterator must be a function");var n,i,s="string"==typeof e,a=e.length,u=arguments.length>2?arguments[2]:null;if(a===+a)for(n=0;a>n;n++)null===u?t(s?e.charAt(n):e[n],n,e):t.call(u,s?e.charAt(n):e[n],n,e);else for(i in e)r.call(e,i)&&(null===u?t(e[i],i,e):t.call(u,e[i],i,e))}},{}],57:[function(e,t){t.exports=Object.keys||e("./shim")},{"./shim":59}],58:[function(e,t){var r=Object.prototype.toString;t.exports=function n(e){var t=r.call(e),n="[object Arguments]"===t;return n||(n="[object Array]"!==t&&null!==e&&"object"==typeof e&&"number"==typeof e.length&&e.length>=0&&"[object Function]"===r.call(e.callee)),n}},{}],59:[function(e,t){!function(){"use strict";var r,n=Object.prototype.hasOwnProperty,o=Object.prototype.toString,i=e("./foreach"),s=e("./isArguments"),a=!{toString:null}.propertyIsEnumerable("toString"),u=function(){}.propertyIsEnumerable("prototype"),c=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"];r=function(e){var t=null!==e&&"object"==typeof e,r="[object Function]"===o.call(e),f=s(e),l=[];if(!t&&!r&&!f)throw new TypeError("Object.keys called on a non-object");if(f)i(e,function(e){l.push(e)});else{var d,h=u&&r;for(d in e)h&&"prototype"===d||!n.call(e,d)||l.push(d)}if(a){var p=e.constructor,v=p&&p.prototype===e;i(c,function(t){v&&"constructor"===t||!n.call(e,t)||l.push(t)})}return l},t.exports=r}()},{"./foreach":56,"./isArguments":58}],60:[function(e,t){function r(e,t,r,n){var o={type:e,key:t,value:r,options:n};return n&&n.prefix&&(o.prefix=n.prefix,delete n.prefix),this._operations.push(o),this}function n(e){this._operations=[],this._sdb=e,this.put=r.bind(this,"put"),this.del=r.bind(this,"del")}var o=n.prototype;o.clear=function(){this._operations=[]},o.write=function(e){this._sdb.batch(this._operations,e)},t.exports=n},{}],61:[function(e,t){(function(r){var n=(e("events").EventEmitter,r.nextTick,e("./sub")),o=e("./batch"),i=e("level-fix-range"),s=e("level-hooks");t.exports=function(e,t){function r(){}function a(e){return function(t){return t=t||{},t=i(t),t.reverse?t.start=t.start||c:t.end=t.end||c,e.call(u,t)}}r.prototype=e;var u=new r;if(u.sublevel)return u;t=t||{};var c=t.sep=t.sep||"ÿ";u._options=t,s(u),u.sublevels={},u.sublevel=function(e,t){return u.sublevels[e]?u.sublevels[e]:new n(u,e,t||this._options)},u.methods={},u.prefix=function(e){return""+(e||"")},u.pre=function(e,t){return t||(t=e,e={max:c}),u.hooks.pre(e,t)},u.post=function(e,t){return t||(t=e,e={max:c}),u.hooks.post(e,t)},u.readStream=u.createReadStream=a(u.createReadStream),u.keyStream=u.createKeyStream=a(u.createKeyStream),u.valuesStream=u.createValueStream=a(u.createValueStream);var f=u.batch;return u.batch=function(e,t,r){return Array.isArray(e)?(e.forEach(function(e){e.prefix&&("function"==typeof e.prefix.prefix?e.key=e.prefix.prefix(e.key):"string"==typeof e.prefix&&(e.key=e.prefix+e.key))}),void f.call(u,e,t,r)):new o(u)},u}}).call(this,e("_process"))},{"./batch":60,"./sub":72,_process:24,events:21,"level-fix-range":62,"level-hooks":64}],62:[function(e,t){var r=e("clone");t.exports=function(e){e=r(e);var t=e.reverse,n=e.max||e.end,o=e.min||e.start,i=[o,n];return null!=o&&null!=n&&i.sort(),t&&(i=i.reverse()),e.start=i[0],e.end=i[1],delete e.min,delete e.max,e}},{clone:63}],63:[function(e,t){(function(e){"use strict";function r(e){return Object.prototype.toString.call(e)}function n(t,r,n,i){function s(t,n){if(null===t)return null;if(0==n)return t;var f,l;if("object"!=typeof t)return t;if(o.isArray(t))f=[];else if(o.isRegExp(t))f=new RegExp(t.source,o.getRegExpFlags(t)),t.lastIndex&&(f.lastIndex=t.lastIndex);else if(o.isDate(t))f=new Date(t.getTime());else{if(c&&e.isBuffer(t))return f=new e(t.length),t.copy(f),f;"undefined"==typeof i?(l=Object.getPrototypeOf(t),f=Object.create(l)):(f=Object.create(i),l=i)}if(r){var d=a.indexOf(t);if(-1!=d)return u[d];a.push(t),u.push(f)}for(var h in t){var p;l&&(p=Object.getOwnPropertyDescriptor(l,h)),p&&null==p.set||(f[h]=s(t[h],n-1))}return f}var a=[],u=[],c="undefined"!=typeof e;return"undefined"==typeof r&&(r=!0),"undefined"==typeof n&&(n=1/0),s(t,n)}var o={isArray:function(e){return Array.isArray(e)||"object"==typeof e&&"[object Array]"===r(e)},isDate:function(e){return"object"==typeof e&&"[object Date]"===r(e)},isRegExp:function(e){return"object"==typeof e&&"[object RegExp]"===r(e)},getRegExpFlags:function(e){var t="";return e.global&&(t+="g"),e.ignoreCase&&(t+="i"),e.multiline&&(t+="m"),t}};"object"==typeof t&&(t.exports=n),n.clonePrototype=function(e){if(null===e)return null;var t=function(){};return t.prototype=e,new t}}).call(this,e("buffer").Buffer)},{buffer:17}],64:[function(e,t){var r=e("string-range");t.exports=function(e){function t(e){return e&&("string"==typeof e?e:"string"==typeof e.prefix?e.prefix:"function"==typeof e.prefix?e.prefix():"")}function n(e){return e&&e._getKeyEncoding?e._getKeyEncoding(e):void 0}function o(e){return e&&e._getValueEncoding?e._getValueEncoding(e):void 0}function i(e,t){return function(){var r=e.indexOf(t);return~r?(e.splice(r,1),!0):!1}}function s(e){e&&e.type&&u.forEach(function(t){t.test(e.key)&&t.hook(e)})}function a(r,i,s,a){try{i.forEach(function p(e,r){c.forEach(function(s){if(s.test(String(e.key))){var a={add:function(e,a){if("undefined"==typeof e)return this;if(e===!1)return delete i[r];var u=t(e.prefix)||t(a)||s.prefix||"";if(u&&(e.prefix=u),e.key=u+e.key,s.safe&&s.test(String(e.key)))throw new Error("prehook cannot insert into own range");var c=e.keyEncoding||n(e.prefix),f=e.valueEncoding||o(e.prefix);return c&&(e.keyEncoding=c),f&&(e.valueEncoding=f),i.push(e),p(e,i.length-1),this},put:function(e,t){return"object"==typeof e&&(e.type="put"),this.add(e,t)},del:function(e,t){return"object"==typeof e&&(e.type="del"),this.add(e,t)},veto:function(){return this.add(!1)}};s.hook.call(a,e,a.add,i)}})})}catch(u){return(a||s)(u)}if(i=i.filter(function(e){return e&&e.type}),1==i.length&&!r){var h=i[0];return"put"==h.type?f.call(e,h.key,h.value,s,a):l.call(e,h.key,s,a)}return d.call(e,i,s,a)}if(!e.hooks){var u=[],c=[];e.hooks={post:function(e,t){t||(t=e,e="");var n={test:r.checker(e),hook:t};return u.push(n),i(u,n)},pre:function(e,t){t||(t=e,e="");var n={test:r.checker(e),hook:t,safe:!1!==e.safe};return c.push(n),i(c,n)},posthooks:u,prehooks:c},e.on("put",function(e,t){s({type:"put",key:e,value:t})}),e.on("del",function(e,t){s({type:"del",key:e,value:t})}),e.on("batch",function(e){e.forEach(s)});var f=e.put,l=e.del,d=e.batch;e.put=function(e,t,r,n){var o=[{key:e,value:t,type:"put"}];return a(!1,o,r,n)},e.del=function(e,t,r){var n=[{key:e,type:"del"}];return a(!1,n,t,r)},e.batch=function(e,t,r){return a(!0,e,t,r)}}}},{"string-range":65}],65:[function(e,t,r){{var n=r.range=function(e){return null==e?{}:"string"==typeof n?{min:n,max:n+"ÿ"}:e},o=(r.prefix=function(e,t,n){e=r.range(e);var o={};return n=n||"ÿ",e instanceof RegExp||"function"==typeof e?(o.min=t,o.max=t+n,o.inner=function(r){var n=r.substring(t.length);return e.test?e.test(n):e(n)}):"object"==typeof e&&(o.min=t+(e.min||e.start||""),o.max=t+(e.max||e.end||n||"~"),o.reverse=!!e.reverse),o},r.checker=function(e){return e||(e={}),"string"==typeof e?function(t){return 0==t.indexOf(e)}:e instanceof RegExp?function(t){return e.test(t)}:"object"==typeof e?function(t){var r=e.min||e.start,n=e.max||e.end;return t=String(t),(!r||t>=r)&&(!n||n>=t)&&(!e.inner||(e.inner.test?e.inner.test(t):e.inner(t)))}:"function"==typeof e?e:void 0});r.satisfies=function(e,t){return o(t)(e)}}},{}],66:[function(e,t){t.exports=e(54)},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/has-keys.js":54}],67:[function(e,t,r){arguments[4][55][0].apply(r,arguments)},{"./has-keys":66,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/index.js":55,"object-keys":68}],68:[function(e,t,r){arguments[4][57][0].apply(r,arguments)},{"./shim":71,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/index.js":57}],69:[function(e,t){var r=Object.prototype.hasOwnProperty,n=Object.prototype.toString;t.exports=function(e,t,o){if("[object Function]"!==n.call(t))throw new TypeError("iterator must be a function");var i=e.length;if(i===+i)for(var s=0;i>s;s++)t.call(o,e[s],s,e);else for(var a in e)r.call(e,a)&&t.call(o,e[a],a,e)}},{}],70:[function(e,t){var r=Object.prototype,n=r.hasOwnProperty,o=r.toString,i=function(e){return e!==e},s={"boolean":1,number:1,string:1,undefined:1},a=t.exports={};a.a=a.type=function(e,t){return typeof e===t},a.defined=function(e){return void 0!==e},a.empty=function(e){var t,r=o.call(e);if("[object Array]"===r||"[object Arguments]"===r)return 0===e.length;if("[object Object]"===r){for(t in e)if(n.call(e,t))return!1;return!0}return"[object String]"===r?""===e:!1},a.equal=function(e,t){var r,n=o.call(e);if(n!==o.call(t))return!1;if("[object Object]"===n){for(r in e)if(!a.equal(e[r],t[r]))return!1;return!0}if("[object Array]"===n){if(r=e.length,r!==t.length)return!1;for(;--r;)if(!a.equal(e[r],t[r]))return!1;return!0}return"[object Function]"===n?e.prototype===t.prototype:"[object Date]"===n?e.getTime()===t.getTime():e===t},a.hosted=function(e,t){var r=typeof t[e];return"object"===r?!!t[e]:!s[r]},a.instance=a["instanceof"]=function(e,t){return e instanceof t},a["null"]=function(e){return null===e},a.undefined=function(e){return void 0===e},a.arguments=function(e){var t="[object Arguments]"===o.call(e),r=!a.array(e)&&a.arraylike(e)&&a.object(e)&&a.fn(e.callee);return t||r},a.array=function(e){return"[object Array]"===o.call(e)},a.arguments.empty=function(e){return a.arguments(e)&&0===e.length},a.array.empty=function(e){return a.array(e)&&0===e.length},a.arraylike=function(e){return!!e&&!a.boolean(e)&&n.call(e,"length")&&isFinite(e.length)&&a.number(e.length)&&e.length>=0},a.boolean=function(e){return"[object Boolean]"===o.call(e)},a["false"]=function(e){return a.boolean(e)&&(e===!1||e.valueOf()===!1) +},a["true"]=function(e){return a.boolean(e)&&(e===!0||e.valueOf()===!0)},a.date=function(e){return"[object Date]"===o.call(e)},a.element=function(e){return void 0!==e&&"undefined"!=typeof HTMLElement&&e instanceof HTMLElement&&1===e.nodeType},a.error=function(e){return"[object Error]"===o.call(e)},a.fn=a["function"]=function(e){var t="undefined"!=typeof window&&e===window.alert;return t||"[object Function]"===o.call(e)},a.number=function(e){return"[object Number]"===o.call(e)},a.infinite=function(e){return 1/0===e||e===-1/0},a.decimal=function(e){return a.number(e)&&!i(e)&&!a.infinite(e)&&e%1!==0},a.divisibleBy=function(e,t){var r=a.infinite(e),n=a.infinite(t),o=a.number(e)&&!i(e)&&a.number(t)&&!i(t)&&0!==t;return r||n||o&&e%t===0},a.int=function(e){return a.number(e)&&!i(e)&&e%1===0},a.maximum=function(e,t){if(i(e))throw new TypeError("NaN is not a valid value");if(!a.arraylike(t))throw new TypeError("second argument must be array-like");for(var r=t.length;--r>=0;)if(e<t[r])return!1;return!0},a.minimum=function(e,t){if(i(e))throw new TypeError("NaN is not a valid value");if(!a.arraylike(t))throw new TypeError("second argument must be array-like");for(var r=t.length;--r>=0;)if(e>t[r])return!1;return!0},a.nan=function(e){return!a.number(e)||e!==e},a.even=function(e){return a.infinite(e)||a.number(e)&&e===e&&e%2===0},a.odd=function(e){return a.infinite(e)||a.number(e)&&e===e&&e%2!==0},a.ge=function(e,t){if(i(e)||i(t))throw new TypeError("NaN is not a valid value");return!a.infinite(e)&&!a.infinite(t)&&e>=t},a.gt=function(e,t){if(i(e)||i(t))throw new TypeError("NaN is not a valid value");return!a.infinite(e)&&!a.infinite(t)&&e>t},a.le=function(e,t){if(i(e)||i(t))throw new TypeError("NaN is not a valid value");return!a.infinite(e)&&!a.infinite(t)&&t>=e},a.lt=function(e,t){if(i(e)||i(t))throw new TypeError("NaN is not a valid value");return!a.infinite(e)&&!a.infinite(t)&&t>e},a.within=function(e,t,r){if(i(e)||i(t)||i(r))throw new TypeError("NaN is not a valid value");if(!a.number(e)||!a.number(t)||!a.number(r))throw new TypeError("all arguments must be numbers");var n=a.infinite(e)||a.infinite(t)||a.infinite(r);return n||e>=t&&r>=e},a.object=function(e){return e&&"[object Object]"===o.call(e)},a.hash=function(e){return a.object(e)&&e.constructor===Object&&!e.nodeType&&!e.setInterval},a.regexp=function(e){return"[object RegExp]"===o.call(e)},a.string=function(e){return"[object String]"===o.call(e)}},{}],71:[function(e,t){!function(){"use strict";var r,n=Object.prototype.hasOwnProperty,o=e("is"),i=e("foreach"),s=!{toString:null}.propertyIsEnumerable("toString"),a=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"];r=function(e){if(!o.object(e)&&!o.array(e))throw new TypeError("Object.keys called on a non-object");var t,r=[];for(t in e)n.call(e,t)&&r.push(t);return s&&i(a,function(t){n.call(e,t)&&r.push(t)}),r},t.exports=r}()},{foreach:69,is:70}],72:[function(e,t){function r(e,t,n){if("string"==typeof n&&(console.error("db.sublevel(name, seperator<string>) is depreciated"),console.error("use db.sublevel(name, {sep: separator})) if you must"),n={sep:n}),!(this instanceof r))return new r(e,t,n);if(!e)throw new Error("must provide db");if(!t)throw new Error("must provide prefix");n=n||{},n.sep=n.sep||"ÿ",this._parent=e,this._options=n,this.options=n,this._prefix=t,this._root=o(this),e.sublevels[t]=this,this.sublevels={},this.methods={};var i=this;this.hooks={pre:function(){return i.pre.apply(i,arguments)},post:function(){return i.post.apply(i,arguments)}}}function n(e,t){["valueEncoding","encoding","keyEncoding","reverse","values","keys","limit","fillCache"].forEach(function(r){t.hasOwnProperty(r)&&(e[r]=t[r])})}function o(e){return e._parent?o(e._parent):e}var i=e("events").EventEmitter,s=e("util").inherits,a=e("string-range"),u=e("level-fix-range"),c=e("xtend"),f=e("./batch");s(r,i);var l=r.prototype;l._key=function(e){var t=this._options.sep;return t+this._prefix+t+e},l._getOptsAndCb=function(e,t){return"function"==typeof e&&(t=e,e={}),{opts:c(e,this._options),cb:t}},l.sublevel=function(e,t){return this.sublevels[e]?this.sublevels[e]:new r(this,e,t||this._options)},l.put=function(e,t,r,n){var o=this._getOptsAndCb(r,n);this._root.put(this.prefix(e),t,o.opts,o.cb)},l.get=function(e,t,r){var n=this._getOptsAndCb(t,r);this._root.get(this.prefix(e),n.opts,n.cb)},l.del=function(e,t,r){var n=this._getOptsAndCb(t,r);this._root.del(this.prefix(e),n.opts,n.cb)},l.batch=function(e,t,r){if(!Array.isArray(e))return new f(this);var n=this,o=this._getOptsAndCb(t,r);e.forEach(function(e){e.key="string"==typeof e.prefix?e.prefix+e.key:(e.prefix||n).prefix(e.key),e.prefix&&(e.prefix=null)}),this._root.batch(e,o.opts,o.cb)},l._getKeyEncoding=function(){return this.options.keyEncoding?this.options.keyEncoding:this._parent&&this._parent._getKeyEncoding?this._parent._getKeyEncoding():void 0},l._getValueEncoding=function(){return this.options.valueEncoding?this.options.valueEncoding:this._parent&&this._parent._getValueEncoding?this._parent._getValueEncoding():void 0},l.prefix=function(e){var t=this._options.sep;return this._parent.prefix()+t+this._prefix+t+(e||"")},l.keyStream=l.createKeyStream=function(e){return e=e||{},e.keys=!0,e.values=!1,this.createReadStream(e)},l.valueStream=l.createValueStream=function(e){return e=e||{},e.keys=!1,e.values=!0,e.keys=!1,this.createReadStream(e)},l.readStream=l.createReadStream=function(e){e=e||{};var t=o(this),r=this.prefix(),i=a.prefix(e,r);n(i,c(e,this._options));var s=t.createReadStream(i);if(i.values===!1){var u=s.read;if(u)s.read=function(e){var t=u.call(this,e);return t&&(t=t.substring(r.length)),t};else{var f=s.emit;s.emit=function(e,t){"data"===e?f.call(this,"data",t.substring(r.length)):f.call(this,e,t)}}return s}if(i.keys===!1)return s;var u=s.read;return u?s.read=function(e){var t=u.call(this,e);return t&&(t.key=t.key.substring(r.length)),t}:s.on("data",function(e){e.key=e.key.substring(r.length)}),s},l.writeStream=l.createWriteStream=function(){var e=o(this),t=this.prefix(),r=e.createWriteStream.apply(e,arguments),n=r.write,i=this._options.encoding,s=this._options.valueEncoding,a=this._options.keyEncoding,u=!i&&!s&&!a;return r.write=u?function(e){return e.key=t+e.key,n.call(r,e)}:function(e){return e.key=t+e.key,i&&"undefined"==typeof e.encoding&&(e.encoding=i),s&&"undefined"==typeof e.valueEncoding&&(e.valueEncoding=s),a&&"undefined"==typeof e.keyEncoding&&(e.keyEncoding=a),n.call(r,e)},r},l.approximateSize=function(){var e=o(db);return e.approximateSize.apply(e,arguments)},l.pre=function(e,t){t||(t=e,e=null),e=a.prefix(e,this.prefix(),this._options.sep);var r=o(this._parent),n=this.prefix();return r.hooks.pre(u(e),function(e,r,o){t({key:e.key.substring(n.length),value:e.value,type:e.type},function(e,t){r(e,e.prefix?t:t||n)},o)})},l.post=function(e,t){t||(t=e,e=null);var r=o(this._parent),n=this.prefix();return e=a.prefix(e,n,this._options.sep),r.hooks.post(u(e),function(e){t({key:e.key.substring(n.length),value:e.value,type:e.type})})};t.exports=r},{"./batch":60,events:21,"level-fix-range":62,"string-range":65,util:39,xtend:67}],73:[function(e,t){function r(e){this._levelup=e,this.batch=e.db.batch(),this.ops=[]}var n=e("./util"),o=e("./errors").WriteError,i=n.getOptions,s=n.dispatchError;r.prototype.put=function(e,t,r){r=i(this._levelup,r);var s=n.encodeKey(e,r),a=n.encodeValue(t,r);try{this.batch.put(s,a)}catch(u){throw new o(u)}return this.ops.push({type:"put",key:s,value:a}),this},r.prototype.del=function(e,t){t=i(this._levelup,t);var r=n.encodeKey(e,t);try{this.batch.del(r)}catch(s){throw new o(s)}return this.ops.push({type:"del",key:r}),this},r.prototype.clear=function(){try{this.batch.clear()}catch(e){throw new o(e)}return this.ops=[],this},r.prototype.write=function(e){var t=this._levelup,r=this.ops;try{this.batch.write(function(n){return n?s(t,new o(n),e):(t.emit("batch",r),void(e&&e()))})}catch(n){throw new o(n)}},t.exports=r},{"./errors":74,"./util":77}],74:[function(e,t){var r=e("errno").create,n=r("LevelUPError"),o=r("NotFoundError",n);o.prototype.notFound=!0,o.prototype.status=404,t.exports={LevelUPError:n,InitializationError:r("InitializationError",n),OpenError:r("OpenError",n),ReadError:r("ReadError",n),WriteError:r("WriteError",n),NotFoundError:o,EncodingError:r("EncodingError",n)}},{errno:85}],75:[function(e,t){(function(r){function n(e,t){return"function"==typeof e?e:t}function o(e,t,n){if(!(this instanceof o))return new o(e,t,n);var i;if(s.call(this),this.setMaxListeners(1/0),"function"==typeof e?(t="object"==typeof t?t:{},t.db=e,e=null):"object"==typeof e&&"function"==typeof e.db&&(t=e,e=null),"function"==typeof t&&(n=t,t={}),(!t||"function"!=typeof t.db)&&"string"!=typeof e){if(i=new y("Must provide a location for the database"),n)return r.nextTick(function(){n(i)});throw i}t=w(this,t),this.options=u(E,t),this._status="new",c(this,"location",e,"e"),this.open(n)}function i(e){return function(t,r){x()[e](t,r||function(){})}}var s=e("events").EventEmitter,a=e("util").inherits,u=e("xtend"),c=e("prr"),f=e("deferred-leveldown"),l=e("./errors").WriteError,d=e("./errors").ReadError,h=e("./errors").NotFoundError,p=e("./errors").OpenError,v=e("./errors").EncodingError,y=e("./errors").InitializationError,g=e("./read-stream"),m=e("./write-stream"),b=e("./util"),_=e("./batch"),w=b.getOptions,E=b.defaultOptions,x=b.getLevelDOWN,k=b.dispatchError;a(o,s),o.prototype.open=function(e){var t,n,o=this;return this.isOpen()?(e&&r.nextTick(function(){e(null,o)}),this):this._isOpening()?e&&this.once("open",function(){e(null,o)}):(this.emit("opening"),this._status="opening",this.db=new f(this.location),t=this.options.db||x(),n=t(this.location),void n.open(this.options,function(t){return t?k(o,new p(t),e):(o.db.setDb(n),o.db=n,o._status="open",e&&e(null,o),o.emit("open"),o.emit("ready"),void 0)}))},o.prototype.close=function(e){var t=this;if(this.isOpen())this._status="closing",this.db.close(function(){t._status="closed",t.emit("closed"),e&&e.apply(null,arguments)}),this.emit("closing"),this.db=null;else{if("closed"==this._status&&e)return r.nextTick(e);"closing"==this._status&&e?this.once("closed",e):this._isOpening()&&this.once("open",function(){t.close(e)})}},o.prototype.isOpen=function(){return"open"==this._status},o.prototype._isOpening=function(){return"opening"==this._status},o.prototype.isClosed=function(){return/^clos/.test(this._status)},o.prototype.get=function(e,t,r){var o,i=this;return r=n(t,r),"function"!=typeof r?k(this,new d("get() requires key and callback arguments")):this._isOpening()||this.isOpen()?(t=b.getOptions(this,t),o=b.encodeKey(e,t),t.asBuffer=b.isValueAsBuffer(t),void this.db.get(o,t,function(n,o){if(n)return n=/notfound/i.test(n)?new h("Key not found in database ["+e+"]",n):new d(n),k(i,n,r);if(r){try{o=b.decodeValue(o,t)}catch(s){return r(new v(s))}r(null,o)}})):k(this,new d("Database is not open"),r)},o.prototype.put=function(e,t,r,o){var i,s,a=this;return o=n(r,o),null===e||void 0===e||null===t||void 0===t?k(this,new l("put() requires key and value arguments"),o):this._isOpening()||this.isOpen()?(r=w(this,r),i=b.encodeKey(e,r),s=b.encodeValue(t,r),void this.db.put(i,s,r,function(r){return r?k(a,new l(r),o):(a.emit("put",e,t),void(o&&o()))})):k(this,new l("Database is not open"),o)},o.prototype.del=function(e,t,r){var o,i=this;return r=n(t,r),null===e||void 0===e?k(this,new l("del() requires a key argument"),r):this._isOpening()||this.isOpen()?(t=w(this,t),o=b.encodeKey(e,t),void this.db.del(o,t,function(t){return t?k(i,new l(t),r):(i.emit("del",e),void(r&&r()))})):k(this,new l("Database is not open"),r)},o.prototype.batch=function(e,t,r){var o,i,s,a=this;return arguments.length?(r=n(t,r),Array.isArray(e)?this._isOpening()||this.isOpen()?(t=w(this,t),o=t.keyEncoding,i=t.valueEncoding,s=e.map(function(e){if(void 0===e.type||void 0===e.key)return{};var r,n=e.keyEncoding||o,s=e.valueEncoding||e.encoding||i;return"utf8"!=n&&"binary"!=n||"utf8"!=s&&"binary"!=s?(r={type:e.type,key:b.encodeKey(e.key,t,e)},void 0!==e.value&&(r.value=b.encodeValue(e.value,t,e)),r):e}),void this.db.batch(s,t,function(t){return t?k(a,new l(t),r):(a.emit("batch",e),void(r&&r()))})):k(this,new l("Database is not open"),r):k(this,new l("batch() requires an array argument"),r)):new _(this)},o.prototype.approximateSize=function(e,t,r){var n,o,i=this;return null===e||void 0===e||null===t||void 0===t||"function"!=typeof r?k(this,new d("approximateSize() requires start, end and callback arguments"),r):(n=b.encodeKey(e,this.options),o=b.encodeKey(t,this.options),this._isOpening()||this.isOpen()?void this.db.approximateSize(n,o,function(e,t){return e?k(i,new p(e),r):void(r&&r(null,t))}):k(this,new l("Database is not open"),r))},o.prototype.readStream=o.prototype.createReadStream=function(e){var t=this;return e=u(this.options,e),new g(e,this,function(e){return t.db.iterator(e)})},o.prototype.keyStream=o.prototype.createKeyStream=function(e){return this.createReadStream(u(e,{keys:!0,values:!1}))},o.prototype.valueStream=o.prototype.createValueStream=function(e){return this.createReadStream(u(e,{keys:!1,values:!0}))},o.prototype.writeStream=o.prototype.createWriteStream=function(e){return new m(u(e),this)},o.prototype.toString=function(){return"LevelUP"},t.exports=o,t.exports.copy=b.copy,t.exports.destroy=i("destroy"),t.exports.repair=i("repair")}).call(this,e("_process"))},{"./batch":73,"./errors":74,"./read-stream":76,"./util":77,"./write-stream":78,_process:24,"deferred-leveldown":80,events:21,prr:86,util:39,xtend:96}],76:[function(e,t){function r(e,t,o){if(!(this instanceof r))return new r(e,t,o);n.call(this,{objectMode:!0,highWaterMark:e.highWaterMark}),this._db=t,e=this._options=i(u,e),this._keyEncoding=e.keyEncoding||e.encoding,this._valueEncoding=e.valueEncoding||e.encoding,"undefined"!=typeof this._options.start&&(this._options.start=a.encodeKey(this._options.start,this._options)),"undefined"!=typeof this._options.end&&(this._options.end=a.encodeKey(this._options.end,this._options)),"number"!=typeof this._options.limit&&(this._options.limit=-1),this._options.keyAsBuffer=a.isKeyAsBuffer(this._options),this._options.valueAsBuffer=a.isValueAsBuffer(this._options),this._makeData=this._options.keys&&this._options.values?c:this._options.keys?f:this._options.values?l:d;var s=this;this._db.isOpen()?this._iterator=o(this._options):this._db.once("ready",function(){s._destroyed||(s._iterator=o(s._options))})}var n=e("readable-stream").Readable,o=e("util").inherits,i=e("xtend"),s=e("./errors").EncodingError,a=e("./util"),u={keys:!0,values:!0},c=function(e,t){return{key:a.decodeKey(e,this._options),value:a.decodeValue(t,this._options)}},f=function(e){return a.decodeKey(e,this._options)},l=function(e,t){return a.decodeValue(t,this._options)},d=function(){return null};o(r,n),r.prototype._read=function h(){var e=this;return e._db.isOpen()?void(e._destroyed||e._iterator.next(function(t,r,n){if(t||void 0===r&&void 0===n)return t||e._destroyed||e.push(null),e._cleanup(t);try{n=e._makeData(r,n)}catch(o){return e._cleanup(new s(o))}e._destroyed||e.push(n)})):e._db.once("ready",function(){h.call(e)})},r.prototype._cleanup=function(e){if(!this._destroyed){this._destroyed=!0;var t=this;e&&t.emit("error",e),t._iterator?t._iterator.end(function(){t._iterator=null,t.emit("close")}):t.emit("close")}},r.prototype.destroy=function(){this._cleanup()},r.prototype.toString=function(){return"LevelUP.ReadStream"},t.exports=r},{"./errors":74,"./util":77,"readable-stream":95,util:39,xtend:96}],77:[function(e,t){(function(r,n){function o(e,t,r){e.readStream().pipe(t.writeStream()).on("close",r?r:function(){}).on("error",r?r:function(e){throw e})}function i(e,t){var r="string"==typeof t;return!r&&t&&t.encoding&&!t.valueEncoding&&(t.valueEncoding=t.encoding),g(e&&e.options||{},r?E[t]||E[_.valueEncoding]:t)}function s(){if(y)return y;var t,r=e("../package.json").devDependencies.leveldown,n="Could not locate LevelDOWN, try `npm install leveldown`";try{t=e("leveldown/package").version}catch(o){throw new m(n)}if(!e("semver").satisfies(t,r))throw new m("Installed version of LevelDOWN ("+t+") does not match required version ("+r+")");try{return y=e("leveldown")}catch(o){throw new m(n)}}function a(e,t,r){return"function"==typeof r?r(t):e.emit("error",t)}function u(e,t){var r=t&&t.keyEncoding||e.keyEncoding||"utf8";return w[r]||r}function c(e,t){var r=t&&(t.valueEncoding||t.encoding)||e.valueEncoding||e.encoding||"utf8";return w[r]||r}function f(e,t,r){return u(t,r).encode(e)}function l(e,t,r){return c(t,r).encode(e)}function d(e,t){return u(t).decode(e)}function h(e,t){return c(t).decode(e)}function p(e,t){return c(e,t).buffer}function v(e,t){return u(e,t).buffer}var y,g=e("xtend"),m=e("./errors").LevelUPError,b=["hex","utf8","utf-8","ascii","binary","base64","ucs2","ucs-2","utf16le","utf-16le"],_={createIfMissing:!0,errorIfExists:!1,keyEncoding:"utf8",valueEncoding:"utf8",compression:!0},w=function(){function e(e){return void 0===e||null===e||n.isBuffer(e)}var t={};return t.utf8=t["utf-8"]={encode:function(t){return e(t)?t:String(t)},decode:function(e){return e},buffer:!1,type:"utf8"},t.json={encode:JSON.stringify,decode:JSON.parse,buffer:!1,type:"json"},b.forEach(function(o){t[o]||(t[o]={encode:function(t){return e(t)?t:new n(t,o)},decode:function(e){return r.browser?e.toString(o):e},buffer:!0,type:o})}),t}(),E=function(){var e={};return b.forEach(function(t){e[t]={valueEncoding:t}}),e}();t.exports={defaultOptions:_,copy:o,getOptions:i,getLevelDOWN:s,dispatchError:a,encodeKey:f,encodeValue:l,isValueAsBuffer:p,isKeyAsBuffer:v,decodeValue:h,decodeKey:d}}).call(this,e("_process"),e("buffer").Buffer)},{"../package.json":97,"./errors":74,_process:24,buffer:17,leveldown:"leveldown","leveldown/package":16,semver:16,xtend:96}],78:[function(e,t){(function(r,n){function o(e,t){if(!(this instanceof o))return new o(e,t);i.call(this),this._options=a(l,f(t,e)),this._db=t,this._buffer=[],this._status="init",this._end=!1,this.writable=!0,this.readable=!1;var r=this,n=function(){r.writable&&(r._status="ready",r.emit("ready"),r._process())};t.isOpen()?c(n):t.once("ready",n)}var i=e("stream").Stream,s=e("util").inherits,a=e("xtend"),u=e("bl"),c=n.setImmediate||r.nextTick,f=e("./util").getOptions,l={type:"put"};s(o,i),o.prototype.write=function(e){return this.writable?(this._buffer.push(e),"init"!=this._status&&this._processDelayed(),this._options.maxBufferLength&&this._buffer.length>this._options.maxBufferLength?(this._writeBlock=!0,!1):!0):!1},o.prototype.end=function(e){var t=this;e&&this.write(e),c(function(){t._end=!0,t._process()})},o.prototype.destroy=function(){this.writable=!1,this.end()},o.prototype.destroySoon=function(){this.end()},o.prototype.add=function(e){return e.props?(e.props.Directory?e.pipe(this._db.writeStream(this._options)):(e.props.File||e.File||"File"==e.type)&&this._write(e),!0):void 0},o.prototype._processDelayed=function(){var e=this;c(function(){e._process()})},o.prototype._process=function(){var e,t=this,r=function(e){return t.writable?("closed"!=t._status&&(t._status="ready"),e?(t.writable=!1,t.emit("error",e)):void t._process()):void 0};return"ready"!=t._status&&t.writable?void(t._buffer.length&&"closed"!=t._status&&t._processDelayed()):t._buffer.length&&t.writable?(t._status="writing",e=t._buffer,t._buffer=[],t._db.batch(e.map(function(e){return{type:e.type||t._options.type,key:e.key,value:e.value,keyEncoding:e.keyEncoding||t._options.keyEncoding,valueEncoding:e.valueEncoding||e.encoding||t._options.valueEncoding}}),r),void(t._writeBlock&&(t._writeBlock=!1,t.emit("drain")))):void(t._end&&"closed"!=t._status&&(t._status="closed",t.writable=!1,t.emit("close")))},o.prototype._write=function(e){var t=e.path||e.props.path,r=this;t&&e.pipe(u(function(e,n){return e?(r.writable=!1,r.emit("error",e)):(r._options.fstreamRoot&&t.indexOf(r._options.fstreamRoot)>-1&&(t=t.substr(r._options.fstreamRoot.length+1)),void r.write({key:t,value:n.slice(0)}))}))},o.prototype.toString=function(){return"LevelUP.WriteStream"},t.exports=o}).call(this,e("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./util":77,_process:24,bl:79,stream:36,util:39,xtend:96}],79:[function(e,t){(function(r){function n(e){if(!(this instanceof n))return new n(e);if(this._bufs=[],this.length=0,"function"==typeof e){this._callback=e;var t=function(e){this._callback&&(this._callback(e),this._callback=null)}.bind(this);this.on("pipe",function(e){e.on("error",t)}),this.on("unpipe",function(e){e.removeListener("error",t)})}else r.isBuffer(e)?this.append(e):Array.isArray(e)&&e.forEach(function(e){r.isBuffer(e)&&this.append(e)}.bind(this));o.call(this)}var o=e("readable-stream").Duplex,i=e("util");i.inherits(n,o),n.prototype._offset=function(e){for(var t,r=0,n=0;n<this._bufs.length;n++){if(t=r+this._bufs[n].length,t>e)return[n,e-r];r=t}},n.prototype.append=function(e){return this._bufs.push(r.isBuffer(e)?e:new r(e)),this.length+=e.length,this},n.prototype._write=function(e,t,r){this.append(e),r&&r()},n.prototype._read=function(e){return this.length?(e=Math.min(e,this.length),this.push(this.slice(0,e)),void this.consume(e)):this.push(null)},n.prototype.end=function(e){o.prototype.end.call(this,e),this._callback&&(this._callback(null,this.slice()),this._callback=null)},n.prototype.get=function(e){return this.slice(e,e+1)[0]},n.prototype.slice=function(e,t){return this.copy(null,0,e,t)},n.prototype.copy=function(e,t,n,o){if(("number"!=typeof n||0>n)&&(n=0),("number"!=typeof o||o>this.length)&&(o=this.length),n>=this.length)return e||new r(0);if(0>=o)return e||new r(0);var i,s,a=!!e,u=this._offset(n),c=o-n,f=c,l=a&&t||0,d=u[1];if(0===n&&o==this.length){if(!a)return r.concat(this._bufs);for(s=0;s<this._bufs.length;s++)this._bufs[s].copy(e,l),l+=this._bufs[s].length;return e}if(f<=this._bufs[u[0]].length-d)return a?this._bufs[u[0]].copy(e,t,d,d+f):this._bufs[u[0]].slice(d,d+f);for(a||(e=new r(c)),s=u[0];s<this._bufs.length;s++){if(i=this._bufs[s].length-d,!(f>i)){this._bufs[s].copy(e,l,d,d+f);break}this._bufs[s].copy(e,l,d),l+=i,f-=i,d&&(d=0)}return e},n.prototype.toString=function(e,t,r){return this.slice(t,r).toString(e)},n.prototype.consume=function(e){for(;this._bufs.length;){if(!(e>this._bufs[0].length)){this._bufs[0]=this._bufs[0].slice(e),this.length-=e;break}e-=this._bufs[0].length,this.length-=this._bufs[0].length,this._bufs.shift()}return this},n.prototype.duplicate=function(){for(var e=0,t=new n;e<this._bufs.length;e++)t.append(this._bufs[e]);return t},n.prototype.destroy=function(){this._bufs.length=0,this.length=0,this.push(null)},function(){var e={readDoubleBE:8,readDoubleLE:8,readFloatBE:4,readFloatLE:4,readInt32BE:4,readInt32LE:4,readUInt32BE:4,readUInt32LE:4,readInt16BE:2,readInt16LE:2,readUInt16BE:2,readUInt16LE:2,readInt8:1,readUInt8:1};for(var t in e)!function(t){n.prototype[t]=function(r){return this.slice(r,r+e[t])[t](0)}}(t)}(),t.exports=n}).call(this,e("buffer").Buffer)},{buffer:17,"readable-stream":95,util:39}],80:[function(e,t){(function(r,n){function o(e){s.call(this,"string"==typeof e?e:""),this._db=void 0,this._operations=[]}var i=e("util"),s=e("abstract-leveldown").AbstractLevelDOWN;i.inherits(o,s),o.prototype.setDb=function(e){this._db=e,this._operations.forEach(function(t){e[t.method].apply(e,t.args)})},o.prototype._open=function(e,t){return r.nextTick(t)},o.prototype._operation=function(e,t){return this._db?this._db[e].apply(this._db,t):void this._operations.push({method:e,args:t})},"put get del batch approximateSize".split(" ").forEach(function(e){o.prototype["_"+e]=function(){this._operation(e,arguments)}}),o.prototype._isBuffer=function(e){return n.isBuffer(e)},o.prototype._iterator=function(){throw new TypeError("not implemented")},t.exports=o}).call(this,e("_process"),e("buffer").Buffer)},{_process:24,"abstract-leveldown":83,buffer:17,util:39}],81:[function(e,t){t.exports=e(46)},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/abstract-leveldown/abstract-chained-batch.js":46,_process:24}],82:[function(e,t){t.exports=e(47)},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/abstract-leveldown/abstract-iterator.js":47,_process:24}],83:[function(e,t){t.exports=e(48)},{"./abstract-chained-batch":81,"./abstract-iterator":82,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/abstract-leveldown/abstract-leveldown.js":48,_process:24,buffer:17,xtend:96}],84:[function(e,t){function r(e,t,r){i(this,{type:e,name:e,cause:"string"!=typeof t?t:r,message:t&&"string"!=typeof t?t.message:t},"ewr")}function n(e,t){Error.call(this),Error.captureStackTrace&&Error.captureStackTrace(this,arguments.callee),r.call(this,"CustomError",e,t)}function o(e,t,o){var i=function(n,o){r.call(this,t,n,o),"FilesystemError"==t&&(this.code=this.cause.code,this.path=this.cause.path,this.errno=this.cause.errno,this.message=(e.errno[this.cause.errno]?e.errno[this.cause.errno].description:this.cause.message)+(this.cause.path?" ["+this.cause.path+"]":"")),Error.call(this),Error.captureStackTrace&&Error.captureStackTrace(this,arguments.callee)};return i.prototype=o?new o:new n,i}var i=e("prr");n.prototype=new Error,t.exports=function(e){var t=function(t,r){return o(e,t,r)};return{CustomError:n,FilesystemError:t("FilesystemError"),createError:t}}},{prr:86}],85:[function(e,t){var r=t.exports.all=[{errno:-1,code:"UNKNOWN",description:"unknown error"},{errno:0,code:"OK",description:"success"},{errno:1,code:"EOF",description:"end of file"},{errno:2,code:"EADDRINFO",description:"getaddrinfo error"},{errno:3,code:"EACCES",description:"permission denied"},{errno:4,code:"EAGAIN",description:"resource temporarily unavailable"},{errno:5,code:"EADDRINUSE",description:"address already in use"},{errno:6,code:"EADDRNOTAVAIL",description:"address not available"},{errno:7,code:"EAFNOSUPPORT",description:"address family not supported"},{errno:8,code:"EALREADY",description:"connection already in progress"},{errno:9,code:"EBADF",description:"bad file descriptor"},{errno:10,code:"EBUSY",description:"resource busy or locked"},{errno:11,code:"ECONNABORTED",description:"software caused connection abort"},{errno:12,code:"ECONNREFUSED",description:"connection refused"},{errno:13,code:"ECONNRESET",description:"connection reset by peer"},{errno:14,code:"EDESTADDRREQ",description:"destination address required"},{errno:15,code:"EFAULT",description:"bad address in system call argument"},{errno:16,code:"EHOSTUNREACH",description:"host is unreachable"},{errno:17,code:"EINTR",description:"interrupted system call"},{errno:18,code:"EINVAL",description:"invalid argument"},{errno:19,code:"EISCONN",description:"socket is already connected"},{errno:20,code:"EMFILE",description:"too many open files"},{errno:21,code:"EMSGSIZE",description:"message too long"},{errno:22,code:"ENETDOWN",description:"network is down"},{errno:23,code:"ENETUNREACH",description:"network is unreachable"},{errno:24,code:"ENFILE",description:"file table overflow"},{errno:25,code:"ENOBUFS",description:"no buffer space available"},{errno:26,code:"ENOMEM",description:"not enough memory"},{errno:27,code:"ENOTDIR",description:"not a directory"},{errno:28,code:"EISDIR",description:"illegal operation on a directory"},{errno:29,code:"ENONET",description:"machine is not on the network"},{errno:31,code:"ENOTCONN",description:"socket is not connected"},{errno:32,code:"ENOTSOCK",description:"socket operation on non-socket"},{errno:33,code:"ENOTSUP",description:"operation not supported on socket"},{errno:34,code:"ENOENT",description:"no such file or directory"},{errno:35,code:"ENOSYS",description:"function not implemented"},{errno:36,code:"EPIPE",description:"broken pipe"},{errno:37,code:"EPROTO",description:"protocol error"},{errno:38,code:"EPROTONOSUPPORT",description:"protocol not supported"},{errno:39,code:"EPROTOTYPE",description:"protocol wrong type for socket"},{errno:40,code:"ETIMEDOUT",description:"connection timed out"},{errno:41,code:"ECHARSET",description:"invalid Unicode character"},{errno:42,code:"EAIFAMNOSUPPORT",description:"address family for hostname not supported"},{errno:44,code:"EAISERVICE",description:"servname not supported for ai_socktype"},{errno:45,code:"EAISOCKTYPE",description:"ai_socktype not supported"},{errno:46,code:"ESHUTDOWN",description:"cannot send after transport endpoint shutdown"},{errno:47,code:"EEXIST",description:"file already exists"},{errno:48,code:"ESRCH",description:"no such process"},{errno:49,code:"ENAMETOOLONG",description:"name too long"},{errno:50,code:"EPERM",description:"operation not permitted"},{errno:51,code:"ELOOP",description:"too many symbolic links encountered"},{errno:52,code:"EXDEV",description:"cross-device link not permitted"},{errno:53,code:"ENOTEMPTY",description:"directory not empty"},{errno:54,code:"ENOSPC",description:"no space left on device"},{errno:55,code:"EIO",description:"i/o error"},{errno:56,code:"EROFS",description:"read-only file system"},{errno:57,code:"ENODEV",description:"no such device"},{errno:58,code:"ESPIPE",description:"invalid seek"},{errno:59,code:"ECANCELED",description:"operation canceled"}];t.exports.errno={"-1":r[0],0:r[1],1:r[2],2:r[3],3:r[4],4:r[5],5:r[6],6:r[7],7:r[8],8:r[9],9:r[10],10:r[11],11:r[12],12:r[13],13:r[14],14:r[15],15:r[16],16:r[17],17:r[18],18:r[19],19:r[20],20:r[21],21:r[22],22:r[23],23:r[24],24:r[25],25:r[26],26:r[27],27:r[28],28:r[29],29:r[30],31:r[31],32:r[32],33:r[33],34:r[34],35:r[35],36:r[36],37:r[37],38:r[38],39:r[39],40:r[40],41:r[41],42:r[42],44:r[43],45:r[44],46:r[45],47:r[46],48:r[47],49:r[48],50:r[49],51:r[50],52:r[51],53:r[52],54:r[53],55:r[54],56:r[55],57:r[56],58:r[57],59:r[58]},t.exports.code={UNKNOWN:r[0],OK:r[1],EOF:r[2],EADDRINFO:r[3],EACCES:r[4],EAGAIN:r[5],EADDRINUSE:r[6],EADDRNOTAVAIL:r[7],EAFNOSUPPORT:r[8],EALREADY:r[9],EBADF:r[10],EBUSY:r[11],ECONNABORTED:r[12],ECONNREFUSED:r[13],ECONNRESET:r[14],EDESTADDRREQ:r[15],EFAULT:r[16],EHOSTUNREACH:r[17],EINTR:r[18],EINVAL:r[19],EISCONN:r[20],EMFILE:r[21],EMSGSIZE:r[22],ENETDOWN:r[23],ENETUNREACH:r[24],ENFILE:r[25],ENOBUFS:r[26],ENOMEM:r[27],ENOTDIR:r[28],EISDIR:r[29],ENONET:r[30],ENOTCONN:r[31],ENOTSOCK:r[32],ENOTSUP:r[33],ENOENT:r[34],ENOSYS:r[35],EPIPE:r[36],EPROTO:r[37],EPROTONOSUPPORT:r[38],EPROTOTYPE:r[39],ETIMEDOUT:r[40],ECHARSET:r[41],EAIFAMNOSUPPORT:r[42],EAISERVICE:r[43],EAISOCKTYPE:r[44],ESHUTDOWN:r[45],EEXIST:r[46],ESRCH:r[47],ENAMETOOLONG:r[48],EPERM:r[49],ELOOP:r[50],EXDEV:r[51],ENOTEMPTY:r[52],ENOSPC:r[53],EIO:r[54],EROFS:r[55],ENODEV:r[56],ESPIPE:r[57],ECANCELED:r[58]},t.exports.custom=e("./custom")(t.exports),t.exports.create=t.exports.custom.createError},{"./custom":84}],86:[function(e,t){!function(e,r,n){"undefined"!=typeof t&&t.exports?t.exports=n():r[e]=n()}("prr",this,function(){var e="function"==typeof Object.defineProperty?function(e,t,r){return Object.defineProperty(e,t,r),e}:function(e,t,r){return e[t]=r.value,e},t=function(e,t){var r="object"==typeof t,n=!r&&"string"==typeof t,o=function(e){return r?!!t[e]:n?t.indexOf(e[0])>-1:!1};return{enumerable:o("enumerable"),configurable:o("configurable"),writable:o("writable"),value:e}},r=function(r,n,o,i){var s;if(i=t(o,i),"object"==typeof n){for(s in n)Object.hasOwnProperty.call(n,s)&&(i.value=n[s],e(r,s,i));return r}return e(r,n,i)};return r})},{}],87:[function(e,t){t.exports=e(26)},{"./_stream_readable":89,"./_stream_writable":91,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_duplex.js":26,_process:24,"core-util-is":92,inherits:44}],88:[function(e,t){t.exports=e(27)},{"./_stream_transform":90,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_passthrough.js":27,"core-util-is":92,inherits:44}],89:[function(e,t){t.exports=e(28)},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_readable.js":28,_process:24,buffer:17,"core-util-is":92,events:21,inherits:44,isarray:93,stream:36,"string_decoder/":94}],90:[function(e,t){t.exports=e(29) +},{"./_stream_duplex":87,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_transform.js":29,"core-util-is":92,inherits:44}],91:[function(e,t){t.exports=e(30)},{"./_stream_duplex":87,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_writable.js":30,_process:24,buffer:17,"core-util-is":92,inherits:44,stream:36}],92:[function(e,t){t.exports=e(31)},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/node_modules/core-util-is/lib/util.js":31,buffer:17}],93:[function(e,t){t.exports=e(22)},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/isarray/index.js":22}],94:[function(e,t){t.exports=e(37)},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/string_decoder/index.js":37,buffer:17}],95:[function(e,t){t.exports=e(33)},{"./lib/_stream_duplex.js":87,"./lib/_stream_passthrough.js":88,"./lib/_stream_readable.js":89,"./lib/_stream_transform.js":90,"./lib/_stream_writable.js":91,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/readable.js":33,stream:36}],96:[function(e,t){t.exports=e(49)},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/abstract-leveldown/node_modules/xtend/index.js":49}],97:[function(e,t){t.exports={name:"levelup",description:"Fast & simple storage - a Node.js-style LevelDB wrapper",version:"0.18.6",contributors:[{name:"Rod Vagg",email:"r@va.gg",url:"https://github.com/rvagg"},{name:"John Chesley",email:"john@chesl.es",url:"https://github.com/chesles/"},{name:"Jake Verbaten",email:"raynos2@gmail.com",url:"https://github.com/raynos"},{name:"Dominic Tarr",email:"dominic.tarr@gmail.com",url:"https://github.com/dominictarr"},{name:"Max Ogden",email:"max@maxogden.com",url:"https://github.com/maxogden"},{name:"Lars-Magnus Skog",email:"lars.magnus.skog@gmail.com",url:"https://github.com/ralphtheninja"},{name:"David Björklund",email:"david.bjorklund@gmail.com",url:"https://github.com/kesla"},{name:"Julian Gruber",email:"julian@juliangruber.com",url:"https://github.com/juliangruber"},{name:"Paolo Fragomeni",email:"paolo@async.ly",url:"https://github.com/hij1nx"},{name:"Anton Whalley",email:"anton.whalley@nearform.com",url:"https://github.com/No9"},{name:"Matteo Collina",email:"matteo.collina@gmail.com",url:"https://github.com/mcollina"},{name:"Pedro Teixeira",email:"pedro.teixeira@gmail.com",url:"https://github.com/pgte"},{name:"James Halliday",email:"mail@substack.net",url:"https://github.com/substack"}],repository:{type:"git",url:"https://github.com/rvagg/node-levelup.git"},homepage:"https://github.com/rvagg/node-levelup",keywords:["leveldb","stream","database","db","store","storage","json"],main:"lib/levelup.js",dependencies:{bl:"~0.8.1","deferred-leveldown":"~0.2.0",errno:"~0.1.1",prr:"~0.0.0","readable-stream":"~1.0.26",semver:"~2.3.1",xtend:"~3.0.0"},devDependencies:{leveldown:"~0.10.0",bustermove:"*",tap:"*",referee:"*",rimraf:"*",async:"*",fstream:"*",tar:"*",mkfiletree:"*",readfiletree:"*","slow-stream":">=0.0.4",delayed:"*",boganipsum:"*",du:"*",memdown:"*","msgpack-js":"*"},browser:{leveldown:!1,"leveldown/package":!1,semver:!1},scripts:{test:"tap test/*-test.js --stderr",functionaltests:"node ./test/functional/fstream-test.js && node ./test/functional/binary-data-test.js && node ./test/functional/compat-test.js",alltests:"npm test && npm run-script functionaltests"},license:"MIT",gitHead:"213e989e2b75273e2b44c23f84f95e35bff7ea11",bugs:{url:"https://github.com/rvagg/node-levelup/issues"},_id:"levelup@0.18.6",_shasum:"e6a01cb089616c8ecc0291c2a9bd3f0c44e3e5eb",_from:"levelup@~0.18.4",_npmVersion:"1.4.14",_npmUser:{name:"rvagg",email:"rod@vagg.org"},maintainers:[{name:"rvagg",email:"rod@vagg.org"}],dist:{shasum:"e6a01cb089616c8ecc0291c2a9bd3f0c44e3e5eb",tarball:"http://127.0.0.1:5080/tarballs/levelup/0.18.6.tgz"},_resolved:"http://127.0.0.1:5080/tarballs/levelup/0.18.6.tgz",readme:"ERROR: No README data found!"}},{}],98:[function(e,t){"use strict";function r(){}t.exports=r},{}],99:[function(e,t){"use strict";function r(e){function t(e,t){function n(e){c[t]=e,++f===r&!u&&(u=!0,a.resolve(d,c))}i(e).then(n,function(e){u||(u=!0,a.reject(d,e))})}if("[object Array]"!==Object.prototype.toString.call(e))return o(new TypeError("must be an array"));var r=e.length,u=!1;if(!r)return i([]);for(var c=new Array(r),f=0,l=-1,d=new n(s);++l<r;)t(e[l],l);return d}var n=e("./promise"),o=e("./reject"),i=e("./resolve"),s=e("./INTERNAL"),a=e("./handlers");t.exports=r},{"./INTERNAL":98,"./handlers":100,"./promise":102,"./reject":105,"./resolve":106}],100:[function(e,t,r){"use strict";function n(e){var t=e&&e.then;return e&&"object"==typeof e&&"function"==typeof t?function(){t.apply(e,arguments)}:void 0}var o=e("./tryCatch"),i=e("./resolveThenable"),s=e("./states");r.resolve=function(e,t){var a=o(n,t);if("error"===a.status)return r.reject(e,a.value);var u=a.value;if(u)i.safely(e,u);else{e.state=s.FULFILLED,e.outcome=t;for(var c=-1,f=e.queue.length;++c<f;)e.queue[c].callFulfilled(t)}return e},r.reject=function(e,t){e.state=s.REJECTED,e.outcome=t;for(var r=-1,n=e.queue.length;++r<n;)e.queue[r].callRejected(t);return e}},{"./resolveThenable":107,"./states":108,"./tryCatch":109}],101:[function(e,t,r){t.exports=r=e("./promise"),r.resolve=e("./resolve"),r.reject=e("./reject"),r.all=e("./all"),r.race=e("./race")},{"./all":99,"./promise":102,"./race":104,"./reject":105,"./resolve":106}],102:[function(e,t){"use strict";function r(e){if(!(this instanceof r))return new r(e);if("function"!=typeof e)throw new TypeError("reslover must be a function");this.state=s.PENDING,this.queue=[],this.outcome=void 0,e!==o&&i.safely(this,e)}var n=e("./unwrap"),o=e("./INTERNAL"),i=e("./resolveThenable"),s=e("./states"),a=e("./queueItem");t.exports=r,r.prototype["catch"]=function(e){return this.then(null,e)},r.prototype.then=function(e,t){if("function"!=typeof e&&this.state===s.FULFILLED||"function"!=typeof t&&this.state===s.REJECTED)return this;var i=new r(o);if(this.state!==s.PENDING){var u=this.state===s.FULFILLED?e:t;n(i,u,this.outcome)}else this.queue.push(new a(i,e,t));return i}},{"./INTERNAL":98,"./queueItem":103,"./resolveThenable":107,"./states":108,"./unwrap":110}],103:[function(e,t){"use strict";function r(e,t,r){this.promise=e,"function"==typeof t&&(this.onFulfilled=t,this.callFulfilled=this.otherCallFulfilled),"function"==typeof r&&(this.onRejected=r,this.callRejected=this.otherCallRejected)}var n=e("./handlers"),o=e("./unwrap");t.exports=r,r.prototype.callFulfilled=function(e){n.resolve(this.promise,e)},r.prototype.otherCallFulfilled=function(e){o(this.promise,this.onFulfilled,e)},r.prototype.callRejected=function(e){n.reject(this.promise,e)},r.prototype.otherCallRejected=function(e){o(this.promise,this.onRejected,e)}},{"./handlers":100,"./unwrap":110}],104:[function(e,t){"use strict";function r(e){function t(e){i(e).then(function(e){u||(u=!0,a.resolve(f,e))},function(e){u||(u=!0,a.reject(f,e))})}if("[object Array]"!==Object.prototype.toString.call(e))return o(new TypeError("must be an array"));var r=e.length,u=!1;if(!r)return i([]);for(var c=-1,f=new n(s);++c<r;)t(e[c]);return f}var n=e("./promise"),o=e("./reject"),i=e("./resolve"),s=e("./INTERNAL"),a=e("./handlers");t.exports=r},{"./INTERNAL":98,"./handlers":100,"./promise":102,"./reject":105,"./resolve":106}],105:[function(e,t){"use strict";function r(e){var t=new n(o);return i.reject(t,e)}var n=e("./promise"),o=e("./INTERNAL"),i=e("./handlers");t.exports=r},{"./INTERNAL":98,"./handlers":100,"./promise":102}],106:[function(e,t){"use strict";function r(e){if(e)return e instanceof n?e:i.resolve(new n(o),e);var t=typeof e;switch(t){case"boolean":return s;case"undefined":return u;case"object":return a;case"number":return c;case"string":return f}}var n=e("./promise"),o=e("./INTERNAL"),i=e("./handlers");t.exports=r;var s=i.resolve(new n(o),!1),a=i.resolve(new n(o),null),u=i.resolve(new n(o),void 0),c=i.resolve(new n(o),0),f=i.resolve(new n(o),"")},{"./INTERNAL":98,"./handlers":100,"./promise":102}],107:[function(e,t,r){"use strict";function n(e,t){function r(t){a||(a=!0,o.reject(e,t))}function n(t){a||(a=!0,o.resolve(e,t))}function s(){t(n,r)}var a=!1,u=i(s);"error"===u.status&&r(u.value)}var o=e("./handlers"),i=e("./tryCatch");r.safely=n},{"./handlers":100,"./tryCatch":109}],108:[function(e,t,r){r.REJECTED=["REJECTED"],r.FULFILLED=["FULFILLED"],r.PENDING=["PENDING"]},{}],109:[function(e,t){"use strict";function r(e,t){var r={};try{r.value=e(t),r.status="success"}catch(n){r.status="error",r.value=n}return r}t.exports=r},{}],110:[function(e,t){"use strict";function r(e,t,r){n(function(){var n;try{n=t(r)}catch(i){return o.reject(e,i)}n===e?o.reject(e,new TypeError("Cannot resolve promise with itself")):o.resolve(e,n)})}var n=e("immediate"),o=e("./handlers");t.exports=r},{"./handlers":100,immediate:111}],111:[function(e,t){"use strict";function r(){o=!0;for(var e,t,r=a.length;r;){for(t=a,a=[],e=-1;++e<r;)t[e]();r=a.length}o=!1}function n(e){1!==a.push(e)||o||i()}for(var o,i,s=[e("./nextTick"),e("./mutation.js"),e("./messageChannel"),e("./stateChange"),e("./timeout")],a=[],u=-1,c=s.length;++u<c;)if(s[u]&&s[u].test&&s[u].test()){i=s[u].install(r);break}t.exports=n},{"./messageChannel":112,"./mutation.js":113,"./nextTick":16,"./stateChange":114,"./timeout":115}],112:[function(e,t,r){(function(e){"use strict";r.test=function(){return e.setImmediate?!1:"undefined"!=typeof e.MessageChannel},r.install=function(t){var r=new e.MessageChannel;return r.port1.onmessage=t,function(){r.port2.postMessage(0)}}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],113:[function(e,t,r){(function(e){"use strict";var t=e.MutationObserver||e.WebKitMutationObserver;r.test=function(){return t},r.install=function(r){var n=0,o=new t(r),i=e.document.createTextNode("");return o.observe(i,{characterData:!0}),function(){i.data=n=++n%2}}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],114:[function(e,t,r){(function(e){"use strict";r.test=function(){return"document"in e&&"onreadystatechange"in e.document.createElement("script")},r.install=function(t){return function(){var r=e.document.createElement("script");return r.onreadystatechange=function(){t(),r.onreadystatechange=null,r.parentNode.removeChild(r),r=null},e.document.documentElement.appendChild(r),t}}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],115:[function(e,t,r){"use strict";r.test=function(){return!0},r.install=function(e){return function(){setTimeout(e,0)}}},{}],116:[function(e,t){"use strict";function r(e){return null===e?String(e):"object"==typeof e||"function"==typeof e?u[d.call(e)]||"object":typeof e}function n(e){return null!==e&&e===e.window}function o(e){if(!e||"object"!==r(e)||e.nodeType||n(e))return!1;try{if(e.constructor&&!h.call(e,"constructor")&&!h.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(t){return!1}var o;for(o in e);return void 0===o||h.call(e,o)}function i(e){return"function"===r(e)}function s(){for(var e=[],t=-1,r=arguments.length,n=new Array(r);++t<r;)n[t]=arguments[t];var o={};e.push({args:n,result:{container:o,key:"key"}});for(var i;i=e.pop();)a(e,i.args,i.result);return o.key}function a(e,t,r){var n,s,a,u,c,f,l,d=t[0]||{},h=1,v=t.length,y=!1,g=/\d+/;for("boolean"==typeof d&&(y=d,d=t[1]||{},h=2),"object"==typeof d||i(d)||(d={}),v===h&&(d=this,--h);v>h;h++)if(null!=(n=t[h])){l=p(n);for(s in n)if(!(s in Object.prototype)){if(l&&!g.test(s))continue;if(a=d[s],u=n[s],d===u)continue;y&&u&&(o(u)||(c=p(u)))?(c?(c=!1,f=a&&p(a)?a:[]):f=a&&o(a)?a:{},e.push({args:[y,f,u],result:{container:d,key:s}})):void 0!==u&&(p(n)&&i(u)||(d[s]=u))}}r.container[r.key]=d}for(var u={},c=["Boolean","Number","String","Function","Array","Date","RegExp","Object","Error"],f=0;f<c.length;f++){var l=c[f];u["[object "+l+"]"]=l.toLowerCase()}var d=u.toString,h=u.hasOwnProperty,p=Array.isArray||function(e){return"array"===r(e)};t.exports=s},{}],117:[function(e,t,r){!function(e){if("object"==typeof r)t.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var n;try{n=window}catch(o){n=self}n.SparkMD5=e()}}(function(){"use strict";var e=function(e,t){return e+t&4294967295},t=function(t,r,n,o,i,s){return r=e(e(r,t),e(o,s)),e(r<<i|r>>>32-i,n)},r=function(e,r,n,o,i,s,a){return t(r&n|~r&o,e,r,i,s,a)},n=function(e,r,n,o,i,s,a){return t(r&o|n&~o,e,r,i,s,a)},o=function(e,r,n,o,i,s,a){return t(r^n^o,e,r,i,s,a)},i=function(e,r,n,o,i,s,a){return t(n^(r|~o),e,r,i,s,a)},s=function(t,s){var a=t[0],u=t[1],c=t[2],f=t[3];a=r(a,u,c,f,s[0],7,-680876936),f=r(f,a,u,c,s[1],12,-389564586),c=r(c,f,a,u,s[2],17,606105819),u=r(u,c,f,a,s[3],22,-1044525330),a=r(a,u,c,f,s[4],7,-176418897),f=r(f,a,u,c,s[5],12,1200080426),c=r(c,f,a,u,s[6],17,-1473231341),u=r(u,c,f,a,s[7],22,-45705983),a=r(a,u,c,f,s[8],7,1770035416),f=r(f,a,u,c,s[9],12,-1958414417),c=r(c,f,a,u,s[10],17,-42063),u=r(u,c,f,a,s[11],22,-1990404162),a=r(a,u,c,f,s[12],7,1804603682),f=r(f,a,u,c,s[13],12,-40341101),c=r(c,f,a,u,s[14],17,-1502002290),u=r(u,c,f,a,s[15],22,1236535329),a=n(a,u,c,f,s[1],5,-165796510),f=n(f,a,u,c,s[6],9,-1069501632),c=n(c,f,a,u,s[11],14,643717713),u=n(u,c,f,a,s[0],20,-373897302),a=n(a,u,c,f,s[5],5,-701558691),f=n(f,a,u,c,s[10],9,38016083),c=n(c,f,a,u,s[15],14,-660478335),u=n(u,c,f,a,s[4],20,-405537848),a=n(a,u,c,f,s[9],5,568446438),f=n(f,a,u,c,s[14],9,-1019803690),c=n(c,f,a,u,s[3],14,-187363961),u=n(u,c,f,a,s[8],20,1163531501),a=n(a,u,c,f,s[13],5,-1444681467),f=n(f,a,u,c,s[2],9,-51403784),c=n(c,f,a,u,s[7],14,1735328473),u=n(u,c,f,a,s[12],20,-1926607734),a=o(a,u,c,f,s[5],4,-378558),f=o(f,a,u,c,s[8],11,-2022574463),c=o(c,f,a,u,s[11],16,1839030562),u=o(u,c,f,a,s[14],23,-35309556),a=o(a,u,c,f,s[1],4,-1530992060),f=o(f,a,u,c,s[4],11,1272893353),c=o(c,f,a,u,s[7],16,-155497632),u=o(u,c,f,a,s[10],23,-1094730640),a=o(a,u,c,f,s[13],4,681279174),f=o(f,a,u,c,s[0],11,-358537222),c=o(c,f,a,u,s[3],16,-722521979),u=o(u,c,f,a,s[6],23,76029189),a=o(a,u,c,f,s[9],4,-640364487),f=o(f,a,u,c,s[12],11,-421815835),c=o(c,f,a,u,s[15],16,530742520),u=o(u,c,f,a,s[2],23,-995338651),a=i(a,u,c,f,s[0],6,-198630844),f=i(f,a,u,c,s[7],10,1126891415),c=i(c,f,a,u,s[14],15,-1416354905),u=i(u,c,f,a,s[5],21,-57434055),a=i(a,u,c,f,s[12],6,1700485571),f=i(f,a,u,c,s[3],10,-1894986606),c=i(c,f,a,u,s[10],15,-1051523),u=i(u,c,f,a,s[1],21,-2054922799),a=i(a,u,c,f,s[8],6,1873313359),f=i(f,a,u,c,s[15],10,-30611744),c=i(c,f,a,u,s[6],15,-1560198380),u=i(u,c,f,a,s[13],21,1309151649),a=i(a,u,c,f,s[4],6,-145523070),f=i(f,a,u,c,s[11],10,-1120210379),c=i(c,f,a,u,s[2],15,718787259),u=i(u,c,f,a,s[9],21,-343485551),t[0]=e(a,t[0]),t[1]=e(u,t[1]),t[2]=e(c,t[2]),t[3]=e(f,t[3])},a=function(e){var t,r=[];for(t=0;64>t;t+=4)r[t>>2]=e.charCodeAt(t)+(e.charCodeAt(t+1)<<8)+(e.charCodeAt(t+2)<<16)+(e.charCodeAt(t+3)<<24);return r},u=function(e){var t,r=[];for(t=0;64>t;t+=4)r[t>>2]=e[t]+(e[t+1]<<8)+(e[t+2]<<16)+(e[t+3]<<24);return r},c=function(e){var t,r,n,o,i,u,c=e.length,f=[1732584193,-271733879,-1732584194,271733878];for(t=64;c>=t;t+=64)s(f,a(e.substring(t-64,t)));for(e=e.substring(t-64),r=e.length,n=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],t=0;r>t;t+=1)n[t>>2]|=e.charCodeAt(t)<<(t%4<<3);if(n[t>>2]|=128<<(t%4<<3),t>55)for(s(f,n),t=0;16>t;t+=1)n[t]=0;return o=8*c,o=o.toString(16).match(/(.*?)(.{0,8})$/),i=parseInt(o[2],16),u=parseInt(o[1],16)||0,n[14]=i,n[15]=u,s(f,n),f},f=function(e){var t,r,n,o,i,a,c=e.length,f=[1732584193,-271733879,-1732584194,271733878];for(t=64;c>=t;t+=64)s(f,u(e.subarray(t-64,t)));for(e=c>t-64?e.subarray(t-64):new Uint8Array(0),r=e.length,n=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],t=0;r>t;t+=1)n[t>>2]|=e[t]<<(t%4<<3);if(n[t>>2]|=128<<(t%4<<3),t>55)for(s(f,n),t=0;16>t;t+=1)n[t]=0;return o=8*c,o=o.toString(16).match(/(.*?)(.{0,8})$/),i=parseInt(o[2],16),a=parseInt(o[1],16)||0,n[14]=i,n[15]=a,s(f,n),f},l=["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"],d=function(e){var t,r="";for(t=0;4>t;t+=1)r+=l[e>>8*t+4&15]+l[e>>8*t&15];return r},h=function(e){var t;for(t=0;t<e.length;t+=1)e[t]=d(e[t]);return e.join("")},p=function(e){return h(c(e))},v=function(){this.reset()};return"5d41402abc4b2a76b9719d911017c592"!==p("hello")&&(e=function(e,t){var r=(65535&e)+(65535&t),n=(e>>16)+(t>>16)+(r>>16);return n<<16|65535&r}),v.prototype.append=function(e){return/[\u0080-\uFFFF]/.test(e)&&(e=unescape(encodeURIComponent(e))),this.appendBinary(e),this},v.prototype.appendBinary=function(e){this._buff+=e,this._length+=e.length;var t,r=this._buff.length;for(t=64;r>=t;t+=64)s(this._state,a(this._buff.substring(t-64,t)));return this._buff=this._buff.substr(t-64),this},v.prototype.end=function(e){var t,r,n=this._buff,o=n.length,i=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];for(t=0;o>t;t+=1)i[t>>2]|=n.charCodeAt(t)<<(t%4<<3);return this._finish(i,o),r=e?this._state:h(this._state),this.reset(),r},v.prototype._finish=function(e,t){var r,n,o,i=t;if(e[i>>2]|=128<<(i%4<<3),i>55)for(s(this._state,e),i=0;16>i;i+=1)e[i]=0;r=8*this._length,r=r.toString(16).match(/(.*?)(.{0,8})$/),n=parseInt(r[2],16),o=parseInt(r[1],16)||0,e[14]=n,e[15]=o,s(this._state,e)},v.prototype.reset=function(){return this._buff="",this._length=0,this._state=[1732584193,-271733879,-1732584194,271733878],this},v.prototype.destroy=function(){delete this._state,delete this._buff,delete this._length},v.hash=function(e,t){/[\u0080-\uFFFF]/.test(e)&&(e=unescape(encodeURIComponent(e)));var r=c(e);return t?r:h(r)},v.hashBinary=function(e,t){var r=c(e);return t?r:h(r)},v.ArrayBuffer=function(){this.reset()},v.ArrayBuffer.prototype.append=function(e){var t,r=this._concatArrayBuffer(this._buff,e),n=r.length;for(this._length+=e.byteLength,t=64;n>=t;t+=64)s(this._state,u(r.subarray(t-64,t)));return this._buff=n>t-64?r.subarray(t-64):new Uint8Array(0),this},v.ArrayBuffer.prototype.end=function(e){var t,r,n=this._buff,o=n.length,i=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];for(t=0;o>t;t+=1)i[t>>2]|=n[t]<<(t%4<<3);return this._finish(i,o),r=e?this._state:h(this._state),this.reset(),r},v.ArrayBuffer.prototype._finish=v.prototype._finish,v.ArrayBuffer.prototype.reset=function(){return this._buff=new Uint8Array(0),this._length=0,this._state=[1732584193,-271733879,-1732584194,271733878],this},v.ArrayBuffer.prototype.destroy=v.prototype.destroy,v.ArrayBuffer.prototype._concatArrayBuffer=function(e,t){var r=e.length,n=new Uint8Array(r+t.byteLength);return n.set(e),n.set(new Uint8Array(t),r),n},v.ArrayBuffer.hash=function(e,t){var r=f(new Uint8Array(e));return t?r:h(r)},v})},{}],118:[function(e,t){t.exports=e(26)},{"./_stream_readable":119,"./_stream_writable":121,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_duplex.js":26,_process:24,"core-util-is":122,inherits:44}],119:[function(e,t){t.exports=e(28)},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_readable.js":28,_process:24,buffer:17,"core-util-is":122,events:21,inherits:44,isarray:123,stream:36,"string_decoder/":124}],120:[function(e,t){t.exports=e(29)},{"./_stream_duplex":118,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_transform.js":29,"core-util-is":122,inherits:44}],121:[function(e,t){t.exports=e(30)},{"./_stream_duplex":118,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_writable.js":30,_process:24,buffer:17,"core-util-is":122,inherits:44,stream:36}],122:[function(e,t){t.exports=e(31)},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/node_modules/core-util-is/lib/util.js":31,buffer:17}],123:[function(e,t){t.exports=e(22)},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/isarray/index.js":22}],124:[function(e,t){t.exports=e(37)},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/string_decoder/index.js":37,buffer:17}],125:[function(e,t){t.exports=e(34)},{"./lib/_stream_transform.js":120,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/transform.js":34}],126:[function(e,t){t.exports=e(54)},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/has-keys.js":54}],127:[function(e,t){t.exports=e(55)},{"./has-keys":126,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/index.js":55,"object-keys":129}],128:[function(e,t){t.exports=e(56)},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/foreach.js":56}],129:[function(e,t){t.exports=e(57)},{"./shim":131,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/index.js":57}],130:[function(e,t){t.exports=e(58)},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/isArguments.js":58}],131:[function(e,t){t.exports=e(59)},{"./foreach":128,"./isArguments":130,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/shim.js":59}],132:[function(e,t){function r(e,t,r){r(null,e)}function n(e){return function(t,n,o){return"function"==typeof t&&(o=n,n=t,t={}),"function"!=typeof n&&(n=r),"function"!=typeof o&&(o=null),e(t,n,o)}}var o=e("readable-stream/transform"),i=e("util").inherits,s=e("xtend");t.exports=n(function(e,t,r){var n=new o(e);return n._transform=t,r&&(n._flush=r),n}),t.exports.ctor=n(function(e,t,r){function n(t){return this instanceof n?(this.options=s(e,t),void o.call(this,this.options)):new n(t)}return i(n,o),n.prototype._transform=t,r&&(n.prototype._flush=r),n}),t.exports.obj=n(function(e,t,r){var n=new o(s({objectMode:!0},e));return n._transform=t,r&&(n._flush=r),n})},{"readable-stream/transform":125,util:39,xtend:127}],133:[function(e,t,r){"use strict";function n(e,t,r){var n=r[r.length-1];e===n.element&&(r.pop(),n=r[r.length-1]);var o=n.element,i=n.index;if(Array.isArray(o))o.push(e);else if(i===t.length-2){var s=t.pop();o[s]=e}else t.push(e)}r.stringify=function(e){var t=[];t.push({obj:e});for(var r,n,o,i,s,a,u,c,f,l,d,h="";r=t.pop();)if(n=r.obj,o=r.prefix||"",i=r.val||"",h+=o,i)h+=i;else if("object"!=typeof n)h+="undefined"==typeof n?null:JSON.stringify(n);else if(null===n)h+="null";else if(Array.isArray(n)){for(t.push({val:"]"}),s=n.length-1;s>=0;s--)a=0===s?"":",",t.push({obj:n[s],prefix:a});t.push({val:"["})}else{u=[];for(c in n)n.hasOwnProperty(c)&&u.push(c);for(t.push({val:"}"}),s=u.length-1;s>=0;s--)f=u[s],l=n[f],d=s>0?",":"",d+=JSON.stringify(f)+":",t.push({obj:l,prefix:d});t.push({val:"{"})}return h},r.parse=function(e){for(var t,r,o,i,s,a,u,c,f,l=[],d=[],h=0;;)if(t=e[h++],"}"!==t&&"]"!==t&&"undefined"!=typeof t)switch(t){case" ":case" ":case"\n":case":":case",":break;case"n":h+=3,n(null,l,d);break;case"t":h+=3,n(!0,l,d);break;case"f":h+=4,n(!1,l,d);break;case"0":case"1":case"2":case"3":case"4":case"5":case"6":case"7":case"8":case"9":case"-":for(r="",h--;;){if(o=e[h++],!/[\d\.\-e\+]/.test(o)){h--;break}r+=o}n(parseFloat(r),l,d);break;case'"':for(i="",s=void 0,a=0;;){if(u=e[h++],'"'===u&&("\\"!==s||a%2!==1))break;i+=u,s=u,"\\"===s?a++:a=0}n(JSON.parse('"'+i+'"'),l,d);break;case"[":c={element:[],index:l.length},l.push(c.element),d.push(c);break;case"{":f={element:{},index:l.length},l.push(f.element),d.push(f);break;default:throw new Error("unexpectedly reached end of input: "+t)}else{if(1===l.length)return l.pop();n(l.pop(),l,d)}}},{}],"adapter-config":[function(e,t){(function(e){"use strict";t.exports={name:"localstorage",valid:function(){return"localStorage"in e},use_prefix:!0}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],leveldown:[function(e,t){(function(r){function n(e){if(!(this instanceof n))return new n(e);if(!e)throw new Error("constructor requires at least a location argument");this.IDBOptions={},this.location=e}t.exports=n;var o=e("idb-wrapper"),i=e("abstract-leveldown").AbstractLevelDOWN,s=e("util"),a=e("./iterator"),u=e("isbuffer"),c=e("xtend"),f=e("typedarray-to-buffer");s.inherits(n,i),n.prototype._open=function(e,t){var r=this,n={storeName:this.location,autoIncrement:!1,keyPath:null,onStoreReady:function(){t&&t(null,r.idb)},onError:function(e){t&&t(e)}};c(n,e),this.IDBOptions=n,this.idb=new o(n)},n.prototype._get=function(e,t,n){this.idb.get(e,function(o){if(void 0===o)return n(new Error("NotFound"));var i=!0;return t.asBuffer===!1&&(i=!1),t.raw&&(i=!1),i&&(o=o instanceof Uint8Array?f(o):new r(String(o))),n(null,o,e)},n)},n.prototype._del=function(e,t,r){this.idb.remove(e,r,r)},n.prototype._put=function(e,t,n,o){t instanceof ArrayBuffer&&(t=f(new Uint8Array(t)));var i=this.convertEncoding(e,t,n);r.isBuffer(i.value)&&(i.value=new Uint8Array(t.toArrayBuffer())),this.idb.put(i.key,i.value,function(){o()},o)},n.prototype.convertEncoding=function(e,t,r){if(r.raw)return{key:e,value:t};if(t){var n=t.toString();"NaN"===n&&(t="NaN")}var o=r.valueEncoding,i={key:e,value:t};return!t||o&&"binary"===o||"object"!=typeof i.value&&(i.value=n),i},n.prototype.iterator=function(e){return"object"!=typeof e&&(e={}),new a(this.idb,e)},n.prototype._batch=function(e,t,r){var n,o,i,s,a=[];if(0===e.length)return setTimeout(r,0);for(n=0;n<e.length;n++){i={},s=e[n],a[n]=i;var u=this.convertEncoding(s.key,s.value,t);s.key=u.key,s.value=u.value;for(o in s)i[o]="type"===o&&"del"==s[o]?"remove":s[o]}return this.idb.batch(a,function(){r()},r)},n.prototype._close=function(e){this.idb.db.close(),e()},n.prototype._approximateSize=function(e,t,r){var n=new Error("Not implemented");if(r)return r(n);throw n},n.prototype._isBuffer=function(e){return r.isBuffer(e)},n.destroy=function(e,t){if("object"==typeof e)var r=e.IDBOptions.storePrefix||"IDBWrapper-",n=e.location;else var r="IDBWrapper-",n=e;var o=indexedDB.deleteDatabase(r+n);o.onsuccess=function(){t()},o.onerror=function(e){t(e)}};n.prototype._checkKeyValue=function(e,t){return null===e||void 0===e?new Error(t+" cannot be `null` or `undefined`"):null===e||void 0===e?new Error(t+" cannot be `null` or `undefined`"):u(e)&&0===e.byteLength?new Error(t+" cannot be an empty ArrayBuffer"):""===String(e)?new Error(t+" cannot be an empty String"):0===e.length?new Error(t+" cannot be an empty Array"):void 0}}).call(this,e("buffer").Buffer)},{"./iterator":45,"abstract-leveldown":48,buffer:17,"idb-wrapper":50,isbuffer:51,"typedarray-to-buffer":53,util:39,xtend:55}]},{},[11]); \ No newline at end of file
diff --git a/dist/pouchdb.memory.js b/dist/pouchdb.memory.js new file mode 100644 index 0000000..63ecd71 --- /dev/null +++ b/dist/pouchdb.memory.js
@@ -0,0 +1,16412 @@ +// PouchDB in-memory plugin 3.2.0 +// Based on MemDOWN: https://github.com/rvagg/memdown +// +// (c) 2012-2014 Dale Harvey and the PouchDB team +// PouchDB may be freely distributed under the Apache license, version 2.0. +// For all details and documentation: +// http://pouchdb.com +require=(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<r.length;o++)s(r[o]);return s})({"./lib/deps/migrate":[function(_dereq_,module,exports){ +(function (process){ +'use strict'; +// LevelAlt doesn't need the pre-2.2.0 LevelDB-specific migrations +exports.toSublevel = function (name, db, callback) { + process.nextTick(function () { + callback(); + }); +}; + +exports.localAndMetaStores = function (db, stores, callback) { + process.nextTick(function () { + callback(); + }); +}; + +}).call(this,_dereq_('_process')) +},{"_process":24}],1:[function(_dereq_,module,exports){ +(function (process,Buffer){ +'use strict'; + +var levelup = _dereq_('levelup'); +var originalLeveldown = _dereq_('leveldown'); +var sublevel = _dereq_('level-sublevel'); +var through = _dereq_('through2').obj; + +var errors = _dereq_('../deps/errors'); +var merge = _dereq_('../merge'); +var utils = _dereq_('../utils'); +var migrate = _dereq_('../deps/migrate'); +var vuvuzela = _dereq_('vuvuzela'); +var Deque = _dereq_("double-ended-queue"); + +var DOC_STORE = 'document-store'; +var BY_SEQ_STORE = 'by-sequence'; +var ATTACHMENT_STORE = 'attach-store'; +var BINARY_STORE = 'attach-binary-store'; +var LOCAL_STORE = 'local-store'; +var META_STORE = 'meta-store'; +var BATCH_SIZE = 50; + +// leveldb barks if we try to open a db multiple times +// so we cache opened connections here for initstore() +var dbStores = new utils.Map(); + +// store the value of update_seq in the by-sequence store the key name will +// never conflict, since the keys in the by-sequence store are integers +var UPDATE_SEQ_KEY = '_local_last_update_seq'; +var DOC_COUNT_KEY = '_local_doc_count'; +var UUID_KEY = '_local_uuid'; + +var MD5_PREFIX = 'md5-'; + +var vuvuEncoding = { + encode: vuvuzela.stringify, + decode: vuvuzela.parse, + buffer: false, + type: 'cheap-json' +}; + +function fetchAttachments(results, stores) { + return utils.Promise.all(results.map(function (row) { + if (row.doc && row.doc._attachments) { + var attNames = Object.keys(row.doc._attachments); + return utils.Promise.all(attNames.map(function (att) { + var attObj = row.doc._attachments[att]; + if ('data' in attObj) { // already fetched + return; + } + return new utils.Promise(function (resolve, reject) { + stores.binaryStore.get(attObj.digest, function (err, buffer) { + var base64 = ''; + if (err && err.name !== 'NotFoundError') { + return reject(err); + } else if (!err) { + base64 = utils.btoa(buffer); + } + row.doc._attachments[att] = utils.extend( + utils.pick(attObj, ['digest', 'content_type']), + {data: base64} + ); + resolve(); + }); + }); + })); + } + })); +} + +function createChangesFilter(opts) { + var baseFilter = utils.filterChange(opts); + var docIds = opts.doc_ids && new utils.Set(opts.doc_ids); + return function filter(change) { + // It's the responsibility of each adapter to actually do + // the doc_ids filtering, since websql/idb can do it + // more efficiently. + if (docIds && !docIds.has(change.id)) { + return false; + } + return baseFilter(change); + }; +} + +function LevelPouch(opts, callback) { + opts = utils.clone(opts); + var api = this; + var instanceId; + var stores = {}; + var db; + var name = opts.name; + if (typeof opts.createIfMissing === 'undefined') { + opts.createIfMissing = true; + } + + var leveldown = opts.db || originalLeveldown; + if (typeof leveldown.destroy !== 'function') { + leveldown.destroy = function (name, cb) { cb(); }; + } + var dbStore; + if (dbStores.has(leveldown.name)) { + dbStore = dbStores.get(leveldown.name); + } else { + dbStore = new utils.Map(); + dbStores.set(leveldown.name, dbStore); + } + if (dbStore.has(name)) { + db = dbStore.get(name); + afterDBCreated(); + } else { + dbStore.set(name, sublevel(levelup(name, opts, function (err) { + if (err) { + dbStore["delete"](name); + return callback(err); + } + db = dbStore.get(name); + db._docCountQueue = { + queue : [], + running : false, + docCount : -1 + }; + db._writeQueue = new Deque(); + if (opts.db || opts.noMigrate) { + afterDBCreated(); + } else { + migrate.toSublevel(name, db, afterDBCreated); + } + }))); + } + + function afterDBCreated() { + stores.docStore = db.sublevel(DOC_STORE, {valueEncoding: vuvuEncoding}); + stores.bySeqStore = db.sublevel(BY_SEQ_STORE, {valueEncoding: 'json'}); + stores.attachmentStore = + db.sublevel(ATTACHMENT_STORE, {valueEncoding: 'json'}); + stores.binaryStore = db.sublevel(BINARY_STORE, {valueEncoding: 'binary'}); + stores.localStore = db.sublevel(LOCAL_STORE, {valueEncoding: 'json'}); + stores.metaStore = db.sublevel(META_STORE, {valueEncoding: 'json'}); + migrate.localAndMetaStores(db, stores, function () { + stores.metaStore.get(UPDATE_SEQ_KEY, function (err, value) { + if (typeof db._updateSeq === 'undefined') { + db._updateSeq = value || 0; + } + stores.metaStore.get(DOC_COUNT_KEY, function (err, value) { + db._docCountQueue.docCount = !err ? value : 0; + countDocs(function (err) { // notify queue that the docCount is ready + if (err) { + api.emit('error', err); + } + stores.metaStore.get(UUID_KEY, function (err, value) { + instanceId = !err ? value : utils.uuid(); + stores.metaStore.put(UUID_KEY, instanceId, function (err, value) { + process.nextTick(function () { + callback(null, api); + }); + }); + }); + }); + }); + }); + }); + } + + function countDocs(callback) { + if (db._docCountQueue.running || !db._docCountQueue.queue.length || + db._docCountQueue.docCount === -1) { + return incrementDocCount(0, callback); // wait for fresh data + } + return db._docCountQueue.docCount; // use cached value + } + + function applyNextDocCountDelta() { + if (db._docCountQueue.running || !db._docCountQueue.queue.length || + db._docCountQueue.docCount === -1) { + return; + } + db._docCountQueue.running = true; + var item = db._docCountQueue.queue.shift(); + if (db.isClosed()) { + return item.callback(new Error('database is closed')); + } + stores.metaStore.get(DOC_COUNT_KEY, function (err, docCount) { + docCount = !err ? docCount : 0; + + function complete(err) { + db._docCountQueue.docCount = docCount; + item.callback(err, docCount); + db._docCountQueue.running = false; + applyNextDocCountDelta(); + } + + if (item.delta === 0) { + complete(); + } else { + stores.metaStore.put(DOC_COUNT_KEY, docCount + item.delta, complete); + } + }); + } + + function incrementDocCount(delta, callback) { + db._docCountQueue.queue.push({delta : delta, callback : callback}); + applyNextDocCountDelta(); + } + + api.type = function () { + return 'leveldb'; + }; + + api._id = function (callback) { + callback(null, instanceId); + }; + + api._info = function (callback) { + countDocs(function (err, docCount) { + if (err) { + return callback(err); + } + stores.metaStore.get(UPDATE_SEQ_KEY, function (err, otherUpdateSeq) { + if (err) { + otherUpdateSeq = db._updateSeq; + } + + return callback(null, { + doc_count: docCount, + update_seq: otherUpdateSeq + }); + }); + }); + }; + + // all read/write operations to the database are done in a queue, + // similar to how websql/idb works. this avoids problems such + // as e.g. compaction needing to have a lock on the database while + // it updates stuff. in the future we can revisit this. + function writeLock(fun) { + return utils.getArguments(function (args) { + + var callback = args[args.length - 1]; + args[args.length - 1] = utils.getArguments(function (cbArgs) { + callback.apply(null, cbArgs); + process.nextTick(function () { + db._writeQueue.shift(); + if (db._writeQueue.length) { + db._writeQueue.peekFront()(); + } + }); + }); + + db._writeQueue.push(function () { + fun.apply(null, args); + }); + + if (db._writeQueue.length === 1) { + db._writeQueue.peekFront()(); + } + }); + } + + function formatSeq(n) { + return ('0000000000000000' + n).slice(-16); + } + + function parseSeq(s) { + return parseInt(s, 10); + } + + function makeDoc(rawDoc, callback) { + var doc = rawDoc.data; + doc._id = rawDoc.metadata.id; + if ('_rev' in doc) { + if (doc._rev !== rawDoc.metadata.rev) { + return callback(new Error('wrong doc returned')); + } + } else { + // we didn't always store rev + doc._rev = rawDoc.metadata.rev; + } + callback(null, {doc: doc, metadata: rawDoc.metadata}); + } + + api._get = function (id, opts, callback) { + opts = utils.clone(opts); + var docChanged = []; + + function didDocChange(doc) { + docChanged.push(doc); + } + + db.on('pouchdb-id-' + id, didDocChange); + + stores.docStore.get(id, function (err, metadata) { + db.removeListener('pouchdb-id-' + id, didDocChange); + + if (err || !metadata) { + return callback(errors.MISSING_DOC); + } + + if (utils.isDeleted(metadata) && !opts.rev) { + return callback(errors.error(errors.MISSING_DOC, "deleted")); + } + + var updated; + + function ifUpdate(doc) { + updated = doc; + } + + var rev = merge.winningRev(metadata); + rev = opts.rev ? opts.rev : rev; + + var seq = metadata.rev_map[rev]; + + var anyChanged = docChanged.filter(function (doc) { + return doc.metadata.seq === seq; + }); + + if (anyChanged.length) { + return makeDoc(anyChanged.pop(), callback); + } + + db.on('pouchdb-' + seq, ifUpdate); + + stores.bySeqStore.get(formatSeq(seq), function (err, doc) { + db.removeListener('pouchdb-' + seq, ifUpdate); + if (updated) { + return makeDoc(updated, callback); + + } + + if (!doc) { + return callback(errors.MISSING_DOC); + } + if ('_id' in doc && doc._id !== metadata.id) { + // this failing implies something very wrong + return callback(new Error('wrong doc returned')); + } + doc._id = metadata.id; + if ('_rev' in doc) { + if (doc._rev !== rev) { + // this failing implies something very wrong + return callback(new Error('wrong doc returned')); + } + } else { + // we didn't always store this + doc._rev = rev; + } + return callback(null, {doc: doc, metadata: metadata}); + }); + }); + }; + + // not technically part of the spec, but if putAttachment has its own + // method... + api._getAttachment = function (attachment, opts, callback) { + var digest = attachment.digest; + + stores.binaryStore.get(digest, function (err, attach) { + var data; + + if (err && err.name === 'NotFoundError') { + // Empty attachment + data = opts.encode ? '' : process.browser ? + utils.createBlob([''], {type: attachment.content_type}) : + new Buffer(''); + return callback(null, data); + } + + if (err) { + return callback(err); + } + + if (process.browser) { + if (opts.encode) { + data = utils.btoa(attach); + } else { + data = utils.createBlob([utils.fixBinary(attach)], + {type: attachment.content_type}); + } + } else { + data = opts.encode ? utils.btoa(attach) : attach; + } + callback(null, data); + }); + }; + + api._bulkDocs = writeLock(function (req, opts, callback) { + var newEdits = opts.new_edits; + var results = new Array(req.docs.length); + var lock = new utils.Set(); + + // parse the docs and give each a sequence number + var userDocs = req.docs; + var info = userDocs.map(function (doc, i) { + if (doc._id && utils.isLocalId(doc._id)) { + return doc; + } + var newDoc = utils.parseDoc(doc, newEdits); + + if (newDoc.metadata && !newDoc.metadata.rev_map) { + newDoc.metadata.rev_map = {}; + } + + return newDoc; + }); + var current = 0; + var infoErrors = info.filter(function (doc) { + return doc.error; + }); + + if (infoErrors.length) { + return callback(infoErrors[0]); + } + + // verify any stub attachments as a precondition test + + function verifyAttachment(digest, callback) { + stores.attachmentStore.get(digest, function (levelErr) { + if (levelErr) { + var err = new Error('unknown stub attachment with digest ' + digest); + err.status = 412; + callback(err); + } else { + callback(); + } + }); + } + + function verifyAttachments(finish) { + var digests = []; + userDocs.forEach(function (doc) { + if (doc && doc._attachments) { + Object.keys(doc._attachments).forEach(function (filename) { + var att = doc._attachments[filename]; + if (att.stub) { + digests.push(att.digest); + } + }); + } + }); + if (!digests.length) { + return finish(); + } + var numDone = 0; + var err; + + function checkDone() { + if (++numDone === digests.length) { + finish(err); + } + } + digests.forEach(function (digest) { + verifyAttachment(digest, function (attErr) { + if (attErr && !err) { + err = attErr; + } + checkDone(); + }); + }); + } + + var inProgress = 0; + function processDocs() { + var index = current; + if (inProgress > BATCH_SIZE) { + return; + } + if (index >= info.length) { + if (inProgress === 0) { + return complete(); + } else { + return; + } + } + var currentDoc = info[index]; + current++; + inProgress++; + if (currentDoc._id && utils.isLocalId(currentDoc._id)) { + api[currentDoc._deleted ? '_removeLocalNoLock' : '_putLocalNoLock']( + currentDoc, function (err, resp) { + if (err) { + results[index] = err; + } else { + results[index] = {}; + } + inProgress--; + processDocs(); + }); + return; + } + + if (lock.has(currentDoc.metadata.id)) { + results[index] = errors.REV_CONFLICT; + inProgress--; + return processDocs(); + } + lock.add(currentDoc.metadata.id); + + stores.docStore.get(currentDoc.metadata.id, function (err, oldDoc) { + if (err) { + if (err.name === 'NotFoundError') { + insertDoc(currentDoc, index, function () { + lock["delete"](currentDoc.metadata.id); + inProgress--; + processDocs(); + }); + } else { + err.error = true; + results[index] = err; + lock["delete"](currentDoc.metadata.id); + inProgress--; + processDocs(); + } + } else { + updateDoc(oldDoc, currentDoc, index, function () { + lock["delete"](currentDoc.metadata.id); + inProgress--; + processDocs(); + }); + } + }); + + if (newEdits) { + processDocs(); + } + } + + function insertDoc(doc, index, callback) { + // Can't insert new deleted documents + if ('was_delete' in opts && utils.isDeleted(doc.metadata)) { + results[index] = errors.MISSING_DOC; + return callback(); + } + writeDoc(doc, index, function (err) { + if (err) { + return callback(err); + } + if (utils.isDeleted(doc.metadata)) { + return callback(); + } + incrementDocCount(1, callback); + }); + } + + function updateDoc(oldDoc, docInfo, index, callback) { + + if (utils.revExists(oldDoc, docInfo.metadata.rev)) { + results[index] = docInfo; + callback(); + return; + } + + var previouslyDeleted = utils.isDeleted(oldDoc); + var deleted = utils.isDeleted(docInfo.metadata); + var isRoot = /^1-/.test(docInfo.metadata.rev); + + if (previouslyDeleted && !deleted && newEdits && isRoot) { + var newDoc = docInfo.data; + newDoc._rev = oldDoc.rev; + newDoc._id = docInfo.metadata.id; + docInfo = utils.parseDoc(newDoc, newEdits); + } + + var merged = + merge.merge(oldDoc.rev_tree, docInfo.metadata.rev_tree[0], 1000); + + var inConflict = newEdits && ((previouslyDeleted && deleted) || + (!previouslyDeleted && newEdits && merged.conflicts !== 'new_leaf') || + (previouslyDeleted && !deleted && merged.conflicts === 'new_branch')); + + if (inConflict) { + results[index] = errors.REV_CONFLICT; + return callback(); + } + var newRev = docInfo.metadata.rev; + docInfo.metadata.rev_tree = merged.tree; + docInfo.metadata.rev_map = oldDoc.rev_map; + + var delta = 0; + if (newEdits || merge.winningRev(docInfo.metadata) === newRev) { + // if newEdits==false and we're pushing existing revisions, + // then the only thing that matters is whether this revision + // is the winning one, and thus replaces an old one + delta = (previouslyDeleted === deleted) ? 0 : + previouslyDeleted < deleted ? -1 : 1; + } + + incrementDocCount(delta, function (err) { + if (err) { + return callback(err); + } + writeDoc(docInfo, index, callback); + }); + + } + + function writeDoc(doc, index, callback2) { + var err = null; + var recv = 0; + + doc.data._id = doc.metadata.id; + doc.data._rev = doc.metadata.rev; + + if (utils.isDeleted(doc.metadata)) { + doc.data._deleted = true; + } + + var attachments = doc.data._attachments ? + Object.keys(doc.data._attachments) : + []; + + function collectResults(attachmentErr) { + if (!err) { + if (attachmentErr) { + err = attachmentErr; + callback2(err); + } else if (recv === attachments.length) { + finish(); + } + } + } + + function attachmentSaved(err) { + recv++; + collectResults(err); + } + + function onMD5Load(doc, key, data, attachmentSaved) { + return function (result) { + saveAttachment(doc, MD5_PREFIX + result, key, data, attachmentSaved); + }; + } + + function onLoadEnd(doc, key, attachmentSaved) { + return function (data) { + utils.MD5(data).then( + onMD5Load(doc, key, data, attachmentSaved) + ); + }; + } + + for (var i = 0; i < attachments.length; i++) { + var key = attachments[i]; + var att = doc.data._attachments[key]; + + if (att.stub) { + // still need to update the refs mapping + var id = doc.data._id; + var rev = doc.data._rev; + saveAttachmentRefs(id, rev, att.digest, attachmentSaved); + continue; + } + var data; + if (typeof att.data === 'string') { + try { + data = utils.atob(att.data); + } catch (e) { + callback(utils.extend({}, errors.BAD_ARG, + {reason: "Attachments need to be base64 encoded"})); + return; + } + } else if (!process.browser) { + data = att.data; + } else { // browser + utils.readAsBinaryString(att.data, + onLoadEnd(doc, key, attachmentSaved)); + continue; + } + utils.MD5(data).then( + onMD5Load(doc, key, data, attachmentSaved) + ); + } + + function finish() { + var seq = doc.metadata.rev_map[doc.metadata.rev]; + if (!seq) { + // check that there aren't any existing revisions with the same + // reivision id, else we shouldn't increment updateSeq + seq = ++db._updateSeq; + } + doc.metadata.rev_map[doc.metadata.rev] = doc.metadata.seq = seq; + var seqKey = formatSeq(seq); + db.emit('pouchdb-id-' + doc.metadata.id, doc); + db.emit('pouchdb-' + seqKey, doc); + db.batch([{ + key: seqKey, + value: doc.data, + prefix: stores.bySeqStore, + type: 'put', + valueEncoding: 'json' + }, { + key: doc.metadata.id, + value: doc.metadata, + prefix: stores.docStore, + type: 'put', + valueEncoding: vuvuEncoding + }], function (err) { + if (!err) { + db.emit('pouchdb-id-' + doc.metadata.id, doc); + db.emit('pouchdb-' + seqKey, doc); + } + return stores.metaStore.put(UPDATE_SEQ_KEY, db._updateSeq, + function (err) { + if (err) { + results[index] = err; + } else { + results[index] = doc; + } + return callback2(); + }); + }); + } + + if (!attachments.length) { + finish(); + } + } + + // attachments are queued per-digest, otherwise the refs could be + // overwritten by concurrent writes in the same bulkDocs session + var attachmentQueues = {}; + + function saveAttachmentRefs(id, rev, digest, callback) { + + function fetchAtt() { + return new utils.Promise(function (resolve, reject) { + stores.attachmentStore.get(digest, function (err, oldAtt) { + if (err && err.name !== 'NotFoundError') { + return reject(err); + } + resolve(oldAtt); + }); + }); + } + + function saveAtt(oldAtt) { + var ref = [id, rev].join('@'); + var newAtt = {}; + + if (oldAtt) { + if (oldAtt.refs) { + // only update references if this attachment already has them + // since we cannot migrate old style attachments here without + // doing a full db scan for references + newAtt.refs = oldAtt.refs; + newAtt.refs[ref] = true; + } + } else { + newAtt.refs = {}; + newAtt.refs[ref] = true; + } + + return new utils.Promise(function (resolve, reject) { + stores.attachmentStore.put(digest, newAtt, function (err) { + if (err) { + return reject(err); + } + resolve(!oldAtt); + }); + }); + } + + // put attachments in a per-digest queue, to avoid two docs with the same + // attachment overwriting each other + var queue = attachmentQueues[digest] || utils.Promise.resolve(); + attachmentQueues[digest] = queue.then(function () { + return fetchAtt().then(saveAtt).then(function (isNewAttachment) { + callback(null, isNewAttachment); + }, callback); + }); + } + + function saveAttachment(docInfo, digest, key, data, callback) { + var att = docInfo.data._attachments[key]; + delete att.data; + att.digest = digest; + att.length = data.length; + var id = docInfo.metadata.id; + var rev = docInfo.metadata.rev; + + saveAttachmentRefs(id, rev, digest, function (err, isNewAttachment) { + if (err) { + return callback(err); + } + // do not try to store empty attachments + if (data.length === 0) { + return callback(err); + } + if (!isNewAttachment) { + // small optimization - don't bother writing it again + return callback(err); + } + // doing this in batch causes a test to fail, wtf? + stores.binaryStore.put(digest, data, function (err) { + callback(err); + }); + }); + } + + function complete() { + var aresults = results.map(function (result) { + if (!Object.keys(result).length) { + return { + ok: true + }; + } + if (result.error) { + return result; + } + + var metadata = result.metadata; + var rev = merge.winningRev(metadata); + + return { + ok: true, + id: metadata.id, + rev: rev + }; + }); + LevelPouch.Changes.notify(name); + process.nextTick(function () { + callback(null, aresults); + }); + } + + verifyAttachments(function (err) { + if (err) { + return callback(err); + } + processDocs(); + }); + }); + api._allDocs = function (opts, callback) { + opts = utils.clone(opts); + countDocs(function (err, docCount) { + if (err) { + return callback(err); + } + var readstreamOpts = {}; + var skip = opts.skip || 0; + if (opts.startkey) { + readstreamOpts.start = opts.startkey; + } + if (opts.endkey) { + readstreamOpts.end = opts.endkey; + } + if (opts.key) { + readstreamOpts.start = readstreamOpts.end = opts.key; + } + if (opts.descending) { + readstreamOpts.reverse = true; + // switch start and ends + var tmp = readstreamOpts.start; + readstreamOpts.start = readstreamOpts.end; + readstreamOpts.end = tmp; + } + var limit; + if (typeof opts.limit === 'number') { + limit = opts.limit; + } else { + limit = -1; + } + if (limit === 0 || + ('start' in readstreamOpts && 'end' in readstreamOpts && + readstreamOpts.start > readstreamOpts.end)) { + // should return 0 results when start is greater than end. + // normally level would "fix" this for us by reversing the order, + // so short-circuit instead + return callback(null, { + total_rows: docCount, + offset: opts.skip, + rows: [] + }); + } + var results = []; + var docstream = stores.docStore.readStream(readstreamOpts); + + var throughStream = through(function (entry, _, next) { + if (!utils.isDeleted(entry.value)) { + if (skip-- > 0) { + next(); + return; + } else if (limit-- === 0) { + docstream.unpipe(); + docstream.destroy(); + next(); + return; + } + } else if (opts.deleted !== 'ok') { + next(); + return; + } + function allDocsInner(metadata, data) { + var doc = { + id: metadata.id, + key: metadata.id, + value: { + rev: merge.winningRev(metadata) + } + }; + if (opts.include_docs) { + doc.doc = data; + doc.doc._rev = doc.value.rev; + if (opts.conflicts) { + doc.doc._conflicts = merge.collectConflicts(metadata); + } + for (var att in doc.doc._attachments) { + if (doc.doc._attachments.hasOwnProperty(att)) { + doc.doc._attachments[att].stub = true; + } + } + } + if (opts.inclusive_end === false && metadata.id === opts.endkey) { + return next(); + } else if (utils.isDeleted(metadata)) { + if (opts.deleted === 'ok') { + doc.value.deleted = true; + doc.doc = null; + } else { + return next(); + } + } + results.push(doc); + next(); + } + var metadata = entry.value; + if (opts.include_docs) { + var seq = metadata.rev_map[merge.winningRev(metadata)]; + stores.bySeqStore.get(formatSeq(seq), function (err, data) { + allDocsInner(metadata, data); + }); + } + else { + allDocsInner(metadata); + } + }, function (next) { + utils.Promise.resolve().then(function () { + return opts.attachments && fetchAttachments(results, stores); + }).then(function () { + callback(null, { + total_rows: docCount, + offset: opts.skip, + rows: results + }); + }, callback); + next(); + }).on('unpipe', function () { + throughStream.end(); + }); + + docstream.on('error', callback); + + docstream.pipe(throughStream); + }); + }; + + api._changes = function (opts) { + opts = utils.clone(opts); + + if (opts.continuous) { + var id = name + ':' + utils.uuid(); + LevelPouch.Changes.addListener(name, id, api, opts); + LevelPouch.Changes.notify(name); + return { + cancel: function () { + LevelPouch.Changes.removeListener(name, id); + } + }; + } + + var descending = opts.descending; + var results = []; + var last_seq = 0; + var called = 0; + var streamOpts = { + reverse: descending + }; + var limit; + if ('limit' in opts && opts.limit > 0) { + limit = opts.limit; + } + if (!streamOpts.reverse) { + streamOpts.start = formatSeq(opts.since ? opts.since + 1 : 0); + } + + var filter = createChangesFilter(opts); + + var returnDocs; + if ('returnDocs' in opts) { + returnDocs = opts.returnDocs; + } else { + returnDocs = true; + } + + function complete() { + opts.done = true; + if (returnDocs && opts.limit) { + if (opts.limit < results.length) { + results.length = opts.limit; + } + } + changeStream.unpipe(throughStream); + changeStream.destroy(); + if (!opts.continuous && !opts.cancelled) { + utils.Promise.resolve().then(function () { + if (opts.include_docs && opts.attachments) { + return fetchAttachments(results, stores); + } + }).then(function () { + opts.complete(null, {results: results, last_seq: last_seq}); + }); + } + } + var changeStream = stores.bySeqStore.readStream(streamOpts); + var throughStream = through(function (data, _, next) { + if (limit && called >= limit) { + complete(); + return next(); + } + if (opts.cancelled || opts.done) { + return next(); + } + + stores.docStore.get(data.value._id, function (err, metadata) { + if (opts.cancelled || opts.done || db.isClosed() || + utils.isLocalId(metadata.id)) { + return next(); + } + var doc = data.value; + doc._rev = merge.winningRev(metadata); + var change = opts.processChange(doc, metadata, opts); + change.seq = metadata.seq; + + if (last_seq < metadata.seq) { + last_seq = metadata.seq; + } + + // Ensure duplicated dont overwrite winning rev + if (parseSeq(data.key) === metadata.rev_map[change.doc._rev] && + filter(change)) { + called++; + + if (opts.attachments && opts.include_docs) { + // fetch attachment immediately for the benefit + // of live listeners + fetchAttachments([change], stores).then(function () { + opts.onChange(change); + }); + } else { + opts.onChange(change); + } + + if (returnDocs) { + results.push(change); + } + } + next(); + }); + }, function (next) { + if (opts.cancelled) { + return next(); + } + if (returnDocs && opts.limit) { + if (opts.limit < results.length) { + results.length = opts.limit; + } + } + + next(); + }).on('unpipe', function () { + throughStream.end(); + complete(); + }); + changeStream.pipe(throughStream); + return { + cancel: function () { + opts.cancelled = true; + complete(); + } + }; + }; + + api._close = function (callback) { + if (db.isClosed()) { + return callback(errors.NOT_OPEN); + } + db.close(function (err) { + if (err) { + callback(err); + } else { + dbStore["delete"](name); + callback(); + } + }); + }; + + api._getRevisionTree = function (docId, callback) { + stores.docStore.get(docId, function (err, metadata) { + if (err) { + callback(errors.MISSING_DOC); + } else { + callback(null, metadata.rev_tree); + } + }); + }; + + api._doCompaction = writeLock(function (docId, revs, callback) { + if (!revs.length) { + return callback(); + } + stores.docStore.get(docId, function (err, metadata) { + if (err) { + return callback(err); + } + var seqs = metadata.rev_map; // map from rev to seq + merge.traverseRevTree(metadata.rev_tree, function (isLeaf, pos, + revHash, ctx, opts) { + var rev = pos + '-' + revHash; + if (revs.indexOf(rev) !== -1) { + opts.status = 'missing'; + } + }); + var batch = []; + batch.push({ + key: metadata.id, + value: metadata, + type: 'put', + valueEncoding: vuvuEncoding, + prefix: stores.docStore + }); + + var digestMap = {}; + var numDone = 0; + var overallErr; + function checkDone(err) { + if (err) { + overallErr = err; + } + if (++numDone === revs.length) { // done + if (overallErr) { + return callback(err); + } + deleteOrphanedAttachments(); + } + } + + function finish(err) { + if (err) { + return callback(err); + } + db.batch(batch, callback); + } + + function deleteOrphanedAttachments() { + var possiblyOrphanedAttachments = Object.keys(digestMap); + if (!possiblyOrphanedAttachments.length) { + return finish(); + } + var numDone = 0; + var overallErr; + function checkDone(err) { + if (err) { + overallErr = err; + } + if (++numDone === possiblyOrphanedAttachments.length) { + finish(overallErr); + } + } + var refsToDelete = new utils.Map(); + revs.forEach(function (rev) { + refsToDelete.set(docId + '@' + rev, true); + }); + possiblyOrphanedAttachments.forEach(function (digest) { + stores.attachmentStore.get(digest, function (err, attData) { + if (err) { + if (err.name === 'NotFoundError') { + return checkDone(); + } else { + return checkDone(err); + } + } + var refs = Object.keys(attData.refs || {}).filter(function (ref) { + return !refsToDelete.has(ref); + }); + var newRefs = {}; + refs.forEach(function (ref) { + newRefs[ref] = true; + }); + if (refs.length) { // not orphaned + batch.push({ + key: digest, + type: 'put', + valueEncoding: 'json', + value: {refs: newRefs}, + prefix: stores.attachmentStore + }); + } else { // orphaned, can safely delete + batch = batch.concat([{ + key: digest, + type: 'del', + prefix: stores.attachmentStore + }, { + key: digest, + type: 'del', + prefix: stores.binaryStore + }]); + } + checkDone(); + }); + }); + } + + revs.forEach(function (rev) { + var seq = seqs[rev]; + if (!seq) { + return; + } + batch.push({ + key: formatSeq(seq), + type: 'del', + prefix: stores.bySeqStore + }); + stores.bySeqStore.get(formatSeq(seq), function (err, doc) { + if (err) { + if (err.name === 'NotFoundError') { + return checkDone(); + } else { + return checkDone(err); + } + } + var atts = Object.keys(doc._attachments || {}); + atts.forEach(function (attName) { + var digest = doc._attachments[attName].digest; + digestMap[digest] = true; + }); + checkDone(); + }); + }); + }); + }); + + api._getLocal = function (id, callback) { + stores.localStore.get(id, function (err, doc) { + if (err) { + callback(errors.MISSING_DOC); + } else { + callback(null, doc); + } + }); + }; + + api._putLocal = writeLock(function (doc, callback) { + api._putLocalNoLock(doc, callback); + }); + + // the NoLock version is for use by bulkDocs + api._putLocalNoLock = function (doc, callback) { + delete doc._revisions; // ignore this, trust the rev + var oldRev = doc._rev; + var id = doc._id; + stores.localStore.get(id, function (err, resp) { + if (err) { + if (oldRev) { + return callback(errors.REV_CONFLICT); + } + } + if (resp && resp._rev !== oldRev) { + return callback(errors.REV_CONFLICT); + } + if (!oldRev) { + doc._rev = '0-1'; + } else { + doc._rev = '0-' + (parseInt(oldRev.split('-')[1], 10) + 1); + } + stores.localStore.put(id, doc, function (err) { + if (err) { + return callback(err); + } + var ret = {ok: true, id: doc._id, rev: doc._rev}; + callback(null, ret); + }); + }); + }; + + api._removeLocal = writeLock(function (doc, callback) { + api._removeLocalNoLock(doc, callback); + }); + + // the NoLock version is for use by bulkDocs + api._removeLocalNoLock = function (doc, callback) { + stores.localStore.get(doc._id, function (err, resp) { + if (err) { + return callback(err); + } + if (resp._rev !== doc._rev) { + return callback(errors.REV_CONFLICT); + } + stores.localStore.del(doc._id, function (err) { + if (err) { + return callback(err); + } + var ret = {ok: true, id: doc._id, rev: '0-0'}; + callback(null, ret); + }); + }); + }; +} + +LevelPouch.valid = function () { + return process && !process.browser; +}; + +// close and delete open leveldb stores +LevelPouch.destroy = utils.toPromise(function (name, opts, callback) { + opts = utils.clone(opts); + + var leveldown = opts.db || originalLeveldown; + function callDestroy(name, cb) { + if (typeof leveldown.destroy === 'function') { + leveldown.destroy(name, cb); + } else { + process.nextTick(callback); + } + } + + var dbStore; + if (dbStores.has(leveldown.name)) { + dbStore = dbStores.get(leveldown.name); + } else { + return callDestroy(name, callback); + } + + if (dbStore.has(name)) { + + LevelPouch.Changes.removeAllListeners(name); + + dbStore.get(name).close(function () { + dbStore["delete"](name); + callDestroy(name, callback); + }); + } else { + callDestroy(name, callback); + } +}); + +LevelPouch.use_prefix = false; + +LevelPouch.Changes = new utils.Changes(); + +module.exports = LevelPouch; + +}).call(this,_dereq_('_process'),_dereq_("buffer").Buffer) +},{"../deps/errors":5,"../deps/migrate":7,"../merge":10,"../utils":13,"_process":24,"buffer":17,"double-ended-queue":43,"level-sublevel":61,"leveldown":"leveldown","levelup":75,"through2":132,"vuvuzela":133}],2:[function(_dereq_,module,exports){ +"use strict"; + +var createBlob = _dereq_('./blob.js'); +var errors = _dereq_('./errors'); +var utils = _dereq_("../utils"); +var hasUpload; + +function ajax(options, adapterCallback) { + + var requestCompleted = false; + var callback = utils.getArguments(function (args) { + if (requestCompleted) { + return; + } + adapterCallback.apply(this, args); + requestCompleted = true; + }); + + if (typeof options === "function") { + callback = options; + options = {}; + } + + options = utils.clone(options); + + var defaultOptions = { + method : "GET", + headers: {}, + json: true, + processData: true, + timeout: 10000, + cache: false + }; + + options = utils.extend(true, defaultOptions, options); + + // cache-buster, specifically designed to work around IE's aggressive caching + // see http://www.dashbay.com/2011/05/internet-explorer-caches-ajax/ + if (options.method === 'GET' && !options.cache) { + var hasArgs = options.url.indexOf('?') !== -1; + options.url += (hasArgs ? '&' : '?') + '_nonce=' + utils.uuid(16); + } + + function onSuccess(obj, resp, cb) { + if (!options.binary && !options.json && options.processData && + typeof obj !== 'string') { + obj = JSON.stringify(obj); + } else if (!options.binary && options.json && typeof obj === 'string') { + try { + obj = JSON.parse(obj); + } catch (e) { + // Probably a malformed JSON from server + return cb(e); + } + } + if (Array.isArray(obj)) { + obj = obj.map(function (v) { + var obj; + if (v.ok) { + return v; + } else if (v.error && v.error === 'conflict') { + obj = errors.REV_CONFLICT; + obj.id = v.id; + return obj; + } else if (v.error && v.error === 'forbidden') { + obj = errors.FORBIDDEN; + obj.id = v.id; + obj.reason = v.reason; + return obj; + } else if (v.missing) { + obj = errors.MISSING_DOC; + obj.missing = v.missing; + return obj; + } else { + return v; + } + }); + } + cb(null, obj, resp); + } + + function onError(err, cb) { + var errParsed, errObj, errType, key; + try { + errParsed = JSON.parse(err.responseText); + //would prefer not to have a try/catch clause + for (key in errors) { + if (errors.hasOwnProperty(key) && + errors[key].name === errParsed.error) { + errType = errors[key]; + break; + } + } + if (!errType) { + errType = errors.UNKNOWN_ERROR; + if (err.status) { + errType.status = err.status; + } + if (err.statusText) { + err.name = err.statusText; + } + } + errObj = errors.error(errType, errParsed.reason); + } catch (e) { + for (var key in errors) { + if (errors.hasOwnProperty(key) && errors[key].status === err.status) { + errType = errors[key]; + break; + } + } + if (!errType) { + errType = errors.UNKNOWN_ERROR; + if (err.status) { + errType.status = err.status; + } + if (err.statusText) { + err.name = err.statusText; + } + } + errObj = errors.error(errType); + } + if (err.withCredentials && err.status === 0) { + // apparently this is what we get when the method + // is reported as not allowed by CORS. so fudge it + errObj.status = 405; + errObj.statusText = "Method Not Allowed"; + } + cb(errObj); + } + + var timer; + var xhr; + if (options.xhr) { + xhr = new options.xhr(); + } else { + xhr = new XMLHttpRequest(); + } + xhr.open(options.method, options.url); + xhr.withCredentials = true; + + if (options.json) { + options.headers.Accept = 'application/json'; + options.headers['Content-Type'] = options.headers['Content-Type'] || + 'application/json'; + if (options.body && + options.processData && + typeof options.body !== "string") { + options.body = JSON.stringify(options.body); + } + } + + if (options.binary) { + xhr.responseType = 'arraybuffer'; + } + + var createCookie = function (name, value, days) { + var expires = ""; + if (days) { + var date = new Date(); + date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); + expires = "; expires=" + date.toGMTString(); + } + document.cookie = name + "=" + value + expires + "; path=/"; + }; + + for (var key in options.headers) { + if (key === 'Cookie') { + var cookie = options.headers[key].split('='); + createCookie(cookie[0], cookie[1], 10); + } else { + xhr.setRequestHeader(key, options.headers[key]); + } + } + + if (!("body" in options)) { + options.body = null; + } + + var abortReq = function () { + if (requestCompleted) { + return; + } + xhr.abort(); + onError(xhr, callback); + }; + + xhr.onreadystatechange = function () { + if (xhr.readyState !== 4 || requestCompleted) { + return; + } + clearTimeout(timer); + if (xhr.status >= 200 && xhr.status < 300) { + var data; + if (options.binary) { + data = createBlob([xhr.response || ''], { + type: xhr.getResponseHeader('Content-Type') + }); + } else { + data = xhr.responseText; + } + onSuccess(data, xhr, callback); + } else { + onError(xhr, callback); + } + }; + + if (options.timeout > 0) { + timer = setTimeout(abortReq, options.timeout); + xhr.onprogress = function () { + clearTimeout(timer); + timer = setTimeout(abortReq, options.timeout); + }; + if (typeof hasUpload === 'undefined') { + // IE throws an error if you try to access it directly + hasUpload = Object.keys(xhr).indexOf('upload') !== -1; + } + if (hasUpload) { // does not exist in ie9 + xhr.upload.onprogress = xhr.onprogress; + } + } + if (options.body && (options.body instanceof Blob)) { + utils.readAsBinaryString(options.body, function (binary) { + xhr.send(utils.fixBinary(binary)); + }); + } else { + xhr.send(options.body); + } + return {abort: abortReq}; +} + +module.exports = ajax; + +},{"../utils":13,"./blob.js":3,"./errors":5}],3:[function(_dereq_,module,exports){ +(function (global){ +"use strict"; + +//Abstracts constructing a Blob object, so it also works in older +//browsers that don't support the native Blob constructor. (i.e. +//old QtWebKit versions, at least). +function createBlob(parts, properties) { + parts = parts || []; + properties = properties || {}; + try { + return new Blob(parts, properties); + } catch (e) { + if (e.name !== "TypeError") { + throw e; + } + var BlobBuilder = global.BlobBuilder || + global.MSBlobBuilder || + global.MozBlobBuilder || + global.WebKitBlobBuilder; + var builder = new BlobBuilder(); + for (var i = 0; i < parts.length; i += 1) { + builder.append(parts[i]); + } + return builder.getBlob(properties.type); + } +} + +module.exports = createBlob; + + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],4:[function(_dereq_,module,exports){ +'use strict'; +exports.Map = LazyMap; // TODO: use ES6 map +exports.Set = LazySet; // TODO: use ES6 set +// based on https://github.com/montagejs/collections +function LazyMap() { + this.store = {}; +} +LazyMap.prototype.mangle = function (key) { + if (typeof key !== "string") { + throw new TypeError("key must be a string but Got " + key); + } + return '$' + key; +}; +LazyMap.prototype.unmangle = function (key) { + return key.substring(1); +}; +LazyMap.prototype.get = function (key) { + var mangled = this.mangle(key); + if (mangled in this.store) { + return this.store[mangled]; + } else { + return void 0; + } +}; +LazyMap.prototype.set = function (key, value) { + var mangled = this.mangle(key); + this.store[mangled] = value; + return true; +}; +LazyMap.prototype.has = function (key) { + var mangled = this.mangle(key); + return mangled in this.store; +}; +LazyMap.prototype["delete"] = function (key) { + var mangled = this.mangle(key); + if (mangled in this.store) { + delete this.store[mangled]; + return true; + } + return false; +}; +LazyMap.prototype.forEach = function (cb) { + var self = this; + var keys = Object.keys(self.store); + keys.forEach(function (key) { + var value = self.store[key]; + key = self.unmangle(key); + cb(value, key); + }); +}; + +function LazySet(array) { + this.store = new LazyMap(); + + // init with an array + if (array && Array.isArray(array)) { + for (var i = 0, len = array.length; i < len; i++) { + this.add(array[i]); + } + } +} +LazySet.prototype.add = function (key) { + return this.store.set(key, true); +}; +LazySet.prototype.has = function (key) { + return this.store.has(key); +}; +LazySet.prototype["delete"] = function (key) { + return this.store["delete"](key); +}; +},{}],5:[function(_dereq_,module,exports){ +"use strict"; + +function PouchError(opts) { + this.status = opts.status; + this.name = opts.error; + this.message = opts.reason; + this.error = true; +} + +PouchError.prototype__proto__ = Error.prototype; + +PouchError.prototype.toString = function () { + return JSON.stringify({ + status: this.status, + name: this.name, + message: this.message + }); +}; + +exports.UNAUTHORIZED = new PouchError({ + status: 401, + error: 'unauthorized', + reason: "Name or password is incorrect." +}); +exports.MISSING_BULK_DOCS = new PouchError({ + status: 400, + error: 'bad_request', + reason: "Missing JSON list of 'docs'" +}); +exports.MISSING_DOC = new PouchError({ + status: 404, + error: 'not_found', + reason: 'missing' +}); +exports.REV_CONFLICT = new PouchError({ + status: 409, + error: 'conflict', + reason: 'Document update conflict' +}); +exports.INVALID_ID = new PouchError({ + status: 400, + error: 'invalid_id', + reason: '_id field must contain a string' +}); +exports.MISSING_ID = new PouchError({ + status: 412, + error: 'missing_id', + reason: '_id is required for puts' +}); +exports.RESERVED_ID = new PouchError({ + status: 400, + error: 'bad_request', + reason: 'Only reserved document ids may start with underscore.' +}); +exports.NOT_OPEN = new PouchError({ + status: 412, + error: 'precondition_failed', + reason: 'Database not open' +}); +exports.UNKNOWN_ERROR = new PouchError({ + status: 500, + error: 'unknown_error', + reason: 'Database encountered an unknown error' +}); +exports.BAD_ARG = new PouchError({ + status: 500, + error: 'badarg', + reason: 'Some query argument is invalid' +}); +exports.INVALID_REQUEST = new PouchError({ + status: 400, + error: 'invalid_request', + reason: 'Request was invalid' +}); +exports.QUERY_PARSE_ERROR = new PouchError({ + status: 400, + error: 'query_parse_error', + reason: 'Some query parameter is invalid' +}); +exports.DOC_VALIDATION = new PouchError({ + status: 500, + error: 'doc_validation', + reason: 'Bad special document member' +}); +exports.BAD_REQUEST = new PouchError({ + status: 400, + error: 'bad_request', + reason: 'Something wrong with the request' +}); +exports.NOT_AN_OBJECT = new PouchError({ + status: 400, + error: 'bad_request', + reason: 'Document must be a JSON object' +}); +exports.DB_MISSING = new PouchError({ + status: 404, + error: 'not_found', + reason: 'Database not found' +}); +exports.IDB_ERROR = new PouchError({ + status: 500, + error: 'indexed_db_went_bad', + reason: 'unknown' +}); +exports.WSQ_ERROR = new PouchError({ + status: 500, + error: 'web_sql_went_bad', + reason: 'unknown' +}); +exports.LDB_ERROR = new PouchError({ + status: 500, + error: 'levelDB_went_went_bad', + reason: 'unknown' +}); +exports.FORBIDDEN = new PouchError({ + status: 403, + error: 'forbidden', + reason: 'Forbidden by design doc validate_doc_update function' +}); +exports.error = function (error, reason, name) { + function CustomPouchError(msg) { + this.message = reason; + if (name) { + this.name = name; + } + } + CustomPouchError.prototype = error; + return new CustomPouchError(reason); +}; + +},{}],6:[function(_dereq_,module,exports){ +(function (process,global){ +'use strict'; + +var crypto = _dereq_('crypto'); +var Md5 = _dereq_('spark-md5'); +var setImmediateShim = global.setImmediate || global.setTimeout; +var MD5_CHUNK_SIZE = 32768; + +function sliceShim(arrayBuffer, begin, end) { + if (typeof arrayBuffer.slice === 'function') { + if (!begin) { + return arrayBuffer.slice(); + } else if (!end) { + return arrayBuffer.slice(begin); + } else { + return arrayBuffer.slice(begin, end); + } + } + // + // shim for IE courtesy of http://stackoverflow.com/a/21440217 + // + + //If `begin`/`end` is unspecified, Chrome assumes 0, so we do the same + //Chrome also converts the values to integers via flooring + begin = Math.floor(begin || 0); + end = Math.floor(end || 0); + + var len = arrayBuffer.byteLength; + + //If either `begin` or `end` is negative, it refers to an + //index from the end of the array, as opposed to from the beginning. + //The range specified by the `begin` and `end` values is clamped to the + //valid index range for the current array. + begin = begin < 0 ? Math.max(begin + len, 0) : Math.min(len, begin); + end = end < 0 ? Math.max(end + len, 0) : Math.min(len, end); + + //If the computed length of the new ArrayBuffer would be negative, it + //is clamped to zero. + if (end - begin <= 0) { + return new ArrayBuffer(0); + } + + var result = new ArrayBuffer(end - begin); + var resultBytes = new Uint8Array(result); + var sourceBytes = new Uint8Array(arrayBuffer, begin, end - begin); + + resultBytes.set(sourceBytes); + + return result; +} + +// convert a 64-bit int to a binary string +function intToString(int) { + var bytes = [ + (int & 0xff), + ((int >>> 8) & 0xff), + ((int >>> 16) & 0xff), + ((int >>> 24) & 0xff) + ]; + return bytes.map(function (byte) { + return String.fromCharCode(byte); + }).join(''); +} + +// convert an array of 64-bit ints into +// a base64-encoded string +function rawToBase64(raw) { + var res = ''; + for (var i = 0; i < raw.length; i++) { + res += intToString(raw[i]); + } + return global.btoa(res); +} + +module.exports = function (data, callback) { + if (!process.browser) { + var base64 = crypto.createHash('md5').update(data).digest('base64'); + callback(null, base64); + return; + } + var inputIsString = typeof data === 'string'; + var len = inputIsString ? data.length : data.byteLength; + var chunkSize = Math.min(MD5_CHUNK_SIZE, len); + var chunks = Math.ceil(len / chunkSize); + var currentChunk = 0; + var buffer = inputIsString ? new Md5() : new Md5.ArrayBuffer(); + + function append(buffer, data, start, end) { + if (inputIsString) { + buffer.appendBinary(data.substring(start, end)); + } else { + buffer.append(sliceShim(data, start, end)); + } + } + + function loadNextChunk() { + var start = currentChunk * chunkSize; + var end = start + chunkSize; + if ((start + chunkSize) >= data.size) { + end = data.size; + } + currentChunk++; + if (currentChunk < chunks) { + append(buffer, data, start, end); + setImmediateShim(loadNextChunk); + } else { + append(buffer, data, start, end); + var raw = buffer.end(true); + var base64 = rawToBase64(raw); + callback(null, base64); + buffer.destroy(); + } + } + loadNextChunk(); +}; + +}).call(this,_dereq_('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"_process":24,"crypto":16,"spark-md5":117}],7:[function(_dereq_,module,exports){ +'use strict'; + +var fs = _dereq_('fs'); +var path = _dereq_('path'); +var utils = _dereq_('../utils'); +var merge = _dereq_('../merge'); +var levelup = _dereq_('levelup'); +var through = _dereq_('through2').obj; +var leveldown = _dereq_("leveldown"); + +var stores = [ + 'document-store', + 'by-sequence', + 'attach-store', + 'attach-binary-store' +]; +function formatSeq(n) { + return ('0000000000000000' + n).slice(-16); +} +var UPDATE_SEQ_KEY = '_local_last_update_seq'; +var DOC_COUNT_KEY = '_local_doc_count'; +var UUID_KEY = '_local_uuid'; + +exports.toSublevel = function (name, db, callback) { + var base = path.resolve(name); + function move(store, index, cb) { + var storePath = path.join(base, store); + var opts; + if (index === 3) { + opts = { + valueEncoding: 'binary' + }; + } else { + opts = { + valueEncoding: 'json' + }; + } + var sub = db.sublevel(store, opts); + var orig = levelup(storePath, opts); + var from = orig.createReadStream(); + var to = sub.createWriteStream(); + from.on('end', function () { + orig.close(function (err) { + cb(err, storePath); + }); + }); + from.pipe(to); + } + fs.unlink(base + '.uuid', function (err) { + if (err) { + return callback(); + } + var todo = 4; + var done = []; + stores.forEach(function (store, i) { + move(store, i, function (err, storePath) { + if (err) { + return callback(err); + } + done.push(storePath); + if (!(--todo)) { + done.forEach(function (item) { + leveldown.destroy(item, function () { + if (++todo === done.length) { + fs.rmdir(base, callback); + } + }); + }); + } + }); + }); + }); +}; +exports.localAndMetaStores = function (db, stores, callback) { + var batches = []; + stores.bySeqStore.get(UUID_KEY, function (err, value) { + if (err) { + // no uuid key, so don't need to migrate; + return callback(); + } + batches.push({ + key: UUID_KEY, + value: value, + prefix: stores.metaStore, + type: 'put', + valueEncoding: 'json' + }); + batches.push({ + key: UUID_KEY, + prefix: stores.bySeqStore, + type: 'del' + }); + stores.bySeqStore.get(DOC_COUNT_KEY, function (err, value) { + if (value) { + // if no doc count key, + // just skip + // we can live with this + batches.push({ + key: DOC_COUNT_KEY, + value: value, + prefix: stores.metaStore, + type: 'put', + valueEncoding: 'json' + }); + batches.push({ + key: DOC_COUNT_KEY, + prefix: stores.bySeqStore, + type: 'del' + }); + } + stores.bySeqStore.get(UPDATE_SEQ_KEY, function (err, value) { + if (value) { + // if no UPDATE_SEQ_KEY + // just skip + // we've gone to far to stop. + batches.push({ + key: UPDATE_SEQ_KEY, + value: value, + prefix: stores.metaStore, + type: 'put', + valueEncoding: 'json' + }); + batches.push({ + key: UPDATE_SEQ_KEY, + prefix: stores.bySeqStore, + type: 'del' + }); + } + var deletedSeqs = {}; + stores.docStore.createReadStream({ + startKey: '_', + endKey: '_\xFF' + }).pipe(through(function (ch, _, next) { + if (!utils.isLocalId(ch.key)) { + return next(); + } + batches.push({ + key: ch.key, + prefix: stores.docStore, + type: 'del' + }); + var winner = merge.winningRev(ch.value); + Object.keys(ch.value.rev_map).forEach(function (key) { + if (key !== 'winner') { + this.push(formatSeq(ch.value.rev_map[key])); + } + }, this); + var winningSeq = ch.value.rev_map[winner]; + stores.bySeqStore.get(formatSeq(winningSeq), function (err, value) { + if (!err) { + batches.push({ + key: ch.key, + value: value, + prefix: stores.localStore, + type: 'put', + valueEncoding: 'json' + }); + } + next(); + }); + + })).pipe(through(function (seq, _, next) { + if (deletedSeqs[seq]) { + return next(); + } + deletedSeqs[seq] = true; + stores.bySeqStore.get(seq, function (err, resp) { + if (err || !utils.isLocalId(resp._id)) { + return next(); + } + batches.push({ + key: seq, + prefix: stores.bySeqStore, + type: 'del' + }); + next(); + }); + }, function (next) { + db.batch(batches, callback); + })); + }); + }); + }); + +}; +},{"../merge":10,"../utils":13,"fs":15,"leveldown":"leveldown","levelup":75,"path":23,"through2":132}],8:[function(_dereq_,module,exports){ +'use strict'; + +// originally parseUri 1.2.2, now patched by us +// (c) Steven Levithan <stevenlevithan.com> +// MIT License +var options = { + strictMode: false, + key: ["source", "protocol", "authority", "userInfo", "user", "password", + "host", "port", "relative", "path", "directory", "file", "query", + "anchor"], + q: { + name: "queryKey", + parser: /(?:^|&)([^&=]*)=?([^&]*)/g + }, + parser: { + /* jshint maxlen: false */ + strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, + loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ + } +}; +function parseUri(str) { + var o = options; + var m = o.parser[o.strictMode ? "strict" : "loose"].exec(str); + var uri = {}; + var i = 14; + + while (i--) { + var key = o.key[i]; + var value = m[i] || ""; + var encoded = ['user', 'password'].indexOf(key) !== -1; + uri[key] = encoded ? decodeURIComponent(value) : value; + } + + uri[o.q.name] = {}; + uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) { + if ($1) { + uri[o.q.name][$1] = $2; + } + }); + + return uri; +} + + +module.exports = parseUri; +},{}],9:[function(_dereq_,module,exports){ +"use strict"; + +// BEGIN Math.uuid.js + +/*! +Math.uuid.js (v1.4) +http://www.broofa.com +mailto:robert@broofa.com + +Copyright (c) 2010 Robert Kieffer +Dual licensed under the MIT and GPL licenses. +*/ + +/* + * Generate a random uuid. + * + * USAGE: Math.uuid(length, radix) + * length - the desired number of characters + * radix - the number of allowable values for each character. + * + * EXAMPLES: + * // No arguments - returns RFC4122, version 4 ID + * >>> Math.uuid() + * "92329D39-6F5C-4520-ABFC-AAB64544E172" + * + * // One argument - returns ID of the specified length + * >>> Math.uuid(15) // 15 character ID (default base=62) + * "VcydxgltxrVZSTV" + * + * // Two arguments - returns ID of the specified length, and radix. + * // (Radix must be <= 62) + * >>> Math.uuid(8, 2) // 8 character ID (base=2) + * "01001010" + * >>> Math.uuid(8, 10) // 8 character ID (base=10) + * "47473046" + * >>> Math.uuid(8, 16) // 8 character ID (base=16) + * "098F4D35" + */ +var chars = ( + '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' + + 'abcdefghijklmnopqrstuvwxyz' +).split(''); +function getValue(radix) { + return 0 | Math.random() * radix; +} +function uuid(len, radix) { + radix = radix || chars.length; + var out = ''; + var i = -1; + + if (len) { + // Compact form + while (++i < len) { + out += chars[getValue(radix)]; + } + return out; + } + // rfc4122, version 4 form + // Fill in random data. At i==19 set the high bits of clock sequence as + // per rfc4122, sec. 4.1.5 + while (++i < 36) { + switch (i) { + case 8: + case 13: + case 18: + case 23: + out += '-'; + break; + case 19: + out += chars[(getValue(16) & 0x3) | 0x8]; + break; + default: + out += chars[getValue(16)]; + } + } + + return out; +} + + + +module.exports = uuid; + + +},{}],10:[function(_dereq_,module,exports){ +'use strict'; +var extend = _dereq_('pouchdb-extend'); + + +// for a better overview of what this is doing, read: +// https://github.com/apache/couchdb/blob/master/src/couchdb/couch_key_tree.erl +// +// But for a quick intro, CouchDB uses a revision tree to store a documents +// history, A -> B -> C, when a document has conflicts, that is a branch in the +// tree, A -> (B1 | B2 -> C), We store these as a nested array in the format +// +// KeyTree = [Path ... ] +// Path = {pos: position_from_root, ids: Tree} +// Tree = [Key, Opts, [Tree, ...]], in particular single node: [Key, []] + +// Turn a path as a flat array into a tree with a single branch +function pathToTree(path) { + var doc = path.shift(); + var root = [doc.id, doc.opts, []]; + var leaf = root; + var nleaf; + + while (path.length) { + doc = path.shift(); + nleaf = [doc.id, doc.opts, []]; + leaf[2].push(nleaf); + leaf = nleaf; + } + return root; +} + +// Merge two trees together +// The roots of tree1 and tree2 must be the same revision +function mergeTree(in_tree1, in_tree2) { + var queue = [{tree1: in_tree1, tree2: in_tree2}]; + var conflicts = false; + while (queue.length > 0) { + var item = queue.pop(); + var tree1 = item.tree1; + var tree2 = item.tree2; + + if (tree1[1].status || tree2[1].status) { + tree1[1].status = + (tree1[1].status === 'available' || + tree2[1].status === 'available') ? 'available' : 'missing'; + } + + for (var i = 0; i < tree2[2].length; i++) { + if (!tree1[2][0]) { + conflicts = 'new_leaf'; + tree1[2][0] = tree2[2][i]; + continue; + } + + var merged = false; + for (var j = 0; j < tree1[2].length; j++) { + if (tree1[2][j][0] === tree2[2][i][0]) { + queue.push({tree1: tree1[2][j], tree2: tree2[2][i]}); + merged = true; + } + } + if (!merged) { + conflicts = 'new_branch'; + tree1[2].push(tree2[2][i]); + tree1[2].sort(); + } + } + } + return {conflicts: conflicts, tree: in_tree1}; +} + +function doMerge(tree, path, dontExpand) { + var restree = []; + var conflicts = false; + var merged = false; + var res; + + if (!tree.length) { + return {tree: [path], conflicts: 'new_leaf'}; + } + + tree.forEach(function (branch) { + if (branch.pos === path.pos && branch.ids[0] === path.ids[0]) { + // Paths start at the same position and have the same root, so they need + // merged + res = mergeTree(branch.ids, path.ids); + restree.push({pos: branch.pos, ids: res.tree}); + conflicts = conflicts || res.conflicts; + merged = true; + } else if (dontExpand !== true) { + // The paths start at a different position, take the earliest path and + // traverse up until it as at the same point from root as the path we + // want to merge. If the keys match we return the longer path with the + // other merged After stemming we dont want to expand the trees + + var t1 = branch.pos < path.pos ? branch : path; + var t2 = branch.pos < path.pos ? path : branch; + var diff = t2.pos - t1.pos; + + var candidateParents = []; + + var trees = []; + trees.push({ids: t1.ids, diff: diff, parent: null, parentIdx: null}); + while (trees.length > 0) { + var item = trees.pop(); + if (item.diff === 0) { + if (item.ids[0] === t2.ids[0]) { + candidateParents.push(item); + } + continue; + } + if (!item.ids) { + continue; + } + /*jshint loopfunc:true */ + item.ids[2].forEach(function (el, idx) { + trees.push( + {ids: el, diff: item.diff - 1, parent: item.ids, parentIdx: idx}); + }); + } + + var el = candidateParents[0]; + + if (!el) { + restree.push(branch); + } else { + res = mergeTree(el.ids, t2.ids); + el.parent[2][el.parentIdx] = res.tree; + restree.push({pos: t1.pos, ids: t1.ids}); + conflicts = conflicts || res.conflicts; + merged = true; + } + } else { + restree.push(branch); + } + }); + + // We didnt find + if (!merged) { + restree.push(path); + } + + restree.sort(function (a, b) { + return a.pos - b.pos; + }); + + return { + tree: restree, + conflicts: conflicts || 'internal_node' + }; +} + +// To ensure we dont grow the revision tree infinitely, we stem old revisions +function stem(tree, depth) { + // First we break out the tree into a complete list of root to leaf paths, + // we cut off the start of the path and generate a new set of flat trees + var stemmedPaths = PouchMerge.rootToLeaf(tree).map(function (path) { + var stemmed = path.ids.slice(-depth); + return { + pos: path.pos + (path.ids.length - stemmed.length), + ids: pathToTree(stemmed) + }; + }); + // Then we remerge all those flat trees together, ensuring that we dont + // connect trees that would go beyond the depth limit + return stemmedPaths.reduce(function (prev, current, i, arr) { + return doMerge(prev, current, true).tree; + }, [stemmedPaths.shift()]); +} + +var PouchMerge = {}; + +PouchMerge.merge = function (tree, path, depth) { + // Ugh, nicer way to not modify arguments in place? + tree = extend(true, [], tree); + path = extend(true, {}, path); + var newTree = doMerge(tree, path); + return { + tree: stem(newTree.tree, depth), + conflicts: newTree.conflicts + }; +}; + +// We fetch all leafs of the revision tree, and sort them based on tree length +// and whether they were deleted, undeleted documents with the longest revision +// tree (most edits) win +// The final sort algorithm is slightly documented in a sidebar here: +// http://guide.couchdb.org/draft/conflicts.html +PouchMerge.winningRev = function (metadata) { + var leafs = []; + PouchMerge.traverseRevTree(metadata.rev_tree, + function (isLeaf, pos, id, something, opts) { + if (isLeaf) { + leafs.push({pos: pos, id: id, deleted: !!opts.deleted}); + } + }); + leafs.sort(function (a, b) { + if (a.deleted !== b.deleted) { + return a.deleted > b.deleted ? 1 : -1; + } + if (a.pos !== b.pos) { + return b.pos - a.pos; + } + return a.id < b.id ? 1 : -1; + }); + + return leafs[0].pos + '-' + leafs[0].id; +}; + +// Pretty much all below can be combined into a higher order function to +// traverse revisions +// The return value from the callback will be passed as context to all +// children of that node +PouchMerge.traverseRevTree = function (revs, callback) { + var toVisit = revs.slice(); + + var node; + while ((node = toVisit.pop())) { + var pos = node.pos; + var tree = node.ids; + var branches = tree[2]; + var newCtx = + callback(branches.length === 0, pos, tree[0], node.ctx, tree[1]); + for (var i = 0, len = branches.length; i < len; i++) { + toVisit.push({pos: pos + 1, ids: branches[i], ctx: newCtx}); + } + } +}; + +PouchMerge.collectLeaves = function (revs) { + var leaves = []; + PouchMerge.traverseRevTree(revs, function (isLeaf, pos, id, acc, opts) { + if (isLeaf) { + leaves.unshift({rev: pos + "-" + id, pos: pos, opts: opts}); + } + }); + leaves.sort(function (a, b) { + return b.pos - a.pos; + }); + leaves.map(function (leaf) { delete leaf.pos; }); + return leaves; +}; + +// returns revs of all conflicts that is leaves such that +// 1. are not deleted and +// 2. are different than winning revision +PouchMerge.collectConflicts = function (metadata) { + var win = PouchMerge.winningRev(metadata); + var leaves = PouchMerge.collectLeaves(metadata.rev_tree); + var conflicts = []; + leaves.forEach(function (leaf) { + if (leaf.rev !== win && !leaf.opts.deleted) { + conflicts.push(leaf.rev); + } + }); + return conflicts; +}; + +PouchMerge.rootToLeaf = function (tree) { + var paths = []; + PouchMerge.traverseRevTree(tree, function (isLeaf, pos, id, history, opts) { + history = history ? history.slice(0) : []; + history.push({id: id, opts: opts}); + if (isLeaf) { + var rootPos = pos + 1 - history.length; + paths.unshift({pos: rootPos, ids: history}); + } + return history; + }); + return paths; +}; + + +module.exports = PouchMerge; + +},{"pouchdb-extend":116}],11:[function(_dereq_,module,exports){ +(function (global){ +"use strict"; + +var adapterConfig = _dereq_('adapter-config'); +var adapterName = adapterConfig.name; +var adapter = _dereq_('./levelalt')(adapterConfig); +var PouchDB = global.PouchDB || _dereq_('pouchdb'); +PouchDB.adapter(adapterName, adapter); +PouchDB.preferredAdapters.push(adapterName); + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./levelalt":12,"adapter-config":"adapter-config","pouchdb":"pouchdb"}],12:[function(_dereq_,module,exports){ +'use strict'; + +var LevelPouch = _dereq_('../adapters/leveldb'); +var leveldown = _dereq_('leveldown'); +var utils = _dereq_('../utils'); +module.exports = altFactory; +function altFactory(adapterConfig) { + function LevelPouchAlt(opts, callback) { + var _opts = utils.extend({ + db: leveldown + }, opts); + + LevelPouch.call(this, _opts, callback); + } + + // overrides for normal LevelDB behavior on Node + LevelPouchAlt.valid = function () { + return adapterConfig.valid(); + }; + LevelPouchAlt.use_prefix = adapterConfig.use_prefix; + + LevelPouchAlt.destroy = utils.toPromise(function (name, opts, callback) { + if (typeof opts === 'function') { + callback = opts; + opts = {}; + } + var _opts = utils.extend({ + db: leveldown + }, opts); + + return LevelPouch.destroy(name, _opts, callback); + }); + return LevelPouchAlt; + +} +},{"../adapters/leveldb":1,"../utils":13,"leveldown":"leveldown"}],13:[function(_dereq_,module,exports){ +(function (process,global){ +/*jshint strict: false */ +/*global chrome */ +var merge = _dereq_('./merge'); +exports.extend = _dereq_('pouchdb-extend'); +exports.ajax = _dereq_('./deps/ajax'); +exports.createBlob = _dereq_('./deps/blob'); +exports.uuid = _dereq_('./deps/uuid'); +exports.getArguments = _dereq_('argsarray'); +var buffer = _dereq_('./deps/buffer'); +var errors = _dereq_('./deps/errors'); +var EventEmitter = _dereq_('events').EventEmitter; +var collections = _dereq_('./deps/collections'); +exports.Map = collections.Map; +exports.Set = collections.Set; + +if (typeof global.Promise === 'function') { + exports.Promise = global.Promise; +} else { + exports.Promise = _dereq_('bluebird'); +} +var Promise = exports.Promise; + +function toObject(array) { + var obj = {}; + array.forEach(function (item) { obj[item] = true; }); + return obj; +} +// List of top level reserved words for doc +var reservedWords = toObject([ + '_id', + '_rev', + '_attachments', + '_deleted', + '_revisions', + '_revs_info', + '_conflicts', + '_deleted_conflicts', + '_local_seq', + '_rev_tree', + //replication documents + '_replication_id', + '_replication_state', + '_replication_state_time', + '_replication_state_reason', + '_replication_stats' +]); + +// List of reserved words that should end up the document +var dataWords = toObject([ + '_attachments', + //replication documents + '_replication_id', + '_replication_state', + '_replication_state_time', + '_replication_state_reason', + '_replication_stats' +]); + +exports.lastIndexOf = function (str, char) { + for (var i = str.length - 1; i >= 0; i--) { + if (str.charAt(i) === char) { + return i; + } + } + return -1; +}; + +exports.clone = function (obj) { + return exports.extend(true, {}, obj); +}; + +// like underscore/lodash _.pick() +exports.pick = function (obj, arr) { + var res = {}; + for (var i = 0, len = arr.length; i < len; i++) { + var prop = arr[i]; + res[prop] = obj[prop]; + } + return res; +}; + +exports.inherits = _dereq_('inherits'); + +// Determine id an ID is valid +// - invalid IDs begin with an underescore that does not begin '_design' or +// '_local' +// - any other string value is a valid id +// Returns the specific error object for each case +exports.invalidIdError = function (id) { + var err; + if (!id) { + err = new TypeError(errors.MISSING_ID.message); + err.status = 412; + } else if (typeof id !== 'string') { + err = new TypeError(errors.INVALID_ID.message); + err.status = 400; + } else if (/^_/.test(id) && !(/^_(design|local)/).test(id)) { + err = new TypeError(errors.RESERVED_ID.message); + err.status = 400; + } + if (err) { + throw err; + } +}; + +function isChromeApp() { + return (typeof chrome !== "undefined" && + typeof chrome.storage !== "undefined" && + typeof chrome.storage.local !== "undefined"); +} + +// Pretty dumb name for a function, just wraps callback calls so we dont +// to if (callback) callback() everywhere +exports.call = exports.getArguments(function (args) { + if (!args.length) { + return; + } + var fun = args.shift(); + if (typeof fun === 'function') { + fun.apply(this, args); + } +}); + +exports.isLocalId = function (id) { + return (/^_local/).test(id); +}; + +// check if a specific revision of a doc has been deleted +// - metadata: the metadata object from the doc store +// - rev: (optional) the revision to check. defaults to winning revision +exports.isDeleted = function (metadata, rev) { + if (!rev) { + rev = merge.winningRev(metadata); + } + var dashIndex = rev.indexOf('-'); + if (dashIndex !== -1) { + rev = rev.substring(dashIndex + 1); + } + var deleted = false; + merge.traverseRevTree(metadata.rev_tree, + function (isLeaf, pos, id, acc, opts) { + if (id === rev) { + deleted = !!opts.deleted; + } + }); + + return deleted; +}; + +exports.revExists = function (metadata, rev) { + var found = false; + merge.traverseRevTree(metadata.rev_tree, function (leaf, pos, id, acc, opts) { + if ((pos + '-' + id) === rev) { + found = true; + } + }); + return found; +}; + +exports.filterChange = function filterChange(opts) { + var req = {}; + var hasFilter = opts.filter && typeof opts.filter === 'function'; + req.query = opts.query_params; + + return function filter(change) { + if (opts.filter && hasFilter && !opts.filter.call(this, change.doc, req)) { + return false; + } + if (!opts.include_docs) { + delete change.doc; + } else if (!opts.attachments) { + for (var att in change.doc._attachments) { + if (change.doc._attachments.hasOwnProperty(att)) { + change.doc._attachments[att].stub = true; + } + } + } + return true; + }; +}; + +// Preprocess documents, parse their revisions, assign an id and a +// revision for new writes that are missing them, etc +exports.parseDoc = function (doc, newEdits) { + + var nRevNum; + var newRevId; + var revInfo; + var error; + var opts = {status: 'available'}; + if (doc._deleted) { + opts.deleted = true; + } + + if (newEdits) { + if (!doc._id) { + doc._id = exports.uuid(); + } + newRevId = exports.uuid(32, 16).toLowerCase(); + if (doc._rev) { + revInfo = /^(\d+)-(.+)$/.exec(doc._rev); + if (!revInfo) { + error = new Error('bad_request'); + error.message = 'Invalid rev format'; + error.error = true; + return error; + } + doc._rev_tree = [{ + pos: parseInt(revInfo[1], 10), + ids: [revInfo[2], {status: 'missing'}, [[newRevId, opts, []]]] + }]; + nRevNum = parseInt(revInfo[1], 10) + 1; + } else { + doc._rev_tree = [{ + pos: 1, + ids : [newRevId, opts, []] + }]; + nRevNum = 1; + } + } else { + if (doc._revisions) { + doc._rev_tree = [{ + pos: doc._revisions.start - doc._revisions.ids.length + 1, + ids: doc._revisions.ids.reduce(function (acc, x) { + if (acc === null) { + return [x, opts, []]; + } else { + return [x, {status: 'missing'}, [acc]]; + } + }, null) + }]; + nRevNum = doc._revisions.start; + newRevId = doc._revisions.ids[0]; + } + if (!doc._rev_tree) { + revInfo = /^(\d+)-(.+)$/.exec(doc._rev); + if (!revInfo) { + error = new Error('bad_request'); + error.message = 'Invalid rev format'; + error.error = true; + return error; + } + nRevNum = parseInt(revInfo[1], 10); + newRevId = revInfo[2]; + doc._rev_tree = [{ + pos: parseInt(revInfo[1], 10), + ids: [revInfo[2], opts, []] + }]; + } + } + + exports.invalidIdError(doc._id); + + doc._rev = [nRevNum, newRevId].join('-'); + + var result = {metadata : {}, data : {}}; + for (var key in doc) { + if (doc.hasOwnProperty(key)) { + var specialKey = key[0] === '_'; + if (specialKey && !reservedWords[key]) { + error = new Error(errors.DOC_VALIDATION.message + ': ' + key); + error.status = errors.DOC_VALIDATION.status; + throw error; + } else if (specialKey && !dataWords[key]) { + result.metadata[key.slice(1)] = doc[key]; + } else { + result.data[key] = doc[key]; + } + } + } + return result; +}; + +exports.isCordova = function () { + return (typeof cordova !== "undefined" || + typeof PhoneGap !== "undefined" || + typeof phonegap !== "undefined"); +}; + +exports.hasLocalStorage = function () { + if (isChromeApp()) { + return false; + } + try { + return global.localStorage; + } catch (e) { + return false; + } +}; +exports.Changes = Changes; +exports.inherits(Changes, EventEmitter); +function Changes() { + if (!(this instanceof Changes)) { + return new Changes(); + } + var self = this; + EventEmitter.call(this); + this.isChrome = isChromeApp(); + this.listeners = {}; + this.hasLocal = false; + if (!this.isChrome) { + this.hasLocal = exports.hasLocalStorage(); + } + if (this.isChrome) { + chrome.storage.onChanged.addListener(function (e) { + // make sure it's event addressed to us + if (e.db_name != null) { + //object only has oldValue, newValue members + self.emit(e.dbName.newValue); + } + }); + } else if (this.hasLocal) { + if (global.addEventListener) { + global.addEventListener("storage", function (e) { + self.emit(e.key); + }); + } else { + global.attachEvent("storage", function (e) { + self.emit(e.key); + }); + } + } + +} +Changes.prototype.addListener = function (dbName, id, db, opts) { + if (this.listeners[id]) { + return; + } + function eventFunction() { + db.changes({ + include_docs: opts.include_docs, + attachments: opts.attachments, + conflicts: opts.conflicts, + continuous: false, + descending: false, + filter: opts.filter, + doc_ids: opts.doc_ids, + view: opts.view, + since: opts.since, + query_params: opts.query_params, + onChange: function (c) { + if (c.seq > opts.since && !opts.cancelled) { + opts.since = c.seq; + exports.call(opts.onChange, c); + } + } + }); + } + this.listeners[id] = eventFunction; + this.on(dbName, eventFunction); +}; + +Changes.prototype.removeListener = function (dbName, id) { + if (!(id in this.listeners)) { + return; + } + EventEmitter.prototype.removeListener.call(this, dbName, + this.listeners[id]); +}; + + +Changes.prototype.notifyLocalWindows = function (dbName) { + //do a useless change on a storage thing + //in order to get other windows's listeners to activate + if (this.isChrome) { + chrome.storage.local.set({dbName: dbName}); + } else if (this.hasLocal) { + localStorage[dbName] = (localStorage[dbName] === "a") ? "b" : "a"; + } +}; + +Changes.prototype.notify = function (dbName) { + this.emit(dbName); + this.notifyLocalWindows(dbName); +}; + +if (!process.browser || !('atob' in global)) { + exports.atob = function (str) { + var base64 = new buffer(str, 'base64'); + // Node.js will just skip the characters it can't encode instead of + // throwing and exception + if (base64.toString('base64') !== str) { + throw ("Cannot base64 encode full string"); + } + return base64.toString('binary'); + }; +} else { + exports.atob = function (str) { + return atob(str); + }; +} + +if (!process.browser || !('btoa' in global)) { + exports.btoa = function (str) { + return new buffer(str, 'binary').toString('base64'); + }; +} else { + exports.btoa = function (str) { + return btoa(str); + }; +} + +// From http://stackoverflow.com/questions/14967647/ (continues on next line) +// encode-decode-image-with-base64-breaks-image (2013-04-21) +exports.fixBinary = function (bin) { + if (!process.browser) { + // don't need to do this in Node + return bin; + } + + var length = bin.length; + var buf = new ArrayBuffer(length); + var arr = new Uint8Array(buf); + for (var i = 0; i < length; i++) { + arr[i] = bin.charCodeAt(i); + } + return buf; +}; + +// shim for browsers that don't support it +exports.readAsBinaryString = function (blob, callback) { + var reader = new FileReader(); + var hasBinaryString = typeof reader.readAsBinaryString === 'function'; + reader.onloadend = function (e) { + var result = e.target.result || ''; + if (hasBinaryString) { + return callback(result); + } + callback(exports.arrayBufferToBinaryString(result)); + }; + if (hasBinaryString) { + reader.readAsBinaryString(blob); + } else { + reader.readAsArrayBuffer(blob); + } +}; + +exports.once = function (fun) { + var called = false; + return exports.getArguments(function (args) { + if (called) { + throw new Error('once called more than once'); + } else { + called = true; + fun.apply(this, args); + } + }); +}; + +exports.toPromise = function (func) { + //create the function we will be returning + return exports.getArguments(function (args) { + var self = this; + var tempCB = + (typeof args[args.length - 1] === 'function') ? args.pop() : false; + // if the last argument is a function, assume its a callback + var usedCB; + if (tempCB) { + // if it was a callback, create a new callback which calls it, + // but do so async so we don't trap any errors + usedCB = function (err, resp) { + process.nextTick(function () { + tempCB(err, resp); + }); + }; + } + var promise = new Promise(function (fulfill, reject) { + var resp; + try { + var callback = exports.once(function (err, mesg) { + if (err) { + reject(err); + } else { + fulfill(mesg); + } + }); + // create a callback for this invocation + // apply the function in the orig context + args.push(callback); + resp = func.apply(self, args); + if (resp && typeof resp.then === 'function') { + fulfill(resp); + } + } catch (e) { + reject(e); + } + }); + // if there is a callback, call it back + if (usedCB) { + promise.then(function (result) { + usedCB(null, result); + }, usedCB); + } + promise.cancel = function () { + return this; + }; + return promise; + }); +}; + +exports.adapterFun = function (name, callback) { + var log = _dereq_('debug')('pouchdb:api'); + + function logApiCall(self, name, args) { + if (!log.enabled) { + return; + } + var logArgs = [self._db_name, name]; + for (var i = 0; i < args.length - 1; i++) { + logArgs.push(args[i]); + } + log.apply(null, logArgs); + + // override the callback itself to log the response + var origCallback = args[args.length - 1]; + args[args.length - 1] = function (err, res) { + var responseArgs = [self._db_name, name]; + responseArgs = responseArgs.concat( + err ? ['error', err] : ['success', res] + ); + log.apply(null, responseArgs); + origCallback(err, res); + }; + } + + + return exports.toPromise(exports.getArguments(function (args) { + if (this._closed) { + return Promise.reject(new Error('database is closed')); + } + var self = this; + logApiCall(self, name, args); + if (!this.taskqueue.isReady) { + return new exports.Promise(function (fulfill, reject) { + self.taskqueue.addTask(function (failed) { + if (failed) { + reject(failed); + } else { + fulfill(self[name].apply(self, args)); + } + }); + }); + } + return callback.apply(this, args); + })); +}; + +//Can't find original post, but this is close +//http://stackoverflow.com/questions/6965107/ (continues on next line) +//converting-between-strings-and-arraybuffers +exports.arrayBufferToBinaryString = function (buffer) { + var binary = ""; + var bytes = new Uint8Array(buffer); + var length = bytes.byteLength; + for (var i = 0; i < length; i++) { + binary += String.fromCharCode(bytes[i]); + } + return binary; +}; + +exports.cancellableFun = function (fun, self, opts) { + + opts = opts ? exports.clone(true, {}, opts) : {}; + + var emitter = new EventEmitter(); + var oldComplete = opts.complete || function () { }; + var complete = opts.complete = exports.once(function (err, resp) { + if (err) { + oldComplete(err); + } else { + emitter.emit('end', resp); + oldComplete(null, resp); + } + emitter.removeAllListeners(); + }); + var oldOnChange = opts.onChange || function () {}; + var lastChange = 0; + self.on('destroyed', function () { + emitter.removeAllListeners(); + }); + opts.onChange = function (change) { + oldOnChange(change); + if (change.seq <= lastChange) { + return; + } + lastChange = change.seq; + emitter.emit('change', change); + if (change.deleted) { + emitter.emit('delete', change); + } else if (change.changes.length === 1 && + change.changes[0].rev.slice(0, 1) === '1-') { + emitter.emit('create', change); + } else { + emitter.emit('update', change); + } + }; + var promise = new Promise(function (fulfill, reject) { + opts.complete = function (err, res) { + if (err) { + reject(err); + } else { + fulfill(res); + } + }; + }); + + promise.then(function (result) { + complete(null, result); + }, complete); + + // this needs to be overwridden by caller, dont fire complete until + // the task is ready + promise.cancel = function () { + promise.isCancelled = true; + if (self.taskqueue.isReady) { + opts.complete(null, {status: 'cancelled'}); + } + }; + + if (!self.taskqueue.isReady) { + self.taskqueue.addTask(function () { + if (promise.isCancelled) { + opts.complete(null, {status: 'cancelled'}); + } else { + fun(self, opts, promise); + } + }); + } else { + fun(self, opts, promise); + } + promise.on = emitter.on.bind(emitter); + promise.once = emitter.once.bind(emitter); + promise.addListener = emitter.addListener.bind(emitter); + promise.removeListener = emitter.removeListener.bind(emitter); + promise.removeAllListeners = emitter.removeAllListeners.bind(emitter); + promise.setMaxListeners = emitter.setMaxListeners.bind(emitter); + promise.listeners = emitter.listeners.bind(emitter); + promise.emit = emitter.emit.bind(emitter); + return promise; +}; + +exports.MD5 = exports.toPromise(_dereq_('./deps/md5')); + +// designed to give info to browser users, who are disturbed +// when they see 404s in the console +exports.explain404 = function (str) { + if (process.browser && 'console' in global && 'info' in console) { + console.info('The above 404 is totally normal. ' + str); + } +}; + +exports.parseUri = _dereq_('./deps/parse-uri'); + +exports.compare = function (left, right) { + return left < right ? -1 : left > right ? 1 : 0; +}; + +exports.updateDoc = function updateDoc(prev, docInfo, results, + i, cb, write, newEdits) { + + if (exports.revExists(prev, docInfo.metadata.rev)) { + results[i] = docInfo; + return cb(); + } + + var previouslyDeleted = exports.isDeleted(prev); + var deleted = exports.isDeleted(docInfo.metadata); + var isRoot = /^1-/.test(docInfo.metadata.rev); + + if (previouslyDeleted && !deleted && newEdits && isRoot) { + var newDoc = docInfo.data; + newDoc._rev = merge.winningRev(prev); + newDoc._id = docInfo.metadata.id; + docInfo = exports.parseDoc(newDoc, newEdits); + } + + var merged = merge.merge(prev.rev_tree, docInfo.metadata.rev_tree[0], 1000); + + var inConflict = newEdits && (((previouslyDeleted && deleted) || + (!previouslyDeleted && merged.conflicts !== 'new_leaf') || + (previouslyDeleted && !deleted && merged.conflicts === 'new_branch'))); + + if (inConflict) { + var err = errors.REV_CONFLICT; + results[i] = err; + return cb(); + } + + docInfo.metadata.rev_tree = merged.tree; + + // recalculate + var winningRev = merge.winningRev(docInfo.metadata); + deleted = exports.isDeleted(docInfo.metadata, winningRev); + + write(docInfo, winningRev, deleted, cb, true, i); +}; + +exports.processDocs = function processDocs(docInfos, api, fetchedDocs, + tx, results, writeDoc, opts) { + + if (!docInfos.length) { + return; + } + + function insertDoc(docInfo, resultsIdx, callback) { + // Cant insert new deleted documents + var winningRev = merge.winningRev(docInfo.metadata); + var deleted = exports.isDeleted(docInfo.metadata, winningRev); + if ('was_delete' in opts && deleted) { + results[resultsIdx] = errors.MISSING_DOC; + return callback(); + } + writeDoc(docInfo, winningRev, deleted, callback, false, resultsIdx); + } + + var newEdits = opts.new_edits; + var idsToDocs = new exports.Map(); + + docInfos.forEach(function (currentDoc, resultsIdx) { + + if (currentDoc._id && exports.isLocalId(currentDoc._id)) { + api[currentDoc._deleted ? '_removeLocal' : '_putLocal']( + currentDoc, {ctx: tx}, function (err, resp) { + if (err) { + results[resultsIdx] = err; + } else { + results[resultsIdx] = {}; + } + }); + return; + } + + var id = currentDoc.metadata.id; + if (idsToDocs.has(id)) { + idsToDocs.get(id).push([currentDoc, resultsIdx]); + } else { + idsToDocs.set(id, [[currentDoc, resultsIdx]]); + } + }); + + // in the case of new_edits, the user can provide multiple docs + // with the same id. these need to be processed sequentially + idsToDocs.forEach(function (docs, id) { + var numDone = 0; + + function docWritten() { + if (++numDone < docs.length) { + nextDoc(); + } + } + function nextDoc() { + var value = docs[numDone]; + var currentDoc = value[0]; + var resultsIdx = value[1]; + + if (fetchedDocs.has(id)) { + exports.updateDoc(fetchedDocs.get(id), currentDoc, results, + resultsIdx, docWritten, writeDoc, newEdits); + } else { + insertDoc(currentDoc, resultsIdx, docWritten); + } + } + nextDoc(); + }); +}; + +exports.preprocessAttachments = function preprocessAttachments( + docInfos, blobType, callback) { + + if (!docInfos.length) { + return callback(); + } + + var docv = 0; + + function parseBase64(data) { + try { + return exports.atob(data); + } catch (e) { + var err = errors.error(errors.BAD_ARG, + "Attachments need to be base64 encoded"); + return {error: err}; + } + } + + function preprocessAttachment(att, callback) { + if (att.stub) { + return callback(); + } + if (typeof att.data === 'string') { + // input is a base64 string + + var asBinary = parseBase64(att.data); + if (asBinary.error) { + return callback(asBinary.error); + } + + att.length = asBinary.length; + if (blobType === 'blob') { + att.data = exports.createBlob([exports.fixBinary(asBinary)], + {type: att.content_type}); + } else if (blobType === 'base64') { + att.data = exports.btoa(asBinary); + } else { // binary + att.data = asBinary; + } + exports.MD5(asBinary).then(function (result) { + att.digest = 'md5-' + result; + callback(); + }); + } else { // input is a blob + exports.readAsBinaryString(att.data, function (binary) { + if (blobType === 'binary') { + att.data = binary; + } else if (blobType === 'base64') { + att.data = exports.btoa(binary); + } + exports.MD5(binary).then(function (result) { + att.digest = 'md5-' + result; + att.length = binary.length; + callback(); + }); + }); + } + } + + var overallErr; + + docInfos.forEach(function (docInfo) { + var attachments = docInfo.data && docInfo.data._attachments ? + Object.keys(docInfo.data._attachments) : []; + var recv = 0; + + if (!attachments.length) { + return done(); + } + + function processedAttachment(err) { + overallErr = err; + recv++; + if (recv === attachments.length) { + done(); + } + } + + for (var key in docInfo.data._attachments) { + if (docInfo.data._attachments.hasOwnProperty(key)) { + preprocessAttachment(docInfo.data._attachments[key], + processedAttachment); + } + } + }); + + function done() { + docv++; + if (docInfos.length === docv) { + if (overallErr) { + callback(overallErr); + } else { + callback(); + } + } + } +}; +}).call(this,_dereq_('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./deps/ajax":2,"./deps/blob":3,"./deps/buffer":16,"./deps/collections":4,"./deps/errors":5,"./deps/md5":6,"./deps/parse-uri":8,"./deps/uuid":9,"./merge":10,"_process":24,"argsarray":14,"bluebird":101,"debug":40,"events":21,"inherits":44,"pouchdb-extend":116}],14:[function(_dereq_,module,exports){ +'use strict'; + +module.exports = argsArray; + +function argsArray(fun) { + return function () { + var len = arguments.length; + if (len) { + var args = []; + var i = -1; + while (++i < len) { + args[i] = arguments[i]; + } + return fun.call(this, args); + } else { + return fun.call(this, []); + } + }; +} +},{}],15:[function(_dereq_,module,exports){ + +},{}],16:[function(_dereq_,module,exports){ +module.exports=_dereq_(15) +},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/lib/_empty.js":15}],17:[function(_dereq_,module,exports){ +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org> + * @license MIT + */ + +var base64 = _dereq_('base64-js') +var ieee754 = _dereq_('ieee754') +var isArray = _dereq_('is-array') + +exports.Buffer = Buffer +exports.SlowBuffer = Buffer +exports.INSPECT_MAX_BYTES = 50 +Buffer.poolSize = 8192 // not used by this implementation + +var kMaxLength = 0x3fffffff + +/** + * If `Buffer.TYPED_ARRAY_SUPPORT`: + * === true Use Uint8Array implementation (fastest) + * === false Use Object implementation (most compatible, even IE6) + * + * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, + * Opera 11.6+, iOS 4.2+. + * + * Note: + * + * - Implementation must support adding new properties to `Uint8Array` instances. + * Firefox 4-29 lacked support, fixed in Firefox 30+. + * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. + * + * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. + * + * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of + * incorrect length in some situations. + * + * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they will + * get the Object implementation, which is slower but will work correctly. + */ +Buffer.TYPED_ARRAY_SUPPORT = (function () { + try { + var buf = new ArrayBuffer(0) + var arr = new Uint8Array(buf) + arr.foo = function () { return 42 } + return 42 === arr.foo() && // typed array instances can be augmented + typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` + new Uint8Array(1).subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` + } catch (e) { + return false + } +})() + +/** + * Class: Buffer + * ============= + * + * The Buffer constructor returns instances of `Uint8Array` that are augmented + * with function properties for all the node `Buffer` API functions. We use + * `Uint8Array` so that square bracket notation works as expected -- it returns + * a single octet. + * + * By augmenting the instances, we can avoid modifying the `Uint8Array` + * prototype. + */ +function Buffer (subject, encoding, noZero) { + if (!(this instanceof Buffer)) + return new Buffer(subject, encoding, noZero) + + var type = typeof subject + + // Find the length + var length + if (type === 'number') + length = subject > 0 ? subject >>> 0 : 0 + else if (type === 'string') { + if (encoding === 'base64') + subject = base64clean(subject) + length = Buffer.byteLength(subject, encoding) + } else if (type === 'object' && subject !== null) { // assume object is array-like + if (subject.type === 'Buffer' && isArray(subject.data)) + subject = subject.data + length = +subject.length > 0 ? Math.floor(+subject.length) : 0 + } else + throw new TypeError('must start with number, buffer, array or string') + + if (this.length > kMaxLength) + throw new RangeError('Attempt to allocate Buffer larger than maximum ' + + 'size: 0x' + kMaxLength.toString(16) + ' bytes') + + var buf + if (Buffer.TYPED_ARRAY_SUPPORT) { + // Preferred: Return an augmented `Uint8Array` instance for best performance + buf = Buffer._augment(new Uint8Array(length)) + } else { + // Fallback: Return THIS instance of Buffer (created by `new`) + buf = this + buf.length = length + buf._isBuffer = true + } + + var i + if (Buffer.TYPED_ARRAY_SUPPORT && typeof subject.byteLength === 'number') { + // Speed optimization -- use set if we're copying from a typed array + buf._set(subject) + } else if (isArrayish(subject)) { + // Treat array-ish objects as a byte array + if (Buffer.isBuffer(subject)) { + for (i = 0; i < length; i++) + buf[i] = subject.readUInt8(i) + } else { + for (i = 0; i < length; i++) + buf[i] = ((subject[i] % 256) + 256) % 256 + } + } else if (type === 'string') { + buf.write(subject, 0, encoding) + } else if (type === 'number' && !Buffer.TYPED_ARRAY_SUPPORT && !noZero) { + for (i = 0; i < length; i++) { + buf[i] = 0 + } + } + + return buf +} + +Buffer.isBuffer = function (b) { + return !!(b != null && b._isBuffer) +} + +Buffer.compare = function (a, b) { + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) + throw new TypeError('Arguments must be Buffers') + + var x = a.length + var y = b.length + for (var i = 0, len = Math.min(x, y); i < len && a[i] === b[i]; i++) {} + if (i !== len) { + x = a[i] + y = b[i] + } + if (x < y) return -1 + if (y < x) return 1 + return 0 +} + +Buffer.isEncoding = function (encoding) { + switch (String(encoding).toLowerCase()) { + case 'hex': + case 'utf8': + case 'utf-8': + case 'ascii': + case 'binary': + case 'base64': + case 'raw': + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return true + default: + return false + } +} + +Buffer.concat = function (list, totalLength) { + if (!isArray(list)) throw new TypeError('Usage: Buffer.concat(list[, length])') + + if (list.length === 0) { + return new Buffer(0) + } else if (list.length === 1) { + return list[0] + } + + var i + if (totalLength === undefined) { + totalLength = 0 + for (i = 0; i < list.length; i++) { + totalLength += list[i].length + } + } + + var buf = new Buffer(totalLength) + var pos = 0 + for (i = 0; i < list.length; i++) { + var item = list[i] + item.copy(buf, pos) + pos += item.length + } + return buf +} + +Buffer.byteLength = function (str, encoding) { + var ret + str = str + '' + switch (encoding || 'utf8') { + case 'ascii': + case 'binary': + case 'raw': + ret = str.length + break + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + ret = str.length * 2 + break + case 'hex': + ret = str.length >>> 1 + break + case 'utf8': + case 'utf-8': + ret = utf8ToBytes(str).length + break + case 'base64': + ret = base64ToBytes(str).length + break + default: + ret = str.length + } + return ret +} + +// pre-set for values that may exist in the future +Buffer.prototype.length = undefined +Buffer.prototype.parent = undefined + +// toString(encoding, start=0, end=buffer.length) +Buffer.prototype.toString = function (encoding, start, end) { + var loweredCase = false + + start = start >>> 0 + end = end === undefined || end === Infinity ? this.length : end >>> 0 + + if (!encoding) encoding = 'utf8' + if (start < 0) start = 0 + if (end > this.length) end = this.length + if (end <= start) return '' + + while (true) { + switch (encoding) { + case 'hex': + return hexSlice(this, start, end) + + case 'utf8': + case 'utf-8': + return utf8Slice(this, start, end) + + case 'ascii': + return asciiSlice(this, start, end) + + case 'binary': + return binarySlice(this, start, end) + + case 'base64': + return base64Slice(this, start, end) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return utf16leSlice(this, start, end) + + default: + if (loweredCase) + throw new TypeError('Unknown encoding: ' + encoding) + encoding = (encoding + '').toLowerCase() + loweredCase = true + } + } +} + +Buffer.prototype.equals = function (b) { + if(!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + return Buffer.compare(this, b) === 0 +} + +Buffer.prototype.inspect = function () { + var str = '' + var max = exports.INSPECT_MAX_BYTES + if (this.length > 0) { + str = this.toString('hex', 0, max).match(/.{2}/g).join(' ') + if (this.length > max) + str += ' ... ' + } + return '<Buffer ' + str + '>' +} + +Buffer.prototype.compare = function (b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + return Buffer.compare(this, b) +} + +// `get` will be removed in Node 0.13+ +Buffer.prototype.get = function (offset) { + console.log('.get() is deprecated. Access using array indexes instead.') + return this.readUInt8(offset) +} + +// `set` will be removed in Node 0.13+ +Buffer.prototype.set = function (v, offset) { + console.log('.set() is deprecated. Access using array indexes instead.') + return this.writeUInt8(v, offset) +} + +function hexWrite (buf, string, offset, length) { + offset = Number(offset) || 0 + var remaining = buf.length - offset + if (!length) { + length = remaining + } else { + length = Number(length) + if (length > remaining) { + length = remaining + } + } + + // must be an even number of digits + var strLen = string.length + if (strLen % 2 !== 0) throw new Error('Invalid hex string') + + if (length > strLen / 2) { + length = strLen / 2 + } + for (var i = 0; i < length; i++) { + var byte = parseInt(string.substr(i * 2, 2), 16) + if (isNaN(byte)) throw new Error('Invalid hex string') + buf[offset + i] = byte + } + return i +} + +function utf8Write (buf, string, offset, length) { + var charsWritten = blitBuffer(utf8ToBytes(string), buf, offset, length) + return charsWritten +} + +function asciiWrite (buf, string, offset, length) { + var charsWritten = blitBuffer(asciiToBytes(string), buf, offset, length) + return charsWritten +} + +function binaryWrite (buf, string, offset, length) { + return asciiWrite(buf, string, offset, length) +} + +function base64Write (buf, string, offset, length) { + var charsWritten = blitBuffer(base64ToBytes(string), buf, offset, length) + return charsWritten +} + +function utf16leWrite (buf, string, offset, length) { + var charsWritten = blitBuffer(utf16leToBytes(string), buf, offset, length) + return charsWritten +} + +Buffer.prototype.write = function (string, offset, length, encoding) { + // Support both (string, offset, length, encoding) + // and the legacy (string, encoding, offset, length) + if (isFinite(offset)) { + if (!isFinite(length)) { + encoding = length + length = undefined + } + } else { // legacy + var swap = encoding + encoding = offset + offset = length + length = swap + } + + offset = Number(offset) || 0 + var remaining = this.length - offset + if (!length) { + length = remaining + } else { + length = Number(length) + if (length > remaining) { + length = remaining + } + } + encoding = String(encoding || 'utf8').toLowerCase() + + var ret + switch (encoding) { + case 'hex': + ret = hexWrite(this, string, offset, length) + break + case 'utf8': + case 'utf-8': + ret = utf8Write(this, string, offset, length) + break + case 'ascii': + ret = asciiWrite(this, string, offset, length) + break + case 'binary': + ret = binaryWrite(this, string, offset, length) + break + case 'base64': + ret = base64Write(this, string, offset, length) + break + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + ret = utf16leWrite(this, string, offset, length) + break + default: + throw new TypeError('Unknown encoding: ' + encoding) + } + return ret +} + +Buffer.prototype.toJSON = function () { + return { + type: 'Buffer', + data: Array.prototype.slice.call(this._arr || this, 0) + } +} + +function base64Slice (buf, start, end) { + if (start === 0 && end === buf.length) { + return base64.fromByteArray(buf) + } else { + return base64.fromByteArray(buf.slice(start, end)) + } +} + +function utf8Slice (buf, start, end) { + var res = '' + var tmp = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; i++) { + if (buf[i] <= 0x7F) { + res += decodeUtf8Char(tmp) + String.fromCharCode(buf[i]) + tmp = '' + } else { + tmp += '%' + buf[i].toString(16) + } + } + + return res + decodeUtf8Char(tmp) +} + +function asciiSlice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; i++) { + ret += String.fromCharCode(buf[i]) + } + return ret +} + +function binarySlice (buf, start, end) { + return asciiSlice(buf, start, end) +} + +function hexSlice (buf, start, end) { + var len = buf.length + + if (!start || start < 0) start = 0 + if (!end || end < 0 || end > len) end = len + + var out = '' + for (var i = start; i < end; i++) { + out += toHex(buf[i]) + } + return out +} + +function utf16leSlice (buf, start, end) { + var bytes = buf.slice(start, end) + var res = '' + for (var i = 0; i < bytes.length; i += 2) { + res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256) + } + return res +} + +Buffer.prototype.slice = function (start, end) { + var len = this.length + start = ~~start + end = end === undefined ? len : ~~end + + if (start < 0) { + start += len; + if (start < 0) + start = 0 + } else if (start > len) { + start = len + } + + if (end < 0) { + end += len + if (end < 0) + end = 0 + } else if (end > len) { + end = len + } + + if (end < start) + end = start + + if (Buffer.TYPED_ARRAY_SUPPORT) { + return Buffer._augment(this.subarray(start, end)) + } else { + var sliceLen = end - start + var newBuf = new Buffer(sliceLen, undefined, true) + for (var i = 0; i < sliceLen; i++) { + newBuf[i] = this[i + start] + } + return newBuf + } +} + +/* + * Need to make sure that buffer isn't trying to write out of bounds. + */ +function checkOffset (offset, ext, length) { + if ((offset % 1) !== 0 || offset < 0) + throw new RangeError('offset is not uint') + if (offset + ext > length) + throw new RangeError('Trying to access beyond buffer length') +} + +Buffer.prototype.readUInt8 = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 1, this.length) + return this[offset] +} + +Buffer.prototype.readUInt16LE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 2, this.length) + return this[offset] | (this[offset + 1] << 8) +} + +Buffer.prototype.readUInt16BE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 2, this.length) + return (this[offset] << 8) | this[offset + 1] +} + +Buffer.prototype.readUInt32LE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length) + + return ((this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16)) + + (this[offset + 3] * 0x1000000) +} + +Buffer.prototype.readUInt32BE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length) + + return (this[offset] * 0x1000000) + + ((this[offset + 1] << 16) | + (this[offset + 2] << 8) | + this[offset + 3]) +} + +Buffer.prototype.readInt8 = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 1, this.length) + if (!(this[offset] & 0x80)) + return (this[offset]) + return ((0xff - this[offset] + 1) * -1) +} + +Buffer.prototype.readInt16LE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 2, this.length) + var val = this[offset] | (this[offset + 1] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt16BE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 2, this.length) + var val = this[offset + 1] | (this[offset] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt32LE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length) + + return (this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16) | + (this[offset + 3] << 24) +} + +Buffer.prototype.readInt32BE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length) + + return (this[offset] << 24) | + (this[offset + 1] << 16) | + (this[offset + 2] << 8) | + (this[offset + 3]) +} + +Buffer.prototype.readFloatLE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, true, 23, 4) +} + +Buffer.prototype.readFloatBE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, false, 23, 4) +} + +Buffer.prototype.readDoubleLE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, true, 52, 8) +} + +Buffer.prototype.readDoubleBE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, false, 52, 8) +} + +function checkInt (buf, value, offset, ext, max, min) { + if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance') + if (value > max || value < min) throw new TypeError('value is out of bounds') + if (offset + ext > buf.length) throw new TypeError('index out of range') +} + +Buffer.prototype.writeUInt8 = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 1, 0xff, 0) + if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) + this[offset] = value + return offset + 1 +} + +function objectWriteUInt16 (buf, value, offset, littleEndian) { + if (value < 0) value = 0xffff + value + 1 + for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) { + buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> + (littleEndian ? i : 1 - i) * 8 + } +} + +Buffer.prototype.writeUInt16LE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 2, 0xffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = value + this[offset + 1] = (value >>> 8) + } else objectWriteUInt16(this, value, offset, true) + return offset + 2 +} + +Buffer.prototype.writeUInt16BE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 2, 0xffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 8) + this[offset + 1] = value + } else objectWriteUInt16(this, value, offset, false) + return offset + 2 +} + +function objectWriteUInt32 (buf, value, offset, littleEndian) { + if (value < 0) value = 0xffffffff + value + 1 + for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) { + buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff + } +} + +Buffer.prototype.writeUInt32LE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 4, 0xffffffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset + 3] = (value >>> 24) + this[offset + 2] = (value >>> 16) + this[offset + 1] = (value >>> 8) + this[offset] = value + } else objectWriteUInt32(this, value, offset, true) + return offset + 4 +} + +Buffer.prototype.writeUInt32BE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 4, 0xffffffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = value + } else objectWriteUInt32(this, value, offset, false) + return offset + 4 +} + +Buffer.prototype.writeInt8 = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 1, 0x7f, -0x80) + if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) + if (value < 0) value = 0xff + value + 1 + this[offset] = value + return offset + 1 +} + +Buffer.prototype.writeInt16LE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 2, 0x7fff, -0x8000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = value + this[offset + 1] = (value >>> 8) + } else objectWriteUInt16(this, value, offset, true) + return offset + 2 +} + +Buffer.prototype.writeInt16BE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 2, 0x7fff, -0x8000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 8) + this[offset + 1] = value + } else objectWriteUInt16(this, value, offset, false) + return offset + 2 +} + +Buffer.prototype.writeInt32LE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = value + this[offset + 1] = (value >>> 8) + this[offset + 2] = (value >>> 16) + this[offset + 3] = (value >>> 24) + } else objectWriteUInt32(this, value, offset, true) + return offset + 4 +} + +Buffer.prototype.writeInt32BE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (value < 0) value = 0xffffffff + value + 1 + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = value + } else objectWriteUInt32(this, value, offset, false) + return offset + 4 +} + +function checkIEEE754 (buf, value, offset, ext, max, min) { + if (value > max || value < min) throw new TypeError('value is out of bounds') + if (offset + ext > buf.length) throw new TypeError('index out of range') +} + +function writeFloat (buf, value, offset, littleEndian, noAssert) { + if (!noAssert) + checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) + ieee754.write(buf, value, offset, littleEndian, 23, 4) + return offset + 4 +} + +Buffer.prototype.writeFloatLE = function (value, offset, noAssert) { + return writeFloat(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeFloatBE = function (value, offset, noAssert) { + return writeFloat(this, value, offset, false, noAssert) +} + +function writeDouble (buf, value, offset, littleEndian, noAssert) { + if (!noAssert) + checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) + ieee754.write(buf, value, offset, littleEndian, 52, 8) + return offset + 8 +} + +Buffer.prototype.writeDoubleLE = function (value, offset, noAssert) { + return writeDouble(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeDoubleBE = function (value, offset, noAssert) { + return writeDouble(this, value, offset, false, noAssert) +} + +// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) +Buffer.prototype.copy = function (target, target_start, start, end) { + var source = this + + if (!start) start = 0 + if (!end && end !== 0) end = this.length + if (!target_start) target_start = 0 + + // Copy 0 bytes; we're done + if (end === start) return + if (target.length === 0 || source.length === 0) return + + // Fatal error conditions + if (end < start) throw new TypeError('sourceEnd < sourceStart') + if (target_start < 0 || target_start >= target.length) + throw new TypeError('targetStart out of bounds') + if (start < 0 || start >= source.length) throw new TypeError('sourceStart out of bounds') + if (end < 0 || end > source.length) throw new TypeError('sourceEnd out of bounds') + + // Are we oob? + if (end > this.length) + end = this.length + if (target.length - target_start < end - start) + end = target.length - target_start + start + + var len = end - start + + if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) { + for (var i = 0; i < len; i++) { + target[i + target_start] = this[i + start] + } + } else { + target._set(this.subarray(start, start + len), target_start) + } +} + +// fill(value, start=0, end=buffer.length) +Buffer.prototype.fill = function (value, start, end) { + if (!value) value = 0 + if (!start) start = 0 + if (!end) end = this.length + + if (end < start) throw new TypeError('end < start') + + // Fill 0 bytes; we're done + if (end === start) return + if (this.length === 0) return + + if (start < 0 || start >= this.length) throw new TypeError('start out of bounds') + if (end < 0 || end > this.length) throw new TypeError('end out of bounds') + + var i + if (typeof value === 'number') { + for (i = start; i < end; i++) { + this[i] = value + } + } else { + var bytes = utf8ToBytes(value.toString()) + var len = bytes.length + for (i = start; i < end; i++) { + this[i] = bytes[i % len] + } + } + + return this +} + +/** + * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance. + * Added in Node 0.12. Only available in browsers that support ArrayBuffer. + */ +Buffer.prototype.toArrayBuffer = function () { + if (typeof Uint8Array !== 'undefined') { + if (Buffer.TYPED_ARRAY_SUPPORT) { + return (new Buffer(this)).buffer + } else { + var buf = new Uint8Array(this.length) + for (var i = 0, len = buf.length; i < len; i += 1) { + buf[i] = this[i] + } + return buf.buffer + } + } else { + throw new TypeError('Buffer.toArrayBuffer not supported in this browser') + } +} + +// HELPER FUNCTIONS +// ================ + +var BP = Buffer.prototype + +/** + * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods + */ +Buffer._augment = function (arr) { + arr.constructor = Buffer + arr._isBuffer = true + + // save reference to original Uint8Array get/set methods before overwriting + arr._get = arr.get + arr._set = arr.set + + // deprecated, will be removed in node 0.13+ + arr.get = BP.get + arr.set = BP.set + + arr.write = BP.write + arr.toString = BP.toString + arr.toLocaleString = BP.toString + arr.toJSON = BP.toJSON + arr.equals = BP.equals + arr.compare = BP.compare + arr.copy = BP.copy + arr.slice = BP.slice + arr.readUInt8 = BP.readUInt8 + arr.readUInt16LE = BP.readUInt16LE + arr.readUInt16BE = BP.readUInt16BE + arr.readUInt32LE = BP.readUInt32LE + arr.readUInt32BE = BP.readUInt32BE + arr.readInt8 = BP.readInt8 + arr.readInt16LE = BP.readInt16LE + arr.readInt16BE = BP.readInt16BE + arr.readInt32LE = BP.readInt32LE + arr.readInt32BE = BP.readInt32BE + arr.readFloatLE = BP.readFloatLE + arr.readFloatBE = BP.readFloatBE + arr.readDoubleLE = BP.readDoubleLE + arr.readDoubleBE = BP.readDoubleBE + arr.writeUInt8 = BP.writeUInt8 + arr.writeUInt16LE = BP.writeUInt16LE + arr.writeUInt16BE = BP.writeUInt16BE + arr.writeUInt32LE = BP.writeUInt32LE + arr.writeUInt32BE = BP.writeUInt32BE + arr.writeInt8 = BP.writeInt8 + arr.writeInt16LE = BP.writeInt16LE + arr.writeInt16BE = BP.writeInt16BE + arr.writeInt32LE = BP.writeInt32LE + arr.writeInt32BE = BP.writeInt32BE + arr.writeFloatLE = BP.writeFloatLE + arr.writeFloatBE = BP.writeFloatBE + arr.writeDoubleLE = BP.writeDoubleLE + arr.writeDoubleBE = BP.writeDoubleBE + arr.fill = BP.fill + arr.inspect = BP.inspect + arr.toArrayBuffer = BP.toArrayBuffer + + return arr +} + +var INVALID_BASE64_RE = /[^+\/0-9A-z]/g + +function base64clean (str) { + // Node strips out invalid characters like \n and \t from the string, base64-js does not + str = stringtrim(str).replace(INVALID_BASE64_RE, '') + // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not + while (str.length % 4 !== 0) { + str = str + '=' + } + return str +} + +function stringtrim (str) { + if (str.trim) return str.trim() + return str.replace(/^\s+|\s+$/g, '') +} + +function isArrayish (subject) { + return isArray(subject) || Buffer.isBuffer(subject) || + subject && typeof subject === 'object' && + typeof subject.length === 'number' +} + +function toHex (n) { + if (n < 16) return '0' + n.toString(16) + return n.toString(16) +} + +function utf8ToBytes (str) { + var byteArray = [] + for (var i = 0; i < str.length; i++) { + var b = str.charCodeAt(i) + if (b <= 0x7F) { + byteArray.push(b) + } else { + var start = i + if (b >= 0xD800 && b <= 0xDFFF) i++ + var h = encodeURIComponent(str.slice(start, i+1)).substr(1).split('%') + for (var j = 0; j < h.length; j++) { + byteArray.push(parseInt(h[j], 16)) + } + } + } + return byteArray +} + +function asciiToBytes (str) { + var byteArray = [] + for (var i = 0; i < str.length; i++) { + // Node's code seems to be doing this and not & 0x7F.. + byteArray.push(str.charCodeAt(i) & 0xFF) + } + return byteArray +} + +function utf16leToBytes (str) { + var c, hi, lo + var byteArray = [] + for (var i = 0; i < str.length; i++) { + c = str.charCodeAt(i) + hi = c >> 8 + lo = c % 256 + byteArray.push(lo) + byteArray.push(hi) + } + + return byteArray +} + +function base64ToBytes (str) { + return base64.toByteArray(str) +} + +function blitBuffer (src, dst, offset, length) { + for (var i = 0; i < length; i++) { + if ((i + offset >= dst.length) || (i >= src.length)) + break + dst[i + offset] = src[i] + } + return i +} + +function decodeUtf8Char (str) { + try { + return decodeURIComponent(str) + } catch (err) { + return String.fromCharCode(0xFFFD) // UTF 8 invalid char + } +} + +},{"base64-js":18,"ieee754":19,"is-array":20}],18:[function(_dereq_,module,exports){ +var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + +;(function (exports) { + 'use strict'; + + var Arr = (typeof Uint8Array !== 'undefined') + ? Uint8Array + : Array + + var PLUS = '+'.charCodeAt(0) + var SLASH = '/'.charCodeAt(0) + var NUMBER = '0'.charCodeAt(0) + var LOWER = 'a'.charCodeAt(0) + var UPPER = 'A'.charCodeAt(0) + + function decode (elt) { + var code = elt.charCodeAt(0) + if (code === PLUS) + return 62 // '+' + if (code === SLASH) + return 63 // '/' + if (code < NUMBER) + return -1 //no match + if (code < NUMBER + 10) + return code - NUMBER + 26 + 26 + if (code < UPPER + 26) + return code - UPPER + if (code < LOWER + 26) + return code - LOWER + 26 + } + + function b64ToByteArray (b64) { + var i, j, l, tmp, placeHolders, arr + + if (b64.length % 4 > 0) { + throw new Error('Invalid string. Length must be a multiple of 4') + } + + // the number of equal signs (place holders) + // if there are two placeholders, than the two characters before it + // represent one byte + // if there is only one, then the three characters before it represent 2 bytes + // this is just a cheap hack to not do indexOf twice + var len = b64.length + placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0 + + // base64 is 4/3 + up to two characters of the original data + arr = new Arr(b64.length * 3 / 4 - placeHolders) + + // if there are placeholders, only get up to the last complete 4 chars + l = placeHolders > 0 ? b64.length - 4 : b64.length + + var L = 0 + + function push (v) { + arr[L++] = v + } + + for (i = 0, j = 0; i < l; i += 4, j += 3) { + tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3)) + push((tmp & 0xFF0000) >> 16) + push((tmp & 0xFF00) >> 8) + push(tmp & 0xFF) + } + + if (placeHolders === 2) { + tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4) + push(tmp & 0xFF) + } else if (placeHolders === 1) { + tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2) + push((tmp >> 8) & 0xFF) + push(tmp & 0xFF) + } + + return arr + } + + function uint8ToBase64 (uint8) { + var i, + extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes + output = "", + temp, length + + function encode (num) { + return lookup.charAt(num) + } + + function tripletToBase64 (num) { + return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F) + } + + // go through the array every three bytes, we'll deal with trailing stuff later + for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) { + temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) + output += tripletToBase64(temp) + } + + // pad the end with zeros, but make sure to not forget the extra bytes + switch (extraBytes) { + case 1: + temp = uint8[uint8.length - 1] + output += encode(temp >> 2) + output += encode((temp << 4) & 0x3F) + output += '==' + break + case 2: + temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]) + output += encode(temp >> 10) + output += encode((temp >> 4) & 0x3F) + output += encode((temp << 2) & 0x3F) + output += '=' + break + } + + return output + } + + exports.toByteArray = b64ToByteArray + exports.fromByteArray = uint8ToBase64 +}(typeof exports === 'undefined' ? (this.base64js = {}) : exports)) + +},{}],19:[function(_dereq_,module,exports){ +exports.read = function(buffer, offset, isLE, mLen, nBytes) { + var e, m, + eLen = nBytes * 8 - mLen - 1, + eMax = (1 << eLen) - 1, + eBias = eMax >> 1, + nBits = -7, + i = isLE ? (nBytes - 1) : 0, + d = isLE ? -1 : 1, + s = buffer[offset + i]; + + i += d; + + e = s & ((1 << (-nBits)) - 1); + s >>= (-nBits); + nBits += eLen; + for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8); + + m = e & ((1 << (-nBits)) - 1); + e >>= (-nBits); + nBits += mLen; + for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8); + + if (e === 0) { + e = 1 - eBias; + } else if (e === eMax) { + return m ? NaN : ((s ? -1 : 1) * Infinity); + } else { + m = m + Math.pow(2, mLen); + e = e - eBias; + } + return (s ? -1 : 1) * m * Math.pow(2, e - mLen); +}; + +exports.write = function(buffer, value, offset, isLE, mLen, nBytes) { + var e, m, c, + eLen = nBytes * 8 - mLen - 1, + eMax = (1 << eLen) - 1, + eBias = eMax >> 1, + rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0), + i = isLE ? 0 : (nBytes - 1), + d = isLE ? 1 : -1, + s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0; + + value = Math.abs(value); + + if (isNaN(value) || value === Infinity) { + m = isNaN(value) ? 1 : 0; + e = eMax; + } else { + e = Math.floor(Math.log(value) / Math.LN2); + if (value * (c = Math.pow(2, -e)) < 1) { + e--; + c *= 2; + } + if (e + eBias >= 1) { + value += rt / c; + } else { + value += rt * Math.pow(2, 1 - eBias); + } + if (value * c >= 2) { + e++; + c /= 2; + } + + if (e + eBias >= eMax) { + m = 0; + e = eMax; + } else if (e + eBias >= 1) { + m = (value * c - 1) * Math.pow(2, mLen); + e = e + eBias; + } else { + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); + e = 0; + } + } + + for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8); + + e = (e << mLen) | m; + eLen += mLen; + for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8); + + buffer[offset + i - d] |= s * 128; +}; + +},{}],20:[function(_dereq_,module,exports){ + +/** + * isArray + */ + +var isArray = Array.isArray; + +/** + * toString + */ + +var str = Object.prototype.toString; + +/** + * Whether or not the given `val` + * is an array. + * + * example: + * + * isArray([]); + * // > true + * isArray(arguments); + * // > false + * isArray(''); + * // > false + * + * @param {mixed} val + * @return {bool} + */ + +module.exports = isArray || function (val) { + return !! val && '[object Array]' == str.call(val); +}; + +},{}],21:[function(_dereq_,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +function EventEmitter() { + this._events = this._events || {}; + this._maxListeners = this._maxListeners || undefined; +} +module.exports = EventEmitter; + +// Backwards-compat with node 0.10.x +EventEmitter.EventEmitter = EventEmitter; + +EventEmitter.prototype._events = undefined; +EventEmitter.prototype._maxListeners = undefined; + +// By default EventEmitters will print a warning if more than 10 listeners are +// added to it. This is a useful default which helps finding memory leaks. +EventEmitter.defaultMaxListeners = 10; + +// Obviously not all Emitters should be limited to 10. This function allows +// that to be increased. Set to zero for unlimited. +EventEmitter.prototype.setMaxListeners = function(n) { + if (!isNumber(n) || n < 0 || isNaN(n)) + throw TypeError('n must be a positive number'); + this._maxListeners = n; + return this; +}; + +EventEmitter.prototype.emit = function(type) { + var er, handler, len, args, i, listeners; + + if (!this._events) + this._events = {}; + + // If there is no 'error' event listener then throw. + if (type === 'error') { + if (!this._events.error || + (isObject(this._events.error) && !this._events.error.length)) { + er = arguments[1]; + if (er instanceof Error) { + throw er; // Unhandled 'error' event + } + throw TypeError('Uncaught, unspecified "error" event.'); + } + } + + handler = this._events[type]; + + if (isUndefined(handler)) + return false; + + if (isFunction(handler)) { + switch (arguments.length) { + // fast cases + case 1: + handler.call(this); + break; + case 2: + handler.call(this, arguments[1]); + break; + case 3: + handler.call(this, arguments[1], arguments[2]); + break; + // slower + default: + len = arguments.length; + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + handler.apply(this, args); + } + } else if (isObject(handler)) { + len = arguments.length; + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + + listeners = handler.slice(); + len = listeners.length; + for (i = 0; i < len; i++) + listeners[i].apply(this, args); + } + + return true; +}; + +EventEmitter.prototype.addListener = function(type, listener) { + var m; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events) + this._events = {}; + + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (this._events.newListener) + this.emit('newListener', type, + isFunction(listener.listener) ? + listener.listener : listener); + + if (!this._events[type]) + // Optimize the case of one listener. Don't need the extra array object. + this._events[type] = listener; + else if (isObject(this._events[type])) + // If we've already got an array, just append. + this._events[type].push(listener); + else + // Adding the second element, need to change to array. + this._events[type] = [this._events[type], listener]; + + // Check for listener leak + if (isObject(this._events[type]) && !this._events[type].warned) { + var m; + if (!isUndefined(this._maxListeners)) { + m = this._maxListeners; + } else { + m = EventEmitter.defaultMaxListeners; + } + + if (m && m > 0 && this._events[type].length > m) { + this._events[type].warned = true; + console.error('(node) warning: possible EventEmitter memory ' + + 'leak detected. %d listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.', + this._events[type].length); + if (typeof console.trace === 'function') { + // not supported in IE 10 + console.trace(); + } + } + } + + return this; +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.once = function(type, listener) { + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + var fired = false; + + function g() { + this.removeListener(type, g); + + if (!fired) { + fired = true; + listener.apply(this, arguments); + } + } + + g.listener = listener; + this.on(type, g); + + return this; +}; + +// emits a 'removeListener' event iff the listener was removed +EventEmitter.prototype.removeListener = function(type, listener) { + var list, position, length, i; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events || !this._events[type]) + return this; + + list = this._events[type]; + length = list.length; + position = -1; + + if (list === listener || + (isFunction(list.listener) && list.listener === listener)) { + delete this._events[type]; + if (this._events.removeListener) + this.emit('removeListener', type, listener); + + } else if (isObject(list)) { + for (i = length; i-- > 0;) { + if (list[i] === listener || + (list[i].listener && list[i].listener === listener)) { + position = i; + break; + } + } + + if (position < 0) + return this; + + if (list.length === 1) { + list.length = 0; + delete this._events[type]; + } else { + list.splice(position, 1); + } + + if (this._events.removeListener) + this.emit('removeListener', type, listener); + } + + return this; +}; + +EventEmitter.prototype.removeAllListeners = function(type) { + var key, listeners; + + if (!this._events) + return this; + + // not listening for removeListener, no need to emit + if (!this._events.removeListener) { + if (arguments.length === 0) + this._events = {}; + else if (this._events[type]) + delete this._events[type]; + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + for (key in this._events) { + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = {}; + return this; + } + + listeners = this._events[type]; + + if (isFunction(listeners)) { + this.removeListener(type, listeners); + } else { + // LIFO order + while (listeners.length) + this.removeListener(type, listeners[listeners.length - 1]); + } + delete this._events[type]; + + return this; +}; + +EventEmitter.prototype.listeners = function(type) { + var ret; + if (!this._events || !this._events[type]) + ret = []; + else if (isFunction(this._events[type])) + ret = [this._events[type]]; + else + ret = this._events[type].slice(); + return ret; +}; + +EventEmitter.listenerCount = function(emitter, type) { + var ret; + if (!emitter._events || !emitter._events[type]) + ret = 0; + else if (isFunction(emitter._events[type])) + ret = 1; + else + ret = emitter._events[type].length; + return ret; +}; + +function isFunction(arg) { + return typeof arg === 'function'; +} + +function isNumber(arg) { + return typeof arg === 'number'; +} + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} + +function isUndefined(arg) { + return arg === void 0; +} + +},{}],22:[function(_dereq_,module,exports){ +module.exports = Array.isArray || function (arr) { + return Object.prototype.toString.call(arr) == '[object Array]'; +}; + +},{}],23:[function(_dereq_,module,exports){ +(function (process){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// resolves . and .. elements in a path array with directory names there +// must be no slashes, empty elements, or device names (c:\) in the array +// (so also no leading and trailing slashes - it does not distinguish +// relative and absolute paths) +function normalizeArray(parts, allowAboveRoot) { + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = parts.length - 1; i >= 0; i--) { + var last = parts[i]; + if (last === '.') { + parts.splice(i, 1); + } else if (last === '..') { + parts.splice(i, 1); + up++; + } else if (up) { + parts.splice(i, 1); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up--; up) { + parts.unshift('..'); + } + } + + return parts; +} + +// Split a filename into [root, dir, basename, ext], unix version +// 'root' is just a slash, or nothing. +var splitPathRe = + /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; +var splitPath = function(filename) { + return splitPathRe.exec(filename).slice(1); +}; + +// path.resolve([from ...], to) +// posix version +exports.resolve = function() { + var resolvedPath = '', + resolvedAbsolute = false; + + for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) ? arguments[i] : process.cwd(); + + // Skip empty and invalid entries + if (typeof path !== 'string') { + throw new TypeError('Arguments to path.resolve must be strings'); + } else if (!path) { + continue; + } + + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = path.charAt(0) === '/'; + } + + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) + + // Normalize the path + resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { + return !!p; + }), !resolvedAbsolute).join('/'); + + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; +}; + +// path.normalize(path) +// posix version +exports.normalize = function(path) { + var isAbsolute = exports.isAbsolute(path), + trailingSlash = substr(path, -1) === '/'; + + // Normalize the path + path = normalizeArray(filter(path.split('/'), function(p) { + return !!p; + }), !isAbsolute).join('/'); + + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + + return (isAbsolute ? '/' : '') + path; +}; + +// posix version +exports.isAbsolute = function(path) { + return path.charAt(0) === '/'; +}; + +// posix version +exports.join = function() { + var paths = Array.prototype.slice.call(arguments, 0); + return exports.normalize(filter(paths, function(p, index) { + if (typeof p !== 'string') { + throw new TypeError('Arguments to path.join must be strings'); + } + return p; + }).join('/')); +}; + + +// path.relative(from, to) +// posix version +exports.relative = function(from, to) { + from = exports.resolve(from).substr(1); + to = exports.resolve(to).substr(1); + + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + + var end = arr.length - 1; + for (; end >= 0; end--) { + if (arr[end] !== '') break; + } + + if (start > end) return []; + return arr.slice(start, end - start + 1); + } + + var fromParts = trim(from.split('/')); + var toParts = trim(to.split('/')); + + var length = Math.min(fromParts.length, toParts.length); + var samePartsLength = length; + for (var i = 0; i < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i; + break; + } + } + + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); + } + + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + + return outputParts.join('/'); +}; + +exports.sep = '/'; +exports.delimiter = ':'; + +exports.dirname = function(path) { + var result = splitPath(path), + root = result[0], + dir = result[1]; + + if (!root && !dir) { + // No dirname whatsoever + return '.'; + } + + if (dir) { + // It has a dirname, strip trailing slash + dir = dir.substr(0, dir.length - 1); + } + + return root + dir; +}; + + +exports.basename = function(path, ext) { + var f = splitPath(path)[2]; + // TODO: make this comparison case-insensitive on windows? + if (ext && f.substr(-1 * ext.length) === ext) { + f = f.substr(0, f.length - ext.length); + } + return f; +}; + + +exports.extname = function(path) { + return splitPath(path)[3]; +}; + +function filter (xs, f) { + if (xs.filter) return xs.filter(f); + var res = []; + for (var i = 0; i < xs.length; i++) { + if (f(xs[i], i, xs)) res.push(xs[i]); + } + return res; +} + +// String.prototype.substr - negative index don't work in IE8 +var substr = 'ab'.substr(-1) === 'b' + ? function (str, start, len) { return str.substr(start, len) } + : function (str, start, len) { + if (start < 0) start = str.length + start; + return str.substr(start, len); + } +; + +}).call(this,_dereq_('_process')) +},{"_process":24}],24:[function(_dereq_,module,exports){ +// shim for using process in browser + +var process = module.exports = {}; + +process.nextTick = (function () { + var canSetImmediate = typeof window !== 'undefined' + && window.setImmediate; + var canMutationObserver = typeof window !== 'undefined' + && window.MutationObserver; + var canPost = typeof window !== 'undefined' + && window.postMessage && window.addEventListener + ; + + if (canSetImmediate) { + return function (f) { return window.setImmediate(f) }; + } + + var queue = []; + + if (canMutationObserver) { + var hiddenDiv = document.createElement("div"); + var observer = new MutationObserver(function () { + var queueList = queue.slice(); + queue.length = 0; + queueList.forEach(function (fn) { + fn(); + }); + }); + + observer.observe(hiddenDiv, { attributes: true }); + + return function nextTick(fn) { + if (!queue.length) { + hiddenDiv.setAttribute('yes', 'no'); + } + queue.push(fn); + }; + } + + if (canPost) { + window.addEventListener('message', function (ev) { + var source = ev.source; + if ((source === window || source === null) && ev.data === 'process-tick') { + ev.stopPropagation(); + if (queue.length > 0) { + var fn = queue.shift(); + fn(); + } + } + }, true); + + return function nextTick(fn) { + queue.push(fn); + window.postMessage('process-tick', '*'); + }; + } + + return function nextTick(fn) { + setTimeout(fn, 0); + }; +})(); + +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +// TODO(shtylman) +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; + +},{}],25:[function(_dereq_,module,exports){ +module.exports = _dereq_("./lib/_stream_duplex.js") + +},{"./lib/_stream_duplex.js":26}],26:[function(_dereq_,module,exports){ +(function (process){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a duplex stream is just a stream that is both readable and writable. +// Since JS doesn't have multiple prototypal inheritance, this class +// prototypally inherits from Readable, and then parasitically from +// Writable. + +module.exports = Duplex; + +/*<replacement>*/ +var objectKeys = Object.keys || function (obj) { + var keys = []; + for (var key in obj) keys.push(key); + return keys; +} +/*</replacement>*/ + + +/*<replacement>*/ +var util = _dereq_('core-util-is'); +util.inherits = _dereq_('inherits'); +/*</replacement>*/ + +var Readable = _dereq_('./_stream_readable'); +var Writable = _dereq_('./_stream_writable'); + +util.inherits(Duplex, Readable); + +forEach(objectKeys(Writable.prototype), function(method) { + if (!Duplex.prototype[method]) + Duplex.prototype[method] = Writable.prototype[method]; +}); + +function Duplex(options) { + if (!(this instanceof Duplex)) + return new Duplex(options); + + Readable.call(this, options); + Writable.call(this, options); + + if (options && options.readable === false) + this.readable = false; + + if (options && options.writable === false) + this.writable = false; + + this.allowHalfOpen = true; + if (options && options.allowHalfOpen === false) + this.allowHalfOpen = false; + + this.once('end', onend); +} + +// the no-half-open enforcer +function onend() { + // if we allow half-open state, or if the writable side ended, + // then we're ok. + if (this.allowHalfOpen || this._writableState.ended) + return; + + // no more data can be written. + // But allow more writes to happen in this tick. + process.nextTick(this.end.bind(this)); +} + +function forEach (xs, f) { + for (var i = 0, l = xs.length; i < l; i++) { + f(xs[i], i); + } +} + +}).call(this,_dereq_('_process')) +},{"./_stream_readable":28,"./_stream_writable":30,"_process":24,"core-util-is":31,"inherits":44}],27:[function(_dereq_,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a passthrough stream. +// basically just the most minimal sort of Transform stream. +// Every written chunk gets output as-is. + +module.exports = PassThrough; + +var Transform = _dereq_('./_stream_transform'); + +/*<replacement>*/ +var util = _dereq_('core-util-is'); +util.inherits = _dereq_('inherits'); +/*</replacement>*/ + +util.inherits(PassThrough, Transform); + +function PassThrough(options) { + if (!(this instanceof PassThrough)) + return new PassThrough(options); + + Transform.call(this, options); +} + +PassThrough.prototype._transform = function(chunk, encoding, cb) { + cb(null, chunk); +}; + +},{"./_stream_transform":29,"core-util-is":31,"inherits":44}],28:[function(_dereq_,module,exports){ +(function (process){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +module.exports = Readable; + +/*<replacement>*/ +var isArray = _dereq_('isarray'); +/*</replacement>*/ + + +/*<replacement>*/ +var Buffer = _dereq_('buffer').Buffer; +/*</replacement>*/ + +Readable.ReadableState = ReadableState; + +var EE = _dereq_('events').EventEmitter; + +/*<replacement>*/ +if (!EE.listenerCount) EE.listenerCount = function(emitter, type) { + return emitter.listeners(type).length; +}; +/*</replacement>*/ + +var Stream = _dereq_('stream'); + +/*<replacement>*/ +var util = _dereq_('core-util-is'); +util.inherits = _dereq_('inherits'); +/*</replacement>*/ + +var StringDecoder; + +util.inherits(Readable, Stream); + +function ReadableState(options, stream) { + options = options || {}; + + // the point at which it stops calling _read() to fill the buffer + // Note: 0 is a valid value, means "don't call _read preemptively ever" + var hwm = options.highWaterMark; + this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024; + + // cast to ints. + this.highWaterMark = ~~this.highWaterMark; + + this.buffer = []; + this.length = 0; + this.pipes = null; + this.pipesCount = 0; + this.flowing = false; + this.ended = false; + this.endEmitted = false; + this.reading = false; + + // In streams that never have any data, and do push(null) right away, + // the consumer can miss the 'end' event if they do some I/O before + // consuming the stream. So, we don't emit('end') until some reading + // happens. + this.calledRead = false; + + // a flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, becuase any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. + this.sync = true; + + // whenever we return null, then we set a flag to say + // that we're awaiting a 'readable' event emission. + this.needReadable = false; + this.emittedReadable = false; + this.readableListening = false; + + + // object stream flag. Used to make read(n) ignore n and to + // make all the buffer merging and length checks go away + this.objectMode = !!options.objectMode; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // when piping, we only care about 'readable' events that happen + // after read()ing all the bytes and not getting any pushback. + this.ranOut = false; + + // the number of writers that are awaiting a drain event in .pipe()s + this.awaitDrain = 0; + + // if true, a maybeReadMore has been scheduled + this.readingMore = false; + + this.decoder = null; + this.encoding = null; + if (options.encoding) { + if (!StringDecoder) + StringDecoder = _dereq_('string_decoder/').StringDecoder; + this.decoder = new StringDecoder(options.encoding); + this.encoding = options.encoding; + } +} + +function Readable(options) { + if (!(this instanceof Readable)) + return new Readable(options); + + this._readableState = new ReadableState(options, this); + + // legacy + this.readable = true; + + Stream.call(this); +} + +// Manually shove something into the read() buffer. +// This returns true if the highWaterMark has not been hit yet, +// similar to how Writable.write() returns true if you should +// write() some more. +Readable.prototype.push = function(chunk, encoding) { + var state = this._readableState; + + if (typeof chunk === 'string' && !state.objectMode) { + encoding = encoding || state.defaultEncoding; + if (encoding !== state.encoding) { + chunk = new Buffer(chunk, encoding); + encoding = ''; + } + } + + return readableAddChunk(this, state, chunk, encoding, false); +}; + +// Unshift should *always* be something directly out of read() +Readable.prototype.unshift = function(chunk) { + var state = this._readableState; + return readableAddChunk(this, state, chunk, '', true); +}; + +function readableAddChunk(stream, state, chunk, encoding, addToFront) { + var er = chunkInvalid(state, chunk); + if (er) { + stream.emit('error', er); + } else if (chunk === null || chunk === undefined) { + state.reading = false; + if (!state.ended) + onEofChunk(stream, state); + } else if (state.objectMode || chunk && chunk.length > 0) { + if (state.ended && !addToFront) { + var e = new Error('stream.push() after EOF'); + stream.emit('error', e); + } else if (state.endEmitted && addToFront) { + var e = new Error('stream.unshift() after end event'); + stream.emit('error', e); + } else { + if (state.decoder && !addToFront && !encoding) + chunk = state.decoder.write(chunk); + + // update the buffer info. + state.length += state.objectMode ? 1 : chunk.length; + if (addToFront) { + state.buffer.unshift(chunk); + } else { + state.reading = false; + state.buffer.push(chunk); + } + + if (state.needReadable) + emitReadable(stream); + + maybeReadMore(stream, state); + } + } else if (!addToFront) { + state.reading = false; + } + + return needMoreData(state); +} + + + +// if it's past the high water mark, we can push in some more. +// Also, if we have no data yet, we can stand some +// more bytes. This is to work around cases where hwm=0, +// such as the repl. Also, if the push() triggered a +// readable event, and the user called read(largeNumber) such that +// needReadable was set, then we ought to push more, so that another +// 'readable' event will be triggered. +function needMoreData(state) { + return !state.ended && + (state.needReadable || + state.length < state.highWaterMark || + state.length === 0); +} + +// backwards compatibility. +Readable.prototype.setEncoding = function(enc) { + if (!StringDecoder) + StringDecoder = _dereq_('string_decoder/').StringDecoder; + this._readableState.decoder = new StringDecoder(enc); + this._readableState.encoding = enc; +}; + +// Don't raise the hwm > 128MB +var MAX_HWM = 0x800000; +function roundUpToNextPowerOf2(n) { + if (n >= MAX_HWM) { + n = MAX_HWM; + } else { + // Get the next highest power of 2 + n--; + for (var p = 1; p < 32; p <<= 1) n |= n >> p; + n++; + } + return n; +} + +function howMuchToRead(n, state) { + if (state.length === 0 && state.ended) + return 0; + + if (state.objectMode) + return n === 0 ? 0 : 1; + + if (n === null || isNaN(n)) { + // only flow one buffer at a time + if (state.flowing && state.buffer.length) + return state.buffer[0].length; + else + return state.length; + } + + if (n <= 0) + return 0; + + // If we're asking for more than the target buffer level, + // then raise the water mark. Bump up to the next highest + // power of 2, to prevent increasing it excessively in tiny + // amounts. + if (n > state.highWaterMark) + state.highWaterMark = roundUpToNextPowerOf2(n); + + // don't have that much. return null, unless we've ended. + if (n > state.length) { + if (!state.ended) { + state.needReadable = true; + return 0; + } else + return state.length; + } + + return n; +} + +// you can override either this method, or the async _read(n) below. +Readable.prototype.read = function(n) { + var state = this._readableState; + state.calledRead = true; + var nOrig = n; + var ret; + + if (typeof n !== 'number' || n > 0) + state.emittedReadable = false; + + // if we're doing read(0) to trigger a readable event, but we + // already have a bunch of data in the buffer, then just trigger + // the 'readable' event and move on. + if (n === 0 && + state.needReadable && + (state.length >= state.highWaterMark || state.ended)) { + emitReadable(this); + return null; + } + + n = howMuchToRead(n, state); + + // if we've ended, and we're now clear, then finish it up. + if (n === 0 && state.ended) { + ret = null; + + // In cases where the decoder did not receive enough data + // to produce a full chunk, then immediately received an + // EOF, state.buffer will contain [<Buffer >, <Buffer 00 ...>]. + // howMuchToRead will see this and coerce the amount to + // read to zero (because it's looking at the length of the + // first <Buffer > in state.buffer), and we'll end up here. + // + // This can only happen via state.decoder -- no other venue + // exists for pushing a zero-length chunk into state.buffer + // and triggering this behavior. In this case, we return our + // remaining data and end the stream, if appropriate. + if (state.length > 0 && state.decoder) { + ret = fromList(n, state); + state.length -= ret.length; + } + + if (state.length === 0) + endReadable(this); + + return ret; + } + + // All the actual chunk generation logic needs to be + // *below* the call to _read. The reason is that in certain + // synthetic stream cases, such as passthrough streams, _read + // may be a completely synchronous operation which may change + // the state of the read buffer, providing enough data when + // before there was *not* enough. + // + // So, the steps are: + // 1. Figure out what the state of things will be after we do + // a read from the buffer. + // + // 2. If that resulting state will trigger a _read, then call _read. + // Note that this may be asynchronous, or synchronous. Yes, it is + // deeply ugly to write APIs this way, but that still doesn't mean + // that the Readable class should behave improperly, as streams are + // designed to be sync/async agnostic. + // Take note if the _read call is sync or async (ie, if the read call + // has returned yet), so that we know whether or not it's safe to emit + // 'readable' etc. + // + // 3. Actually pull the requested chunks out of the buffer and return. + + // if we need a readable event, then we need to do some reading. + var doRead = state.needReadable; + + // if we currently have less than the highWaterMark, then also read some + if (state.length - n <= state.highWaterMark) + doRead = true; + + // however, if we've ended, then there's no point, and if we're already + // reading, then it's unnecessary. + if (state.ended || state.reading) + doRead = false; + + if (doRead) { + state.reading = true; + state.sync = true; + // if the length is currently zero, then we *need* a readable event. + if (state.length === 0) + state.needReadable = true; + // call internal read method + this._read(state.highWaterMark); + state.sync = false; + } + + // If _read called its callback synchronously, then `reading` + // will be false, and we need to re-evaluate how much data we + // can return to the user. + if (doRead && !state.reading) + n = howMuchToRead(nOrig, state); + + if (n > 0) + ret = fromList(n, state); + else + ret = null; + + if (ret === null) { + state.needReadable = true; + n = 0; + } + + state.length -= n; + + // If we have nothing in the buffer, then we want to know + // as soon as we *do* get something into the buffer. + if (state.length === 0 && !state.ended) + state.needReadable = true; + + // If we happened to read() exactly the remaining amount in the + // buffer, and the EOF has been seen at this point, then make sure + // that we emit 'end' on the very next tick. + if (state.ended && !state.endEmitted && state.length === 0) + endReadable(this); + + return ret; +}; + +function chunkInvalid(state, chunk) { + var er = null; + if (!Buffer.isBuffer(chunk) && + 'string' !== typeof chunk && + chunk !== null && + chunk !== undefined && + !state.objectMode) { + er = new TypeError('Invalid non-string/buffer chunk'); + } + return er; +} + + +function onEofChunk(stream, state) { + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) { + state.buffer.push(chunk); + state.length += state.objectMode ? 1 : chunk.length; + } + } + state.ended = true; + + // if we've ended and we have some data left, then emit + // 'readable' now to make sure it gets picked up. + if (state.length > 0) + emitReadable(stream); + else + endReadable(stream); +} + +// Don't emit readable right away in sync mode, because this can trigger +// another read() call => stack overflow. This way, it might trigger +// a nextTick recursion warning, but that's not so bad. +function emitReadable(stream) { + var state = stream._readableState; + state.needReadable = false; + if (state.emittedReadable) + return; + + state.emittedReadable = true; + if (state.sync) + process.nextTick(function() { + emitReadable_(stream); + }); + else + emitReadable_(stream); +} + +function emitReadable_(stream) { + stream.emit('readable'); +} + + +// at this point, the user has presumably seen the 'readable' event, +// and called read() to consume some data. that may have triggered +// in turn another _read(n) call, in which case reading = true if +// it's in progress. +// However, if we're not ended, or reading, and the length < hwm, +// then go ahead and try to read some more preemptively. +function maybeReadMore(stream, state) { + if (!state.readingMore) { + state.readingMore = true; + process.nextTick(function() { + maybeReadMore_(stream, state); + }); + } +} + +function maybeReadMore_(stream, state) { + var len = state.length; + while (!state.reading && !state.flowing && !state.ended && + state.length < state.highWaterMark) { + stream.read(0); + if (len === state.length) + // didn't get any data, stop spinning. + break; + else + len = state.length; + } + state.readingMore = false; +} + +// abstract method. to be overridden in specific implementation classes. +// call cb(er, data) where data is <= n in length. +// for virtual (non-string, non-buffer) streams, "length" is somewhat +// arbitrary, and perhaps not very meaningful. +Readable.prototype._read = function(n) { + this.emit('error', new Error('not implemented')); +}; + +Readable.prototype.pipe = function(dest, pipeOpts) { + var src = this; + var state = this._readableState; + + switch (state.pipesCount) { + case 0: + state.pipes = dest; + break; + case 1: + state.pipes = [state.pipes, dest]; + break; + default: + state.pipes.push(dest); + break; + } + state.pipesCount += 1; + + var doEnd = (!pipeOpts || pipeOpts.end !== false) && + dest !== process.stdout && + dest !== process.stderr; + + var endFn = doEnd ? onend : cleanup; + if (state.endEmitted) + process.nextTick(endFn); + else + src.once('end', endFn); + + dest.on('unpipe', onunpipe); + function onunpipe(readable) { + if (readable !== src) return; + cleanup(); + } + + function onend() { + dest.end(); + } + + // when the dest drains, it reduces the awaitDrain counter + // on the source. This would be more elegant with a .once() + // handler in flow(), but adding and removing repeatedly is + // too slow. + var ondrain = pipeOnDrain(src); + dest.on('drain', ondrain); + + function cleanup() { + // cleanup event handlers once the pipe is broken + dest.removeListener('close', onclose); + dest.removeListener('finish', onfinish); + dest.removeListener('drain', ondrain); + dest.removeListener('error', onerror); + dest.removeListener('unpipe', onunpipe); + src.removeListener('end', onend); + src.removeListener('end', cleanup); + + // if the reader is waiting for a drain event from this + // specific writer, then it would cause it to never start + // flowing again. + // So, if this is awaiting a drain, then we just call it now. + // If we don't know, then assume that we are waiting for one. + if (!dest._writableState || dest._writableState.needDrain) + ondrain(); + } + + // if the dest has an error, then stop piping into it. + // however, don't suppress the throwing behavior for this. + function onerror(er) { + unpipe(); + dest.removeListener('error', onerror); + if (EE.listenerCount(dest, 'error') === 0) + dest.emit('error', er); + } + // This is a brutally ugly hack to make sure that our error handler + // is attached before any userland ones. NEVER DO THIS. + if (!dest._events || !dest._events.error) + dest.on('error', onerror); + else if (isArray(dest._events.error)) + dest._events.error.unshift(onerror); + else + dest._events.error = [onerror, dest._events.error]; + + + + // Both close and finish should trigger unpipe, but only once. + function onclose() { + dest.removeListener('finish', onfinish); + unpipe(); + } + dest.once('close', onclose); + function onfinish() { + dest.removeListener('close', onclose); + unpipe(); + } + dest.once('finish', onfinish); + + function unpipe() { + src.unpipe(dest); + } + + // tell the dest that it's being piped to + dest.emit('pipe', src); + + // start the flow if it hasn't been started already. + if (!state.flowing) { + // the handler that waits for readable events after all + // the data gets sucked out in flow. + // This would be easier to follow with a .once() handler + // in flow(), but that is too slow. + this.on('readable', pipeOnReadable); + + state.flowing = true; + process.nextTick(function() { + flow(src); + }); + } + + return dest; +}; + +function pipeOnDrain(src) { + return function() { + var dest = this; + var state = src._readableState; + state.awaitDrain--; + if (state.awaitDrain === 0) + flow(src); + }; +} + +function flow(src) { + var state = src._readableState; + var chunk; + state.awaitDrain = 0; + + function write(dest, i, list) { + var written = dest.write(chunk); + if (false === written) { + state.awaitDrain++; + } + } + + while (state.pipesCount && null !== (chunk = src.read())) { + + if (state.pipesCount === 1) + write(state.pipes, 0, null); + else + forEach(state.pipes, write); + + src.emit('data', chunk); + + // if anyone needs a drain, then we have to wait for that. + if (state.awaitDrain > 0) + return; + } + + // if every destination was unpiped, either before entering this + // function, or in the while loop, then stop flowing. + // + // NB: This is a pretty rare edge case. + if (state.pipesCount === 0) { + state.flowing = false; + + // if there were data event listeners added, then switch to old mode. + if (EE.listenerCount(src, 'data') > 0) + emitDataEvents(src); + return; + } + + // at this point, no one needed a drain, so we just ran out of data + // on the next readable event, start it over again. + state.ranOut = true; +} + +function pipeOnReadable() { + if (this._readableState.ranOut) { + this._readableState.ranOut = false; + flow(this); + } +} + + +Readable.prototype.unpipe = function(dest) { + var state = this._readableState; + + // if we're not piping anywhere, then do nothing. + if (state.pipesCount === 0) + return this; + + // just one destination. most common case. + if (state.pipesCount === 1) { + // passed in one, but it's not the right one. + if (dest && dest !== state.pipes) + return this; + + if (!dest) + dest = state.pipes; + + // got a match. + state.pipes = null; + state.pipesCount = 0; + this.removeListener('readable', pipeOnReadable); + state.flowing = false; + if (dest) + dest.emit('unpipe', this); + return this; + } + + // slow case. multiple pipe destinations. + + if (!dest) { + // remove all. + var dests = state.pipes; + var len = state.pipesCount; + state.pipes = null; + state.pipesCount = 0; + this.removeListener('readable', pipeOnReadable); + state.flowing = false; + + for (var i = 0; i < len; i++) + dests[i].emit('unpipe', this); + return this; + } + + // try to find the right one. + var i = indexOf(state.pipes, dest); + if (i === -1) + return this; + + state.pipes.splice(i, 1); + state.pipesCount -= 1; + if (state.pipesCount === 1) + state.pipes = state.pipes[0]; + + dest.emit('unpipe', this); + + return this; +}; + +// set up data events if they are asked for +// Ensure readable listeners eventually get something +Readable.prototype.on = function(ev, fn) { + var res = Stream.prototype.on.call(this, ev, fn); + + if (ev === 'data' && !this._readableState.flowing) + emitDataEvents(this); + + if (ev === 'readable' && this.readable) { + var state = this._readableState; + if (!state.readableListening) { + state.readableListening = true; + state.emittedReadable = false; + state.needReadable = true; + if (!state.reading) { + this.read(0); + } else if (state.length) { + emitReadable(this, state); + } + } + } + + return res; +}; +Readable.prototype.addListener = Readable.prototype.on; + +// pause() and resume() are remnants of the legacy readable stream API +// If the user uses them, then switch into old mode. +Readable.prototype.resume = function() { + emitDataEvents(this); + this.read(0); + this.emit('resume'); +}; + +Readable.prototype.pause = function() { + emitDataEvents(this, true); + this.emit('pause'); +}; + +function emitDataEvents(stream, startPaused) { + var state = stream._readableState; + + if (state.flowing) { + // https://github.com/isaacs/readable-stream/issues/16 + throw new Error('Cannot switch to old mode now.'); + } + + var paused = startPaused || false; + var readable = false; + + // convert to an old-style stream. + stream.readable = true; + stream.pipe = Stream.prototype.pipe; + stream.on = stream.addListener = Stream.prototype.on; + + stream.on('readable', function() { + readable = true; + + var c; + while (!paused && (null !== (c = stream.read()))) + stream.emit('data', c); + + if (c === null) { + readable = false; + stream._readableState.needReadable = true; + } + }); + + stream.pause = function() { + paused = true; + this.emit('pause'); + }; + + stream.resume = function() { + paused = false; + if (readable) + process.nextTick(function() { + stream.emit('readable'); + }); + else + this.read(0); + this.emit('resume'); + }; + + // now make it start, just in case it hadn't already. + stream.emit('readable'); +} + +// wrap an old-style stream as the async data source. +// This is *not* part of the readable stream interface. +// It is an ugly unfortunate mess of history. +Readable.prototype.wrap = function(stream) { + var state = this._readableState; + var paused = false; + + var self = this; + stream.on('end', function() { + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) + self.push(chunk); + } + + self.push(null); + }); + + stream.on('data', function(chunk) { + if (state.decoder) + chunk = state.decoder.write(chunk); + + // don't skip over falsy values in objectMode + //if (state.objectMode && util.isNullOrUndefined(chunk)) + if (state.objectMode && (chunk === null || chunk === undefined)) + return; + else if (!state.objectMode && (!chunk || !chunk.length)) + return; + + var ret = self.push(chunk); + if (!ret) { + paused = true; + stream.pause(); + } + }); + + // proxy all the other methods. + // important when wrapping filters and duplexes. + for (var i in stream) { + if (typeof stream[i] === 'function' && + typeof this[i] === 'undefined') { + this[i] = function(method) { return function() { + return stream[method].apply(stream, arguments); + }}(i); + } + } + + // proxy certain important events. + var events = ['error', 'close', 'destroy', 'pause', 'resume']; + forEach(events, function(ev) { + stream.on(ev, self.emit.bind(self, ev)); + }); + + // when we try to consume some more bytes, simply unpause the + // underlying stream. + self._read = function(n) { + if (paused) { + paused = false; + stream.resume(); + } + }; + + return self; +}; + + + +// exposed for testing purposes only. +Readable._fromList = fromList; + +// Pluck off n bytes from an array of buffers. +// Length is the combined lengths of all the buffers in the list. +function fromList(n, state) { + var list = state.buffer; + var length = state.length; + var stringMode = !!state.decoder; + var objectMode = !!state.objectMode; + var ret; + + // nothing in the list, definitely empty. + if (list.length === 0) + return null; + + if (length === 0) + ret = null; + else if (objectMode) + ret = list.shift(); + else if (!n || n >= length) { + // read it all, truncate the array. + if (stringMode) + ret = list.join(''); + else + ret = Buffer.concat(list, length); + list.length = 0; + } else { + // read just some of it. + if (n < list[0].length) { + // just take a part of the first list item. + // slice is the same for buffers and strings. + var buf = list[0]; + ret = buf.slice(0, n); + list[0] = buf.slice(n); + } else if (n === list[0].length) { + // first list is a perfect match + ret = list.shift(); + } else { + // complex case. + // we have enough to cover it, but it spans past the first buffer. + if (stringMode) + ret = ''; + else + ret = new Buffer(n); + + var c = 0; + for (var i = 0, l = list.length; i < l && c < n; i++) { + var buf = list[0]; + var cpy = Math.min(n - c, buf.length); + + if (stringMode) + ret += buf.slice(0, cpy); + else + buf.copy(ret, c, 0, cpy); + + if (cpy < buf.length) + list[0] = buf.slice(cpy); + else + list.shift(); + + c += cpy; + } + } + } + + return ret; +} + +function endReadable(stream) { + var state = stream._readableState; + + // If we get here before consuming all the bytes, then that is a + // bug in node. Should never happen. + if (state.length > 0) + throw new Error('endReadable called on non-empty stream'); + + if (!state.endEmitted && state.calledRead) { + state.ended = true; + process.nextTick(function() { + // Check that we didn't get one last unshift. + if (!state.endEmitted && state.length === 0) { + state.endEmitted = true; + stream.readable = false; + stream.emit('end'); + } + }); + } +} + +function forEach (xs, f) { + for (var i = 0, l = xs.length; i < l; i++) { + f(xs[i], i); + } +} + +function indexOf (xs, x) { + for (var i = 0, l = xs.length; i < l; i++) { + if (xs[i] === x) return i; + } + return -1; +} + +}).call(this,_dereq_('_process')) +},{"_process":24,"buffer":17,"core-util-is":31,"events":21,"inherits":44,"isarray":22,"stream":36,"string_decoder/":37}],29:[function(_dereq_,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + +// a transform stream is a readable/writable stream where you do +// something with the data. Sometimes it's called a "filter", +// but that's not a great name for it, since that implies a thing where +// some bits pass through, and others are simply ignored. (That would +// be a valid example of a transform, of course.) +// +// While the output is causally related to the input, it's not a +// necessarily symmetric or synchronous transformation. For example, +// a zlib stream might take multiple plain-text writes(), and then +// emit a single compressed chunk some time in the future. +// +// Here's how this works: +// +// The Transform stream has all the aspects of the readable and writable +// stream classes. When you write(chunk), that calls _write(chunk,cb) +// internally, and returns false if there's a lot of pending writes +// buffered up. When you call read(), that calls _read(n) until +// there's enough pending readable data buffered up. +// +// In a transform stream, the written data is placed in a buffer. When +// _read(n) is called, it transforms the queued up data, calling the +// buffered _write cb's as it consumes chunks. If consuming a single +// written chunk would result in multiple output chunks, then the first +// outputted bit calls the readcb, and subsequent chunks just go into +// the read buffer, and will cause it to emit 'readable' if necessary. +// +// This way, back-pressure is actually determined by the reading side, +// since _read has to be called to start processing a new chunk. However, +// a pathological inflate type of transform can cause excessive buffering +// here. For example, imagine a stream where every byte of input is +// interpreted as an integer from 0-255, and then results in that many +// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in +// 1kb of data being output. In this case, you could write a very small +// amount of input, and end up with a very large amount of output. In +// such a pathological inflating mechanism, there'd be no way to tell +// the system to stop doing the transform. A single 4MB write could +// cause the system to run out of memory. +// +// However, even in such a pathological case, only a single written chunk +// would be consumed, and then the rest would wait (un-transformed) until +// the results of the previous transformed chunk were consumed. + +module.exports = Transform; + +var Duplex = _dereq_('./_stream_duplex'); + +/*<replacement>*/ +var util = _dereq_('core-util-is'); +util.inherits = _dereq_('inherits'); +/*</replacement>*/ + +util.inherits(Transform, Duplex); + + +function TransformState(options, stream) { + this.afterTransform = function(er, data) { + return afterTransform(stream, er, data); + }; + + this.needTransform = false; + this.transforming = false; + this.writecb = null; + this.writechunk = null; +} + +function afterTransform(stream, er, data) { + var ts = stream._transformState; + ts.transforming = false; + + var cb = ts.writecb; + + if (!cb) + return stream.emit('error', new Error('no writecb in Transform class')); + + ts.writechunk = null; + ts.writecb = null; + + if (data !== null && data !== undefined) + stream.push(data); + + if (cb) + cb(er); + + var rs = stream._readableState; + rs.reading = false; + if (rs.needReadable || rs.length < rs.highWaterMark) { + stream._read(rs.highWaterMark); + } +} + + +function Transform(options) { + if (!(this instanceof Transform)) + return new Transform(options); + + Duplex.call(this, options); + + var ts = this._transformState = new TransformState(options, this); + + // when the writable side finishes, then flush out anything remaining. + var stream = this; + + // start out asking for a readable event once data is transformed. + this._readableState.needReadable = true; + + // we have implemented the _read method, and done the other things + // that Readable wants before the first _read call, so unset the + // sync guard flag. + this._readableState.sync = false; + + this.once('finish', function() { + if ('function' === typeof this._flush) + this._flush(function(er) { + done(stream, er); + }); + else + done(stream); + }); +} + +Transform.prototype.push = function(chunk, encoding) { + this._transformState.needTransform = false; + return Duplex.prototype.push.call(this, chunk, encoding); +}; + +// This is the part where you do stuff! +// override this function in implementation classes. +// 'chunk' is an input chunk. +// +// Call `push(newChunk)` to pass along transformed output +// to the readable side. You may call 'push' zero or more times. +// +// Call `cb(err)` when you are done with this chunk. If you pass +// an error, then that'll put the hurt on the whole operation. If you +// never call cb(), then you'll never get another chunk. +Transform.prototype._transform = function(chunk, encoding, cb) { + throw new Error('not implemented'); +}; + +Transform.prototype._write = function(chunk, encoding, cb) { + var ts = this._transformState; + ts.writecb = cb; + ts.writechunk = chunk; + ts.writeencoding = encoding; + if (!ts.transforming) { + var rs = this._readableState; + if (ts.needTransform || + rs.needReadable || + rs.length < rs.highWaterMark) + this._read(rs.highWaterMark); + } +}; + +// Doesn't matter what the args are here. +// _transform does all the work. +// That we got here means that the readable side wants more data. +Transform.prototype._read = function(n) { + var ts = this._transformState; + + if (ts.writechunk !== null && ts.writecb && !ts.transforming) { + ts.transforming = true; + this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); + } else { + // mark that we need a transform, so that any data that comes in + // will get processed, now that we've asked for it. + ts.needTransform = true; + } +}; + + +function done(stream, er) { + if (er) + return stream.emit('error', er); + + // if there's nothing in the write buffer, then that means + // that nothing more will ever be provided + var ws = stream._writableState; + var rs = stream._readableState; + var ts = stream._transformState; + + if (ws.length) + throw new Error('calling transform done when ws.length != 0'); + + if (ts.transforming) + throw new Error('calling transform done when still transforming'); + + return stream.push(null); +} + +},{"./_stream_duplex":26,"core-util-is":31,"inherits":44}],30:[function(_dereq_,module,exports){ +(function (process){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// A bit simpler than readable streams. +// Implement an async ._write(chunk, cb), and it'll handle all +// the drain event emission and buffering. + +module.exports = Writable; + +/*<replacement>*/ +var Buffer = _dereq_('buffer').Buffer; +/*</replacement>*/ + +Writable.WritableState = WritableState; + + +/*<replacement>*/ +var util = _dereq_('core-util-is'); +util.inherits = _dereq_('inherits'); +/*</replacement>*/ + +var Stream = _dereq_('stream'); + +util.inherits(Writable, Stream); + +function WriteReq(chunk, encoding, cb) { + this.chunk = chunk; + this.encoding = encoding; + this.callback = cb; +} + +function WritableState(options, stream) { + options = options || {}; + + // the point at which write() starts returning false + // Note: 0 is a valid value, means that we always return false if + // the entire buffer is not flushed immediately on write() + var hwm = options.highWaterMark; + this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024; + + // object stream flag to indicate whether or not this stream + // contains buffers or objects. + this.objectMode = !!options.objectMode; + + // cast to ints. + this.highWaterMark = ~~this.highWaterMark; + + this.needDrain = false; + // at the start of calling end() + this.ending = false; + // when end() has been called, and returned + this.ended = false; + // when 'finish' is emitted + this.finished = false; + + // should we decode strings into buffers before passing to _write? + // this is here so that some node-core streams can optimize string + // handling at a lower level. + var noDecode = options.decodeStrings === false; + this.decodeStrings = !noDecode; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // not an actual buffer we keep track of, but a measurement + // of how much we're waiting to get pushed to some underlying + // socket or file. + this.length = 0; + + // a flag to see when we're in the middle of a write. + this.writing = false; + + // a flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, becuase any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. + this.sync = true; + + // a flag to know if we're processing previously buffered items, which + // may call the _write() callback in the same tick, so that we don't + // end up in an overlapped onwrite situation. + this.bufferProcessing = false; + + // the callback that's passed to _write(chunk,cb) + this.onwrite = function(er) { + onwrite(stream, er); + }; + + // the callback that the user supplies to write(chunk,encoding,cb) + this.writecb = null; + + // the amount that is being written when _write is called. + this.writelen = 0; + + this.buffer = []; + + // True if the error was already emitted and should not be thrown again + this.errorEmitted = false; +} + +function Writable(options) { + var Duplex = _dereq_('./_stream_duplex'); + + // Writable ctor is applied to Duplexes, though they're not + // instanceof Writable, they're instanceof Readable. + if (!(this instanceof Writable) && !(this instanceof Duplex)) + return new Writable(options); + + this._writableState = new WritableState(options, this); + + // legacy. + this.writable = true; + + Stream.call(this); +} + +// Otherwise people can pipe Writable streams, which is just wrong. +Writable.prototype.pipe = function() { + this.emit('error', new Error('Cannot pipe. Not readable.')); +}; + + +function writeAfterEnd(stream, state, cb) { + var er = new Error('write after end'); + // TODO: defer error events consistently everywhere, not just the cb + stream.emit('error', er); + process.nextTick(function() { + cb(er); + }); +} + +// If we get something that is not a buffer, string, null, or undefined, +// and we're not in objectMode, then that's an error. +// Otherwise stream chunks are all considered to be of length=1, and the +// watermarks determine how many objects to keep in the buffer, rather than +// how many bytes or characters. +function validChunk(stream, state, chunk, cb) { + var valid = true; + if (!Buffer.isBuffer(chunk) && + 'string' !== typeof chunk && + chunk !== null && + chunk !== undefined && + !state.objectMode) { + var er = new TypeError('Invalid non-string/buffer chunk'); + stream.emit('error', er); + process.nextTick(function() { + cb(er); + }); + valid = false; + } + return valid; +} + +Writable.prototype.write = function(chunk, encoding, cb) { + var state = this._writableState; + var ret = false; + + if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (Buffer.isBuffer(chunk)) + encoding = 'buffer'; + else if (!encoding) + encoding = state.defaultEncoding; + + if (typeof cb !== 'function') + cb = function() {}; + + if (state.ended) + writeAfterEnd(this, state, cb); + else if (validChunk(this, state, chunk, cb)) + ret = writeOrBuffer(this, state, chunk, encoding, cb); + + return ret; +}; + +function decodeChunk(state, chunk, encoding) { + if (!state.objectMode && + state.decodeStrings !== false && + typeof chunk === 'string') { + chunk = new Buffer(chunk, encoding); + } + return chunk; +} + +// if we're already writing something, then just put this +// in the queue, and wait our turn. Otherwise, call _write +// If we return false, then we need a drain event, so set that flag. +function writeOrBuffer(stream, state, chunk, encoding, cb) { + chunk = decodeChunk(state, chunk, encoding); + if (Buffer.isBuffer(chunk)) + encoding = 'buffer'; + var len = state.objectMode ? 1 : chunk.length; + + state.length += len; + + var ret = state.length < state.highWaterMark; + // we must ensure that previous needDrain will not be reset to false. + if (!ret) + state.needDrain = true; + + if (state.writing) + state.buffer.push(new WriteReq(chunk, encoding, cb)); + else + doWrite(stream, state, len, chunk, encoding, cb); + + return ret; +} + +function doWrite(stream, state, len, chunk, encoding, cb) { + state.writelen = len; + state.writecb = cb; + state.writing = true; + state.sync = true; + stream._write(chunk, encoding, state.onwrite); + state.sync = false; +} + +function onwriteError(stream, state, sync, er, cb) { + if (sync) + process.nextTick(function() { + cb(er); + }); + else + cb(er); + + stream._writableState.errorEmitted = true; + stream.emit('error', er); +} + +function onwriteStateUpdate(state) { + state.writing = false; + state.writecb = null; + state.length -= state.writelen; + state.writelen = 0; +} + +function onwrite(stream, er) { + var state = stream._writableState; + var sync = state.sync; + var cb = state.writecb; + + onwriteStateUpdate(state); + + if (er) + onwriteError(stream, state, sync, er, cb); + else { + // Check if we're actually ready to finish, but don't emit yet + var finished = needFinish(stream, state); + + if (!finished && !state.bufferProcessing && state.buffer.length) + clearBuffer(stream, state); + + if (sync) { + process.nextTick(function() { + afterWrite(stream, state, finished, cb); + }); + } else { + afterWrite(stream, state, finished, cb); + } + } +} + +function afterWrite(stream, state, finished, cb) { + if (!finished) + onwriteDrain(stream, state); + cb(); + if (finished) + finishMaybe(stream, state); +} + +// Must force callback to be called on nextTick, so that we don't +// emit 'drain' before the write() consumer gets the 'false' return +// value, and has a chance to attach a 'drain' listener. +function onwriteDrain(stream, state) { + if (state.length === 0 && state.needDrain) { + state.needDrain = false; + stream.emit('drain'); + } +} + + +// if there's something in the buffer waiting, then process it +function clearBuffer(stream, state) { + state.bufferProcessing = true; + + for (var c = 0; c < state.buffer.length; c++) { + var entry = state.buffer[c]; + var chunk = entry.chunk; + var encoding = entry.encoding; + var cb = entry.callback; + var len = state.objectMode ? 1 : chunk.length; + + doWrite(stream, state, len, chunk, encoding, cb); + + // if we didn't call the onwrite immediately, then + // it means that we need to wait until it does. + // also, that means that the chunk and cb are currently + // being processed, so move the buffer counter past them. + if (state.writing) { + c++; + break; + } + } + + state.bufferProcessing = false; + if (c < state.buffer.length) + state.buffer = state.buffer.slice(c); + else + state.buffer.length = 0; +} + +Writable.prototype._write = function(chunk, encoding, cb) { + cb(new Error('not implemented')); +}; + +Writable.prototype.end = function(chunk, encoding, cb) { + var state = this._writableState; + + if (typeof chunk === 'function') { + cb = chunk; + chunk = null; + encoding = null; + } else if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (typeof chunk !== 'undefined' && chunk !== null) + this.write(chunk, encoding); + + // ignore unnecessary end() calls. + if (!state.ending && !state.finished) + endWritable(this, state, cb); +}; + + +function needFinish(stream, state) { + return (state.ending && + state.length === 0 && + !state.finished && + !state.writing); +} + +function finishMaybe(stream, state) { + var need = needFinish(stream, state); + if (need) { + state.finished = true; + stream.emit('finish'); + } + return need; +} + +function endWritable(stream, state, cb) { + state.ending = true; + finishMaybe(stream, state); + if (cb) { + if (state.finished) + process.nextTick(cb); + else + stream.once('finish', cb); + } + state.ended = true; +} + +}).call(this,_dereq_('_process')) +},{"./_stream_duplex":26,"_process":24,"buffer":17,"core-util-is":31,"inherits":44,"stream":36}],31:[function(_dereq_,module,exports){ +(function (Buffer){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. +function isArray(ar) { + return Array.isArray(ar); +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return isObject(re) && objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return isObject(d) && objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return isObject(e) && + (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +function isBuffer(arg) { + return Buffer.isBuffer(arg); +} +exports.isBuffer = isBuffer; + +function objectToString(o) { + return Object.prototype.toString.call(o); +} +}).call(this,_dereq_("buffer").Buffer) +},{"buffer":17}],32:[function(_dereq_,module,exports){ +module.exports = _dereq_("./lib/_stream_passthrough.js") + +},{"./lib/_stream_passthrough.js":27}],33:[function(_dereq_,module,exports){ +var Stream = _dereq_('stream'); // hack to fix a circular dependency issue when used with browserify +exports = module.exports = _dereq_('./lib/_stream_readable.js'); +exports.Stream = Stream; +exports.Readable = exports; +exports.Writable = _dereq_('./lib/_stream_writable.js'); +exports.Duplex = _dereq_('./lib/_stream_duplex.js'); +exports.Transform = _dereq_('./lib/_stream_transform.js'); +exports.PassThrough = _dereq_('./lib/_stream_passthrough.js'); + +},{"./lib/_stream_duplex.js":26,"./lib/_stream_passthrough.js":27,"./lib/_stream_readable.js":28,"./lib/_stream_transform.js":29,"./lib/_stream_writable.js":30,"stream":36}],34:[function(_dereq_,module,exports){ +module.exports = _dereq_("./lib/_stream_transform.js") + +},{"./lib/_stream_transform.js":29}],35:[function(_dereq_,module,exports){ +module.exports = _dereq_("./lib/_stream_writable.js") + +},{"./lib/_stream_writable.js":30}],36:[function(_dereq_,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +module.exports = Stream; + +var EE = _dereq_('events').EventEmitter; +var inherits = _dereq_('inherits'); + +inherits(Stream, EE); +Stream.Readable = _dereq_('readable-stream/readable.js'); +Stream.Writable = _dereq_('readable-stream/writable.js'); +Stream.Duplex = _dereq_('readable-stream/duplex.js'); +Stream.Transform = _dereq_('readable-stream/transform.js'); +Stream.PassThrough = _dereq_('readable-stream/passthrough.js'); + +// Backwards-compat with node 0.4.x +Stream.Stream = Stream; + + + +// old-style streams. Note that the pipe method (the only relevant +// part of this class) is overridden in the Readable class. + +function Stream() { + EE.call(this); +} + +Stream.prototype.pipe = function(dest, options) { + var source = this; + + function ondata(chunk) { + if (dest.writable) { + if (false === dest.write(chunk) && source.pause) { + source.pause(); + } + } + } + + source.on('data', ondata); + + function ondrain() { + if (source.readable && source.resume) { + source.resume(); + } + } + + dest.on('drain', ondrain); + + // If the 'end' option is not supplied, dest.end() will be called when + // source gets the 'end' or 'close' events. Only dest.end() once. + if (!dest._isStdio && (!options || options.end !== false)) { + source.on('end', onend); + source.on('close', onclose); + } + + var didOnEnd = false; + function onend() { + if (didOnEnd) return; + didOnEnd = true; + + dest.end(); + } + + + function onclose() { + if (didOnEnd) return; + didOnEnd = true; + + if (typeof dest.destroy === 'function') dest.destroy(); + } + + // don't leave dangling pipes when there are errors. + function onerror(er) { + cleanup(); + if (EE.listenerCount(this, 'error') === 0) { + throw er; // Unhandled stream error in pipe. + } + } + + source.on('error', onerror); + dest.on('error', onerror); + + // remove all the event listeners that were added. + function cleanup() { + source.removeListener('data', ondata); + dest.removeListener('drain', ondrain); + + source.removeListener('end', onend); + source.removeListener('close', onclose); + + source.removeListener('error', onerror); + dest.removeListener('error', onerror); + + source.removeListener('end', cleanup); + source.removeListener('close', cleanup); + + dest.removeListener('close', cleanup); + } + + source.on('end', cleanup); + source.on('close', cleanup); + + dest.on('close', cleanup); + + dest.emit('pipe', source); + + // Allow for unix-like usage: A.pipe(B).pipe(C) + return dest; +}; + +},{"events":21,"inherits":44,"readable-stream/duplex.js":25,"readable-stream/passthrough.js":32,"readable-stream/readable.js":33,"readable-stream/transform.js":34,"readable-stream/writable.js":35}],37:[function(_dereq_,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var Buffer = _dereq_('buffer').Buffer; + +var isBufferEncoding = Buffer.isEncoding + || function(encoding) { + switch (encoding && encoding.toLowerCase()) { + case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true; + default: return false; + } + } + + +function assertEncoding(encoding) { + if (encoding && !isBufferEncoding(encoding)) { + throw new Error('Unknown encoding: ' + encoding); + } +} + +// StringDecoder provides an interface for efficiently splitting a series of +// buffers into a series of JS strings without breaking apart multi-byte +// characters. CESU-8 is handled as part of the UTF-8 encoding. +// +// @TODO Handling all encodings inside a single object makes it very difficult +// to reason about this code, so it should be split up in the future. +// @TODO There should be a utf8-strict encoding that rejects invalid UTF-8 code +// points as used by CESU-8. +var StringDecoder = exports.StringDecoder = function(encoding) { + this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, ''); + assertEncoding(encoding); + switch (this.encoding) { + case 'utf8': + // CESU-8 represents each of Surrogate Pair by 3-bytes + this.surrogateSize = 3; + break; + case 'ucs2': + case 'utf16le': + // UTF-16 represents each of Surrogate Pair by 2-bytes + this.surrogateSize = 2; + this.detectIncompleteChar = utf16DetectIncompleteChar; + break; + case 'base64': + // Base-64 stores 3 bytes in 4 chars, and pads the remainder. + this.surrogateSize = 3; + this.detectIncompleteChar = base64DetectIncompleteChar; + break; + default: + this.write = passThroughWrite; + return; + } + + // Enough space to store all bytes of a single character. UTF-8 needs 4 + // bytes, but CESU-8 may require up to 6 (3 bytes per surrogate). + this.charBuffer = new Buffer(6); + // Number of bytes received for the current incomplete multi-byte character. + this.charReceived = 0; + // Number of bytes expected for the current incomplete multi-byte character. + this.charLength = 0; +}; + + +// write decodes the given buffer and returns it as JS string that is +// guaranteed to not contain any partial multi-byte characters. Any partial +// character found at the end of the buffer is buffered up, and will be +// returned when calling write again with the remaining bytes. +// +// Note: Converting a Buffer containing an orphan surrogate to a String +// currently works, but converting a String to a Buffer (via `new Buffer`, or +// Buffer#write) will replace incomplete surrogates with the unicode +// replacement character. See https://codereview.chromium.org/121173009/ . +StringDecoder.prototype.write = function(buffer) { + var charStr = ''; + // if our last write ended with an incomplete multibyte character + while (this.charLength) { + // determine how many remaining bytes this buffer has to offer for this char + var available = (buffer.length >= this.charLength - this.charReceived) ? + this.charLength - this.charReceived : + buffer.length; + + // add the new bytes to the char buffer + buffer.copy(this.charBuffer, this.charReceived, 0, available); + this.charReceived += available; + + if (this.charReceived < this.charLength) { + // still not enough chars in this buffer? wait for more ... + return ''; + } + + // remove bytes belonging to the current character from the buffer + buffer = buffer.slice(available, buffer.length); + + // get the character that was split + charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding); + + // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character + var charCode = charStr.charCodeAt(charStr.length - 1); + if (charCode >= 0xD800 && charCode <= 0xDBFF) { + this.charLength += this.surrogateSize; + charStr = ''; + continue; + } + this.charReceived = this.charLength = 0; + + // if there are no more bytes in this buffer, just emit our char + if (buffer.length === 0) { + return charStr; + } + break; + } + + // determine and set charLength / charReceived + this.detectIncompleteChar(buffer); + + var end = buffer.length; + if (this.charLength) { + // buffer the incomplete character bytes we got + buffer.copy(this.charBuffer, 0, buffer.length - this.charReceived, end); + end -= this.charReceived; + } + + charStr += buffer.toString(this.encoding, 0, end); + + var end = charStr.length - 1; + var charCode = charStr.charCodeAt(end); + // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character + if (charCode >= 0xD800 && charCode <= 0xDBFF) { + var size = this.surrogateSize; + this.charLength += size; + this.charReceived += size; + this.charBuffer.copy(this.charBuffer, size, 0, size); + buffer.copy(this.charBuffer, 0, 0, size); + return charStr.substring(0, end); + } + + // or just emit the charStr + return charStr; +}; + +// detectIncompleteChar determines if there is an incomplete UTF-8 character at +// the end of the given buffer. If so, it sets this.charLength to the byte +// length that character, and sets this.charReceived to the number of bytes +// that are available for this character. +StringDecoder.prototype.detectIncompleteChar = function(buffer) { + // determine how many bytes we have to check at the end of this buffer + var i = (buffer.length >= 3) ? 3 : buffer.length; + + // Figure out if one of the last i bytes of our buffer announces an + // incomplete char. + for (; i > 0; i--) { + var c = buffer[buffer.length - i]; + + // See http://en.wikipedia.org/wiki/UTF-8#Description + + // 110XXXXX + if (i == 1 && c >> 5 == 0x06) { + this.charLength = 2; + break; + } + + // 1110XXXX + if (i <= 2 && c >> 4 == 0x0E) { + this.charLength = 3; + break; + } + + // 11110XXX + if (i <= 3 && c >> 3 == 0x1E) { + this.charLength = 4; + break; + } + } + this.charReceived = i; +}; + +StringDecoder.prototype.end = function(buffer) { + var res = ''; + if (buffer && buffer.length) + res = this.write(buffer); + + if (this.charReceived) { + var cr = this.charReceived; + var buf = this.charBuffer; + var enc = this.encoding; + res += buf.slice(0, cr).toString(enc); + } + + return res; +}; + +function passThroughWrite(buffer) { + return buffer.toString(this.encoding); +} + +function utf16DetectIncompleteChar(buffer) { + this.charReceived = buffer.length % 2; + this.charLength = this.charReceived ? 2 : 0; +} + +function base64DetectIncompleteChar(buffer) { + this.charReceived = buffer.length % 3; + this.charLength = this.charReceived ? 3 : 0; +} + +},{"buffer":17}],38:[function(_dereq_,module,exports){ +module.exports = function isBuffer(arg) { + return arg && typeof arg === 'object' + && typeof arg.copy === 'function' + && typeof arg.fill === 'function' + && typeof arg.readUInt8 === 'function'; +} +},{}],39:[function(_dereq_,module,exports){ +(function (process,global){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var formatRegExp = /%[sdj%]/g; +exports.format = function(f) { + if (!isString(f)) { + var objects = []; + for (var i = 0; i < arguments.length; i++) { + objects.push(inspect(arguments[i])); + } + return objects.join(' '); + } + + var i = 1; + var args = arguments; + var len = args.length; + var str = String(f).replace(formatRegExp, function(x) { + if (x === '%') return '%'; + if (i >= len) return x; + switch (x) { + case '%s': return String(args[i++]); + case '%d': return Number(args[i++]); + case '%j': + try { + return JSON.stringify(args[i++]); + } catch (_) { + return '[Circular]'; + } + default: + return x; + } + }); + for (var x = args[i]; i < len; x = args[++i]) { + if (isNull(x) || !isObject(x)) { + str += ' ' + x; + } else { + str += ' ' + inspect(x); + } + } + return str; +}; + + +// Mark that a method should not be used. +// Returns a modified function which warns once by default. +// If --no-deprecation is set, then it is a no-op. +exports.deprecate = function(fn, msg) { + // Allow for deprecating things in the process of starting up. + if (isUndefined(global.process)) { + return function() { + return exports.deprecate(fn, msg).apply(this, arguments); + }; + } + + if (process.noDeprecation === true) { + return fn; + } + + var warned = false; + function deprecated() { + if (!warned) { + if (process.throwDeprecation) { + throw new Error(msg); + } else if (process.traceDeprecation) { + console.trace(msg); + } else { + console.error(msg); + } + warned = true; + } + return fn.apply(this, arguments); + } + + return deprecated; +}; + + +var debugs = {}; +var debugEnviron; +exports.debuglog = function(set) { + if (isUndefined(debugEnviron)) + debugEnviron = process.env.NODE_DEBUG || ''; + set = set.toUpperCase(); + if (!debugs[set]) { + if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { + var pid = process.pid; + debugs[set] = function() { + var msg = exports.format.apply(exports, arguments); + console.error('%s %d: %s', set, pid, msg); + }; + } else { + debugs[set] = function() {}; + } + } + return debugs[set]; +}; + + +/** + * Echos the value of a value. Trys to print the value out + * in the best way possible given the different types. + * + * @param {Object} obj The object to print out. + * @param {Object} opts Optional options object that alters the output. + */ +/* legacy: obj, showHidden, depth, colors*/ +function inspect(obj, opts) { + // default options + var ctx = { + seen: [], + stylize: stylizeNoColor + }; + // legacy... + if (arguments.length >= 3) ctx.depth = arguments[2]; + if (arguments.length >= 4) ctx.colors = arguments[3]; + if (isBoolean(opts)) { + // legacy... + ctx.showHidden = opts; + } else if (opts) { + // got an "options" object + exports._extend(ctx, opts); + } + // set default options + if (isUndefined(ctx.showHidden)) ctx.showHidden = false; + if (isUndefined(ctx.depth)) ctx.depth = 2; + if (isUndefined(ctx.colors)) ctx.colors = false; + if (isUndefined(ctx.customInspect)) ctx.customInspect = true; + if (ctx.colors) ctx.stylize = stylizeWithColor; + return formatValue(ctx, obj, ctx.depth); +} +exports.inspect = inspect; + + +// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics +inspect.colors = { + 'bold' : [1, 22], + 'italic' : [3, 23], + 'underline' : [4, 24], + 'inverse' : [7, 27], + 'white' : [37, 39], + 'grey' : [90, 39], + 'black' : [30, 39], + 'blue' : [34, 39], + 'cyan' : [36, 39], + 'green' : [32, 39], + 'magenta' : [35, 39], + 'red' : [31, 39], + 'yellow' : [33, 39] +}; + +// Don't use 'blue' not visible on cmd.exe +inspect.styles = { + 'special': 'cyan', + 'number': 'yellow', + 'boolean': 'yellow', + 'undefined': 'grey', + 'null': 'bold', + 'string': 'green', + 'date': 'magenta', + // "name": intentionally not styling + 'regexp': 'red' +}; + + +function stylizeWithColor(str, styleType) { + var style = inspect.styles[styleType]; + + if (style) { + return '\u001b[' + inspect.colors[style][0] + 'm' + str + + '\u001b[' + inspect.colors[style][1] + 'm'; + } else { + return str; + } +} + + +function stylizeNoColor(str, styleType) { + return str; +} + + +function arrayToHash(array) { + var hash = {}; + + array.forEach(function(val, idx) { + hash[val] = true; + }); + + return hash; +} + + +function formatValue(ctx, value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if (ctx.customInspect && + value && + isFunction(value.inspect) && + // Filter out the util module, it's inspect function is special + value.inspect !== exports.inspect && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + var ret = value.inspect(recurseTimes, ctx); + if (!isString(ret)) { + ret = formatValue(ctx, ret, recurseTimes); + } + return ret; + } + + // Primitive types cannot have properties + var primitive = formatPrimitive(ctx, value); + if (primitive) { + return primitive; + } + + // Look up the keys of the object. + var keys = Object.keys(value); + var visibleKeys = arrayToHash(keys); + + if (ctx.showHidden) { + keys = Object.getOwnPropertyNames(value); + } + + // IE doesn't make error fields non-enumerable + // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx + if (isError(value) + && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { + return formatError(value); + } + + // Some type of object without properties can be shortcutted. + if (keys.length === 0) { + if (isFunction(value)) { + var name = value.name ? ': ' + value.name : ''; + return ctx.stylize('[Function' + name + ']', 'special'); + } + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } + if (isDate(value)) { + return ctx.stylize(Date.prototype.toString.call(value), 'date'); + } + if (isError(value)) { + return formatError(value); + } + } + + var base = '', array = false, braces = ['{', '}']; + + // Make Array say that they are Array + if (isArray(value)) { + array = true; + braces = ['[', ']']; + } + + // Make functions say that they are functions + if (isFunction(value)) { + var n = value.name ? ': ' + value.name : ''; + base = ' [Function' + n + ']'; + } + + // Make RegExps say that they are RegExps + if (isRegExp(value)) { + base = ' ' + RegExp.prototype.toString.call(value); + } + + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + Date.prototype.toUTCString.call(value); + } + + // Make error with message first say the error + if (isError(value)) { + base = ' ' + formatError(value); + } + + if (keys.length === 0 && (!array || value.length == 0)) { + return braces[0] + base + braces[1]; + } + + if (recurseTimes < 0) { + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } else { + return ctx.stylize('[Object]', 'special'); + } + } + + ctx.seen.push(value); + + var output; + if (array) { + output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); + } else { + output = keys.map(function(key) { + return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); + }); + } + + ctx.seen.pop(); + + return reduceToSingleString(output, base, braces); +} + + +function formatPrimitive(ctx, value) { + if (isUndefined(value)) + return ctx.stylize('undefined', 'undefined'); + if (isString(value)) { + var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return ctx.stylize(simple, 'string'); + } + if (isNumber(value)) + return ctx.stylize('' + value, 'number'); + if (isBoolean(value)) + return ctx.stylize('' + value, 'boolean'); + // For some reason typeof null is "object", so special case here. + if (isNull(value)) + return ctx.stylize('null', 'null'); +} + + +function formatError(value) { + return '[' + Error.prototype.toString.call(value) + ']'; +} + + +function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { + var output = []; + for (var i = 0, l = value.length; i < l; ++i) { + if (hasOwnProperty(value, String(i))) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + String(i), true)); + } else { + output.push(''); + } + } + keys.forEach(function(key) { + if (!key.match(/^\d+$/)) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + key, true)); + } + }); + return output; +} + + +function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { + var name, str, desc; + desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; + if (desc.get) { + if (desc.set) { + str = ctx.stylize('[Getter/Setter]', 'special'); + } else { + str = ctx.stylize('[Getter]', 'special'); + } + } else { + if (desc.set) { + str = ctx.stylize('[Setter]', 'special'); + } + } + if (!hasOwnProperty(visibleKeys, key)) { + name = '[' + key + ']'; + } + if (!str) { + if (ctx.seen.indexOf(desc.value) < 0) { + if (isNull(recurseTimes)) { + str = formatValue(ctx, desc.value, null); + } else { + str = formatValue(ctx, desc.value, recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (array) { + str = str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n').substr(2); + } else { + str = '\n' + str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = ctx.stylize('[Circular]', 'special'); + } + } + if (isUndefined(name)) { + if (array && key.match(/^\d+$/)) { + return str; + } + name = JSON.stringify('' + key); + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.substr(1, name.length - 2); + name = ctx.stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = ctx.stylize(name, 'string'); + } + } + + return name + ': ' + str; +} + + +function reduceToSingleString(output, base, braces) { + var numLinesEst = 0; + var length = output.reduce(function(prev, cur) { + numLinesEst++; + if (cur.indexOf('\n') >= 0) numLinesEst++; + return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; + }, 0); + + if (length > 60) { + return braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + } + + return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; +} + + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. +function isArray(ar) { + return Array.isArray(ar); +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return isObject(re) && objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return isObject(d) && objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return isObject(e) && + (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +exports.isBuffer = _dereq_('./support/isBuffer'); + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + + +function pad(n) { + return n < 10 ? '0' + n.toString(10) : n.toString(10); +} + + +var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', + 'Oct', 'Nov', 'Dec']; + +// 26 Feb 16:19:34 +function timestamp() { + var d = new Date(); + var time = [pad(d.getHours()), + pad(d.getMinutes()), + pad(d.getSeconds())].join(':'); + return [d.getDate(), months[d.getMonth()], time].join(' '); +} + + +// log is just a thin wrapper to console.log that prepends a timestamp +exports.log = function() { + console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); +}; + + +/** + * Inherit the prototype methods from one constructor into another. + * + * The Function.prototype.inherits from lang.js rewritten as a standalone + * function (not on Function.prototype). NOTE: If this file is to be loaded + * during bootstrapping this function needs to be rewritten using some native + * functions as prototype setup using normal JavaScript does not work as + * expected during bootstrapping (see mirror.js in r114903). + * + * @param {function} ctor Constructor function which needs to inherit the + * prototype. + * @param {function} superCtor Constructor function to inherit prototype from. + */ +exports.inherits = _dereq_('inherits'); + +exports._extend = function(origin, add) { + // Don't do anything if add isn't an object + if (!add || !isObject(add)) return origin; + + var keys = Object.keys(add); + var i = keys.length; + while (i--) { + origin[keys[i]] = add[keys[i]]; + } + return origin; +}; + +function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +} + +}).call(this,_dereq_('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./support/isBuffer":38,"_process":24,"inherits":44}],40:[function(_dereq_,module,exports){ + +/** + * This is the web browser implementation of `debug()`. + * + * Expose `debug()` as the module. + */ + +exports = module.exports = _dereq_('./debug'); +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; + +/** + * Colors. + */ + +exports.colors = [ + 'lightseagreen', + 'forestgreen', + 'goldenrod', + 'dodgerblue', + 'darkorchid', + 'crimson' +]; + +/** + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors + */ + +function useColors() { + // is webkit? http://stackoverflow.com/a/16459606/376773 + return ('WebkitAppearance' in document.documentElement.style) || + // is firebug? http://stackoverflow.com/a/398120/376773 + (window.console && (console.firebug || (console.exception && console.table))) || + // is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + (navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31); +} + +/** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ + +exports.formatters.j = function(v) { + return JSON.stringify(v); +}; + + +/** + * Colorize log arguments if enabled. + * + * @api public + */ + +function formatArgs() { + var args = arguments; + var useColors = this.useColors; + + args[0] = (useColors ? '%c' : '') + + this.namespace + + (useColors ? ' %c' : ' ') + + args[0] + + (useColors ? '%c ' : ' ') + + '+' + exports.humanize(this.diff); + + if (!useColors) return args; + + var c = 'color: ' + this.color; + args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1)); + + // the final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + var index = 0; + var lastC = 0; + args[0].replace(/%[a-z%]/g, function(match) { + if ('%' === match) return; + index++; + if ('%c' === match) { + // we only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); + + args.splice(lastC, 0, c); + return args; +} + +/** + * Invokes `console.log()` when available. + * No-op when `console.log` is not a "function". + * + * @api public + */ + +function log() { + // This hackery is required for IE8, + // where the `console.log` function doesn't have 'apply' + return 'object' == typeof console + && 'function' == typeof console.log + && Function.prototype.apply.call(console.log, console, arguments); +} + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ + +function save(namespaces) { + try { + if (null == namespaces) { + localStorage.removeItem('debug'); + } else { + localStorage.debug = namespaces; + } + } catch(e) {} +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + +function load() { + var r; + try { + r = localStorage.debug; + } catch(e) {} + return r; +} + +/** + * Enable namespaces listed in `localStorage.debug` initially. + */ + +exports.enable(load()); + +},{"./debug":41}],41:[function(_dereq_,module,exports){ + +/** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + * + * Expose `debug()` as the module. + */ + +exports = module.exports = debug; +exports.coerce = coerce; +exports.disable = disable; +exports.enable = enable; +exports.enabled = enabled; +exports.humanize = _dereq_('ms'); + +/** + * The currently active debug mode names, and names to skip. + */ + +exports.names = []; +exports.skips = []; + +/** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lowercased letter, i.e. "n". + */ + +exports.formatters = {}; + +/** + * Previously assigned color. + */ + +var prevColor = 0; + +/** + * Previous log timestamp. + */ + +var prevTime; + +/** + * Select a color. + * + * @return {Number} + * @api private + */ + +function selectColor() { + return exports.colors[prevColor++ % exports.colors.length]; +} + +/** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ + +function debug(namespace) { + + // define the `disabled` version + function disabled() { + } + disabled.enabled = false; + + // define the `enabled` version + function enabled() { + + var self = enabled; + + // set `diff` timestamp + var curr = +new Date(); + var ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; + + // add the `color` if not set + if (null == self.useColors) self.useColors = exports.useColors(); + if (null == self.color && self.useColors) self.color = selectColor(); + + var args = Array.prototype.slice.call(arguments); + + args[0] = exports.coerce(args[0]); + + if ('string' !== typeof args[0]) { + // anything else let's inspect with %o + args = ['%o'].concat(args); + } + + // apply any `formatters` transformations + var index = 0; + args[0] = args[0].replace(/%([a-z%])/g, function(match, format) { + // if we encounter an escaped % then don't increase the array index + if (match === '%') return match; + index++; + var formatter = exports.formatters[format]; + if ('function' === typeof formatter) { + var val = args[index]; + match = formatter.call(self, val); + + // now we need to remove `args[index]` since it's inlined in the `format` + args.splice(index, 1); + index--; + } + return match; + }); + + if ('function' === typeof exports.formatArgs) { + args = exports.formatArgs.apply(self, args); + } + var logFn = enabled.log || exports.log || console.log.bind(console); + logFn.apply(self, args); + } + enabled.enabled = true; + + var fn = exports.enabled(namespace) ? enabled : disabled; + + fn.namespace = namespace; + + return fn; +} + +/** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ + +function enable(namespaces) { + exports.save(namespaces); + + var split = (namespaces || '').split(/[\s,]+/); + var len = split.length; + + for (var i = 0; i < len; i++) { + if (!split[i]) continue; // ignore empty strings + namespaces = split[i].replace(/\*/g, '.*?'); + if (namespaces[0] === '-') { + exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); + } else { + exports.names.push(new RegExp('^' + namespaces + '$')); + } + } +} + +/** + * Disable debug output. + * + * @api public + */ + +function disable() { + exports.enable(''); +} + +/** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + +function enabled(name) { + var i, len; + for (i = 0, len = exports.skips.length; i < len; i++) { + if (exports.skips[i].test(name)) { + return false; + } + } + for (i = 0, len = exports.names.length; i < len; i++) { + if (exports.names[i].test(name)) { + return true; + } + } + return false; +} + +/** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + +function coerce(val) { + if (val instanceof Error) return val.stack || val.message; + return val; +} + +},{"ms":42}],42:[function(_dereq_,module,exports){ +/** + * Helpers. + */ + +var s = 1000; +var m = s * 60; +var h = m * 60; +var d = h * 24; +var y = d * 365.25; + +/** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} options + * @return {String|Number} + * @api public + */ + +module.exports = function(val, options){ + options = options || {}; + if ('string' == typeof val) return parse(val); + return options.long + ? long(val) + : short(val); +}; + +/** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function parse(str) { + var match = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str); + if (!match) return; + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'y': + return n * y; + case 'days': + case 'day': + case 'd': + return n * d; + case 'hours': + case 'hour': + case 'h': + return n * h; + case 'minutes': + case 'minute': + case 'm': + return n * m; + case 'seconds': + case 'second': + case 's': + return n * s; + case 'ms': + return n; + } +} + +/** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function short(ms) { + if (ms >= d) return Math.round(ms / d) + 'd'; + if (ms >= h) return Math.round(ms / h) + 'h'; + if (ms >= m) return Math.round(ms / m) + 'm'; + if (ms >= s) return Math.round(ms / s) + 's'; + return ms + 'ms'; +} + +/** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function long(ms) { + return plural(ms, d, 'day') + || plural(ms, h, 'hour') + || plural(ms, m, 'minute') + || plural(ms, s, 'second') + || ms + ' ms'; +} + +/** + * Pluralization helper. + */ + +function plural(ms, n, name) { + if (ms < n) return; + if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name; + return Math.ceil(ms / n) + ' ' + name + 's'; +} + +},{}],43:[function(_dereq_,module,exports){ +/** + * Copyright (c) 2013 Petka Antonov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions:</p> + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +"use strict"; +function Deque(capacity) { + this._capacity = getCapacity(capacity); + this._length = 0; + this._front = 0; + this._makeCapacity(); + if (isArray(capacity)) { + var len = capacity.length; + for (var i = 0; i < len; ++i) { + this[i] = capacity[i]; + } + this._length = len; + } +} + +Deque.prototype.toArray = function Deque$toArray() { + var len = this._length; + var ret = new Array(len); + var front = this._front; + var capacity = this._capacity; + for (var j = 0; j < len; ++j) { + ret[j] = this[(front + j) & (capacity - 1)]; + } + return ret; +}; + +Deque.prototype.push = function Deque$push(item) { + var argsLength = arguments.length; + var length = this._length; + if (argsLength > 1) { + var capacity = this._capacity; + if (length + argsLength > capacity) { + for (var i = 0; i < argsLength; ++i) { + this._checkCapacity(length + 1); + var j = (this._front + length) & (this._capacity - 1); + this[j] = arguments[i]; + length++; + this._length = length; + } + return length; + } + else { + var j = this._front; + for (var i = 0; i < argsLength; ++i) { + this[(j + length) & (capacity - 1)] = arguments[i]; + j++; + } + this._length = length + argsLength; + return length + argsLength; + } + + } + + if (argsLength === 0) return length; + + this._checkCapacity(length + 1); + var i = (this._front + length) & (this._capacity - 1); + this[i] = item; + this._length = length + 1; + return length + 1; +}; + +Deque.prototype.pop = function Deque$pop() { + var length = this._length; + if (length === 0) { + return void 0; + } + var i = (this._front + length - 1) & (this._capacity - 1); + var ret = this[i]; + this[i] = void 0; + this._length = length - 1; + return ret; +}; + +Deque.prototype.shift = function Deque$shift() { + var length = this._length; + if (length === 0) { + return void 0; + } + var front = this._front; + var ret = this[front]; + this[front] = void 0; + this._front = (front + 1) & (this._capacity - 1); + this._length = length - 1; + return ret; +}; + +Deque.prototype.unshift = function Deque$unshift(item) { + var length = this._length; + var argsLength = arguments.length; + + + if (argsLength > 1) { + var capacity = this._capacity; + if (length + argsLength > capacity) { + for (var i = argsLength - 1; i >= 0; i--) { + this._checkCapacity(length + 1); + var capacity = this._capacity; + var j = (((( this._front - 1 ) & + ( capacity - 1) ) ^ capacity ) - capacity ); + this[j] = arguments[i]; + length++; + this._length = length; + this._front = j; + } + return length; + } + else { + var front = this._front; + for (var i = argsLength - 1; i >= 0; i--) { + var j = (((( front - 1 ) & + ( capacity - 1) ) ^ capacity ) - capacity ); + this[j] = arguments[i]; + front = j; + } + this._front = front; + this._length = length + argsLength; + return length + argsLength; + } + } + + if (argsLength === 0) return length; + + this._checkCapacity(length + 1); + var capacity = this._capacity; + var i = (((( this._front - 1 ) & + ( capacity - 1) ) ^ capacity ) - capacity ); + this[i] = item; + this._length = length + 1; + this._front = i; + return length + 1; +}; + +Deque.prototype.peekBack = function Deque$peekBack() { + var length = this._length; + if (length === 0) { + return void 0; + } + var index = (this._front + length - 1) & (this._capacity - 1); + return this[index]; +}; + +Deque.prototype.peekFront = function Deque$peekFront() { + if (this._length === 0) { + return void 0; + } + return this[this._front]; +}; + +Deque.prototype.get = function Deque$get(index) { + var i = index; + if ((i !== (i | 0))) { + return void 0; + } + var len = this._length; + if (i < 0) { + i = i + len; + } + if (i < 0 || i >= len) { + return void 0; + } + return this[(this._front + i) & (this._capacity - 1)]; +}; + +Deque.prototype.isEmpty = function Deque$isEmpty() { + return this._length === 0; +}; + +Deque.prototype.clear = function Deque$clear() { + this._length = 0; + this._front = 0; + this._makeCapacity(); +}; + +Deque.prototype.toString = function Deque$toString() { + return this.toArray().toString(); +}; + +Deque.prototype.valueOf = Deque.prototype.toString; +Deque.prototype.removeFront = Deque.prototype.shift; +Deque.prototype.removeBack = Deque.prototype.pop; +Deque.prototype.insertFront = Deque.prototype.unshift; +Deque.prototype.insertBack = Deque.prototype.push; +Deque.prototype.enqueue = Deque.prototype.push; +Deque.prototype.dequeue = Deque.prototype.shift; +Deque.prototype.toJSON = Deque.prototype.toArray; + +Object.defineProperty(Deque.prototype, "length", { + get: function() { + return this._length; + }, + set: function() { + throw new RangeError(""); + } +}); + +Deque.prototype._makeCapacity = function Deque$_makeCapacity() { + var len = this._capacity; + for (var i = 0; i < len; ++i) { + this[i] = void 0; + } +}; + +Deque.prototype._checkCapacity = function Deque$_checkCapacity(size) { + if (this._capacity < size) { + this._resizeTo(getCapacity(this._capacity * 1.5 + 16)); + } +}; + +Deque.prototype._resizeTo = function Deque$_resizeTo(capacity) { + var oldFront = this._front; + var oldCapacity = this._capacity; + var oldDeque = new Array(oldCapacity); + var length = this._length; + + arrayCopy(this, 0, oldDeque, 0, oldCapacity); + this._capacity = capacity; + this._makeCapacity(); + this._front = 0; + if (oldFront + length <= oldCapacity) { + arrayCopy(oldDeque, oldFront, this, 0, length); + } else { var lengthBeforeWrapping = + length - ((oldFront + length) & (oldCapacity - 1)); + + arrayCopy(oldDeque, oldFront, this, 0, lengthBeforeWrapping); + arrayCopy(oldDeque, 0, this, lengthBeforeWrapping, + length - lengthBeforeWrapping); + } +}; + + +var isArray = Array.isArray; + +function arrayCopy(src, srcIndex, dst, dstIndex, len) { + for (var j = 0; j < len; ++j) { + dst[j + dstIndex] = src[j + srcIndex]; + } +} + +function pow2AtLeast(n) { + n = n >>> 0; + n = n - 1; + n = n | (n >> 1); + n = n | (n >> 2); + n = n | (n >> 4); + n = n | (n >> 8); + n = n | (n >> 16); + return n + 1; +} + +function getCapacity(capacity) { + if (typeof capacity !== "number") { + if (isArray(capacity)) { + capacity = capacity.length; + } + else { + return 16; + } + } + return pow2AtLeast( + Math.min( + Math.max(16, capacity), 1073741824) + ); +} + +module.exports = Deque; + +},{}],44:[function(_dereq_,module,exports){ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +} + +},{}],45:[function(_dereq_,module,exports){ +var util = _dereq_('util') +var AbstractIterator = _dereq_('abstract-leveldown').AbstractIterator +var ltgt = _dereq_('ltgt') + +module.exports = Iterator + +function Iterator (db, options) { + if (!options) options = {} + this.options = options + AbstractIterator.call(this, db) + this._order = options.reverse ? 'DESC': 'ASC' + this._limit = options.limit + this._count = 0 + this._done = false + var lower = ltgt.lowerBound(options) + var upper = ltgt.upperBound(options) + this._keyRange = lower || upper ? this.db.makeKeyRange({ + lower: lower, + upper: upper, + excludeLower: ltgt.lowerBoundExclusive(options), + excludeUpper: ltgt.upperBoundExclusive(options) + }) : null + this.callback = null +} + +util.inherits(Iterator, AbstractIterator) + +Iterator.prototype.createIterator = function() { + var self = this + + self.iterator = self.db.iterate(function () { + self.onItem.apply(self, arguments) + }, { + keyRange: self._keyRange, + autoContinue: false, + order: self._order, + onError: function(err) { console.log('horrible error', err) }, + }) +} + +// TODO the limit implementation here just ignores all reads after limit has been reached +// it should cancel the iterator instead but I don't know how +Iterator.prototype.onItem = function (value, cursor, cursorTransaction) { + if (!cursor && this.callback) { + this.callback() + this.callback = false + return + } + var shouldCall = true + + if (!!this._limit && this._limit > 0 && this._count++ >= this._limit) + shouldCall = false + + if (shouldCall) this.callback(false, cursor.key, cursor.value) + if (cursor) cursor['continue']() +} + +Iterator.prototype._next = function (callback) { + if (!callback) return new Error('next() requires a callback argument') + if (!this._started) { + this.createIterator() + this._started = true + } + this.callback = callback +} + +},{"abstract-leveldown":48,"ltgt":52,"util":39}],46:[function(_dereq_,module,exports){ +(function (process){ +/* Copyright (c) 2013 Rod Vagg, MIT License */ + +function AbstractChainedBatch (db) { + this._db = db + this._operations = [] + this._written = false +} + +AbstractChainedBatch.prototype._checkWritten = function () { + if (this._written) + throw new Error('write() already called on this batch') +} + +AbstractChainedBatch.prototype.put = function (key, value) { + this._checkWritten() + + var err = this._db._checkKeyValue(key, 'key', this._db._isBuffer) + if (err) throw err + err = this._db._checkKeyValue(value, 'value', this._db._isBuffer) + if (err) throw err + + if (!this._db._isBuffer(key)) key = String(key) + if (!this._db._isBuffer(value)) value = String(value) + + if (typeof this._put == 'function' ) + this._put(key, value) + else + this._operations.push({ type: 'put', key: key, value: value }) + + return this +} + +AbstractChainedBatch.prototype.del = function (key) { + this._checkWritten() + + var err = this._db._checkKeyValue(key, 'key', this._db._isBuffer) + if (err) throw err + + if (!this._db._isBuffer(key)) key = String(key) + + if (typeof this._del == 'function' ) + this._del(key) + else + this._operations.push({ type: 'del', key: key }) + + return this +} + +AbstractChainedBatch.prototype.clear = function () { + this._checkWritten() + + this._operations = [] + + if (typeof this._clear == 'function' ) + this._clear() + + return this +} + +AbstractChainedBatch.prototype.write = function (options, callback) { + this._checkWritten() + + if (typeof options == 'function') + callback = options + if (typeof callback != 'function') + throw new Error('write() requires a callback argument') + if (typeof options != 'object') + options = {} + + this._written = true + + if (typeof this._write == 'function' ) + return this._write(callback) + + if (typeof this._db._batch == 'function') + return this._db._batch(this._operations, options, callback) + + process.nextTick(callback) +} + +module.exports = AbstractChainedBatch +}).call(this,_dereq_('_process')) +},{"_process":24}],47:[function(_dereq_,module,exports){ +(function (process){ +/* Copyright (c) 2013 Rod Vagg, MIT License */ + +function AbstractIterator (db) { + this.db = db + this._ended = false + this._nexting = false +} + +AbstractIterator.prototype.next = function (callback) { + var self = this + + if (typeof callback != 'function') + throw new Error('next() requires a callback argument') + + if (self._ended) + return callback(new Error('cannot call next() after end()')) + if (self._nexting) + return callback(new Error('cannot call next() before previous next() has completed')) + + self._nexting = true + if (typeof self._next == 'function') { + return self._next(function () { + self._nexting = false + callback.apply(null, arguments) + }) + } + + process.nextTick(function () { + self._nexting = false + callback() + }) +} + +AbstractIterator.prototype.end = function (callback) { + if (typeof callback != 'function') + throw new Error('end() requires a callback argument') + + if (this._ended) + return callback(new Error('end() already called on iterator')) + + this._ended = true + + if (typeof this._end == 'function') + return this._end(callback) + + process.nextTick(callback) +} + +module.exports = AbstractIterator + +}).call(this,_dereq_('_process')) +},{"_process":24}],48:[function(_dereq_,module,exports){ +(function (process,Buffer){ +/* Copyright (c) 2013 Rod Vagg, MIT License */ + +var xtend = _dereq_('xtend') + , AbstractIterator = _dereq_('./abstract-iterator') + , AbstractChainedBatch = _dereq_('./abstract-chained-batch') + +function AbstractLevelDOWN (location) { + if (!arguments.length || location === undefined) + throw new Error('constructor requires at least a location argument') + + if (typeof location != 'string') + throw new Error('constructor requires a location string argument') + + this.location = location +} + +AbstractLevelDOWN.prototype.open = function (options, callback) { + if (typeof options == 'function') + callback = options + + if (typeof callback != 'function') + throw new Error('open() requires a callback argument') + + if (typeof options != 'object') + options = {} + + if (typeof this._open == 'function') + return this._open(options, callback) + + process.nextTick(callback) +} + +AbstractLevelDOWN.prototype.close = function (callback) { + if (typeof callback != 'function') + throw new Error('close() requires a callback argument') + + if (typeof this._close == 'function') + return this._close(callback) + + process.nextTick(callback) +} + +AbstractLevelDOWN.prototype.get = function (key, options, callback) { + var err + + if (typeof options == 'function') + callback = options + + if (typeof callback != 'function') + throw new Error('get() requires a callback argument') + + if (err = this._checkKeyValue(key, 'key', this._isBuffer)) + return callback(err) + + if (!this._isBuffer(key)) + key = String(key) + + if (typeof options != 'object') + options = {} + + if (typeof this._get == 'function') + return this._get(key, options, callback) + + process.nextTick(function () { callback(new Error('NotFound')) }) +} + +AbstractLevelDOWN.prototype.put = function (key, value, options, callback) { + var err + + if (typeof options == 'function') + callback = options + + if (typeof callback != 'function') + throw new Error('put() requires a callback argument') + + if (err = this._checkKeyValue(key, 'key', this._isBuffer)) + return callback(err) + + if (err = this._checkKeyValue(value, 'value', this._isBuffer)) + return callback(err) + + if (!this._isBuffer(key)) + key = String(key) + + // coerce value to string in node, don't touch it in browser + // (indexeddb can store any JS type) + if (!this._isBuffer(value) && !process.browser) + value = String(value) + + if (typeof options != 'object') + options = {} + + if (typeof this._put == 'function') + return this._put(key, value, options, callback) + + process.nextTick(callback) +} + +AbstractLevelDOWN.prototype.del = function (key, options, callback) { + var err + + if (typeof options == 'function') + callback = options + + if (typeof callback != 'function') + throw new Error('del() requires a callback argument') + + if (err = this._checkKeyValue(key, 'key', this._isBuffer)) + return callback(err) + + if (!this._isBuffer(key)) + key = String(key) + + if (typeof options != 'object') + options = {} + + if (typeof this._del == 'function') + return this._del(key, options, callback) + + process.nextTick(callback) +} + +AbstractLevelDOWN.prototype.batch = function (array, options, callback) { + if (!arguments.length) + return this._chainedBatch() + + if (typeof options == 'function') + callback = options + + if (typeof callback != 'function') + throw new Error('batch(array) requires a callback argument') + + if (!Array.isArray(array)) + return callback(new Error('batch(array) requires an array argument')) + + if (typeof options != 'object') + options = {} + + var i = 0 + , l = array.length + , e + , err + + for (; i < l; i++) { + e = array[i] + if (typeof e != 'object') + continue + + if (err = this._checkKeyValue(e.type, 'type', this._isBuffer)) + return callback(err) + + if (err = this._checkKeyValue(e.key, 'key', this._isBuffer)) + return callback(err) + + if (e.type == 'put') { + if (err = this._checkKeyValue(e.value, 'value', this._isBuffer)) + return callback(err) + } + } + + if (typeof this._batch == 'function') + return this._batch(array, options, callback) + + process.nextTick(callback) +} + +//TODO: remove from here, not a necessary primitive +AbstractLevelDOWN.prototype.approximateSize = function (start, end, callback) { + if ( start == null + || end == null + || typeof start == 'function' + || typeof end == 'function') { + throw new Error('approximateSize() requires valid `start`, `end` and `callback` arguments') + } + + if (typeof callback != 'function') + throw new Error('approximateSize() requires a callback argument') + + if (!this._isBuffer(start)) + start = String(start) + + if (!this._isBuffer(end)) + end = String(end) + + if (typeof this._approximateSize == 'function') + return this._approximateSize(start, end, callback) + + process.nextTick(function () { + callback(null, 0) + }) +} + +AbstractLevelDOWN.prototype._setupIteratorOptions = function (options) { + var self = this + + options = xtend(options) + + ;[ 'start', 'end', 'gt', 'gte', 'lt', 'lte' ].forEach(function (o) { + if (options[o] && self._isBuffer(options[o]) && options[o].length === 0) + delete options[o] + }) + + options.reverse = !!options.reverse + + // fix `start` so it takes into account gt, gte, lt, lte as appropriate + if (options.reverse && options.lt) + options.start = options.lt + if (options.reverse && options.lte) + options.start = options.lte + if (!options.reverse && options.gt) + options.start = options.gt + if (!options.reverse && options.gte) + options.start = options.gte + + if ((options.reverse && options.lt && !options.lte) + || (!options.reverse && options.gt && !options.gte)) + options.exclusiveStart = true // start should *not* include matching key + + return options +} + +AbstractLevelDOWN.prototype.iterator = function (options) { + if (typeof options != 'object') + options = {} + + options = this._setupIteratorOptions(options) + + if (typeof this._iterator == 'function') + return this._iterator(options) + + return new AbstractIterator(this) +} + +AbstractLevelDOWN.prototype._chainedBatch = function () { + return new AbstractChainedBatch(this) +} + +AbstractLevelDOWN.prototype._isBuffer = function (obj) { + return Buffer.isBuffer(obj) +} + +AbstractLevelDOWN.prototype._checkKeyValue = function (obj, type) { + + if (obj === null || obj === undefined) + return new Error(type + ' cannot be `null` or `undefined`') + + if (this._isBuffer(obj)) { + if (obj.length === 0) + return new Error(type + ' cannot be an empty Buffer') + } else if (String(obj) === '') + return new Error(type + ' cannot be an empty String') +} + +module.exports.AbstractLevelDOWN = AbstractLevelDOWN +module.exports.AbstractIterator = AbstractIterator +module.exports.AbstractChainedBatch = AbstractChainedBatch + +}).call(this,_dereq_('_process'),_dereq_("buffer").Buffer) +},{"./abstract-chained-batch":46,"./abstract-iterator":47,"_process":24,"buffer":17,"xtend":49}],49:[function(_dereq_,module,exports){ +module.exports = extend + +function extend() { + var target = {} + + for (var i = 0; i < arguments.length; i++) { + var source = arguments[i] + + for (var key in source) { + if (source.hasOwnProperty(key)) { + target[key] = source[key] + } + } + } + + return target +} + +},{}],50:[function(_dereq_,module,exports){ +/*global window:false, self:false, define:false, module:false */ + +/** + * @license IDBWrapper - A cross-browser wrapper for IndexedDB + * Copyright (c) 2011 - 2013 Jens Arps + * http://jensarps.de/ + * + * Licensed under the MIT (X11) license + */ + +(function (name, definition, global) { + if (typeof define === 'function') { + define(definition); + } else if (typeof module !== 'undefined' && module.exports) { + module.exports = definition(); + } else { + global[name] = definition(); + } +})('IDBStore', function () { + + 'use strict'; + + var defaultErrorHandler = function (error) { + throw error; + }; + + var defaults = { + storeName: 'Store', + storePrefix: 'IDBWrapper-', + dbVersion: 1, + keyPath: 'id', + autoIncrement: true, + onStoreReady: function () { + }, + onError: defaultErrorHandler, + indexes: [] + }; + + /** + * + * The IDBStore constructor + * + * @constructor + * @name IDBStore + * @version 1.4.1 + * + * @param {Object} [kwArgs] An options object used to configure the store and + * set callbacks + * @param {String} [kwArgs.storeName='Store'] The name of the store + * @param {String} [kwArgs.storePrefix='IDBWrapper-'] A prefix that is + * internally used to construct the name of the database, which will be + * kwArgs.storePrefix + kwArgs.storeName + * @param {Number} [kwArgs.dbVersion=1] The version of the store + * @param {String} [kwArgs.keyPath='id'] The key path to use. If you want to + * setup IDBWrapper to work with out-of-line keys, you need to set this to + * `null` + * @param {Boolean} [kwArgs.autoIncrement=true] If set to true, IDBStore will + * automatically make sure a unique keyPath value is present on each object + * that is stored. + * @param {Function} [kwArgs.onStoreReady] A callback to be called when the + * store is ready to be used. + * @param {Function} [kwArgs.onError=throw] A callback to be called when an + * error occurred during instantiation of the store. + * @param {Array} [kwArgs.indexes=[]] An array of indexData objects + * defining the indexes to use with the store. For every index to be used + * one indexData object needs to be passed in the array. + * An indexData object is defined as follows: + * @param {Object} [kwArgs.indexes.indexData] An object defining the index to + * use + * @param {String} kwArgs.indexes.indexData.name The name of the index + * @param {String} [kwArgs.indexes.indexData.keyPath] The key path of the index + * @param {Boolean} [kwArgs.indexes.indexData.unique] Whether the index is unique + * @param {Boolean} [kwArgs.indexes.indexData.multiEntry] Whether the index is multi entry + * @param {Function} [onStoreReady] A callback to be called when the store + * is ready to be used. + * @example + // create a store for customers with an additional index over the + // `lastname` property. + var myCustomerStore = new IDBStore({ + dbVersion: 1, + storeName: 'customer-index', + keyPath: 'customerid', + autoIncrement: true, + onStoreReady: populateTable, + indexes: [ + { name: 'lastname', keyPath: 'lastname', unique: false, multiEntry: false } + ] + }); + * @example + // create a generic store + var myCustomerStore = new IDBStore({ + storeName: 'my-data-store', + onStoreReady: function(){ + // start working with the store. + } + }); + */ + var IDBStore = function (kwArgs, onStoreReady) { + + if (typeof onStoreReady == 'undefined' && typeof kwArgs == 'function') { + onStoreReady = kwArgs; + } + if (Object.prototype.toString.call(kwArgs) != '[object Object]') { + kwArgs = {}; + } + + for (var key in defaults) { + this[key] = typeof kwArgs[key] != 'undefined' ? kwArgs[key] : defaults[key]; + } + + this.dbName = this.storePrefix + this.storeName; + this.dbVersion = parseInt(this.dbVersion, 10) || 1; + + onStoreReady && (this.onStoreReady = onStoreReady); + + var env = typeof window == 'object' ? window : self; + this.idb = env.indexedDB || env.webkitIndexedDB || env.mozIndexedDB; + this.keyRange = env.IDBKeyRange || env.webkitIDBKeyRange || env.mozIDBKeyRange; + + this.features = { + hasAutoIncrement: !env.mozIndexedDB + }; + + this.consts = { + 'READ_ONLY': 'readonly', + 'READ_WRITE': 'readwrite', + 'VERSION_CHANGE': 'versionchange', + 'NEXT': 'next', + 'NEXT_NO_DUPLICATE': 'nextunique', + 'PREV': 'prev', + 'PREV_NO_DUPLICATE': 'prevunique' + }; + + this.openDB(); + }; + + IDBStore.prototype = /** @lends IDBStore */ { + + /** + * A pointer to the IDBStore ctor + * + * @type IDBStore + */ + constructor: IDBStore, + + /** + * The version of IDBStore + * + * @type String + */ + version: '1.4.1', + + /** + * A reference to the IndexedDB object + * + * @type Object + */ + db: null, + + /** + * The full name of the IndexedDB used by IDBStore, composed of + * this.storePrefix + this.storeName + * + * @type String + */ + dbName: null, + + /** + * The version of the IndexedDB used by IDBStore + * + * @type Number + */ + dbVersion: null, + + /** + * A reference to the objectStore used by IDBStore + * + * @type Object + */ + store: null, + + /** + * The store name + * + * @type String + */ + storeName: null, + + /** + * The key path + * + * @type String + */ + keyPath: null, + + /** + * Whether IDBStore uses autoIncrement + * + * @type Boolean + */ + autoIncrement: null, + + /** + * The indexes used by IDBStore + * + * @type Array + */ + indexes: null, + + /** + * A hashmap of features of the used IDB implementation + * + * @type Object + * @proprty {Boolean} autoIncrement If the implementation supports + * native auto increment + */ + features: null, + + /** + * The callback to be called when the store is ready to be used + * + * @type Function + */ + onStoreReady: null, + + /** + * The callback to be called if an error occurred during instantiation + * of the store + * + * @type Function + */ + onError: null, + + /** + * The internal insertID counter + * + * @type Number + * @private + */ + _insertIdCount: 0, + + /** + * Opens an IndexedDB; called by the constructor. + * + * Will check if versions match and compare provided index configuration + * with existing ones, and update indexes if necessary. + * + * Will call this.onStoreReady() if everything went well and the store + * is ready to use, and this.onError() is something went wrong. + * + * @private + * + */ + openDB: function () { + + var openRequest = this.idb.open(this.dbName, this.dbVersion); + var preventSuccessCallback = false; + + openRequest.onerror = function (error) { + + var gotVersionErr = false; + if ('error' in error.target) { + gotVersionErr = error.target.error.name == 'VersionError'; + } else if ('errorCode' in error.target) { + gotVersionErr = error.target.errorCode == 12; + } + + if (gotVersionErr) { + this.onError(new Error('The version number provided is lower than the existing one.')); + } else { + this.onError(error); + } + }.bind(this); + + openRequest.onsuccess = function (event) { + + if (preventSuccessCallback) { + return; + } + + if(this.db){ + this.onStoreReady(); + return; + } + + this.db = event.target.result; + + if(typeof this.db.version == 'string'){ + this.onError(new Error('The IndexedDB implementation in this browser is outdated. Please upgrade your browser.')); + return; + } + + if(!this.db.objectStoreNames.contains(this.storeName)){ + // We should never ever get here. + // Lets notify the user anyway. + this.onError(new Error('Something is wrong with the IndexedDB implementation in this browser. Please upgrade your browser.')); + return; + } + + var emptyTransaction = this.db.transaction([this.storeName], this.consts.READ_ONLY); + this.store = emptyTransaction.objectStore(this.storeName); + + // check indexes + var existingIndexes = Array.prototype.slice.call(this.getIndexList()); + this.indexes.forEach(function(indexData){ + var indexName = indexData.name; + + if(!indexName){ + preventSuccessCallback = true; + this.onError(new Error('Cannot create index: No index name given.')); + return; + } + + this.normalizeIndexData(indexData); + + if(this.hasIndex(indexName)){ + // check if it complies + var actualIndex = this.store.index(indexName); + var complies = this.indexComplies(actualIndex, indexData); + if(!complies){ + preventSuccessCallback = true; + this.onError(new Error('Cannot modify index "' + indexName + '" for current version. Please bump version number to ' + ( this.dbVersion + 1 ) + '.')); + } + + existingIndexes.splice(existingIndexes.indexOf(indexName), 1); + } else { + preventSuccessCallback = true; + this.onError(new Error('Cannot create new index "' + indexName + '" for current version. Please bump version number to ' + ( this.dbVersion + 1 ) + '.')); + } + + }, this); + + if (existingIndexes.length) { + preventSuccessCallback = true; + this.onError(new Error('Cannot delete index(es) "' + existingIndexes.toString() + '" for current version. Please bump version number to ' + ( this.dbVersion + 1 ) + '.')); + } + + preventSuccessCallback || this.onStoreReady(); + }.bind(this); + + openRequest.onupgradeneeded = function(/* IDBVersionChangeEvent */ event){ + + this.db = event.target.result; + + if(this.db.objectStoreNames.contains(this.storeName)){ + this.store = event.target.transaction.objectStore(this.storeName); + } else { + var optionalParameters = { autoIncrement: this.autoIncrement }; + if (this.keyPath !== null) { + optionalParameters.keyPath = this.keyPath; + } + this.store = this.db.createObjectStore(this.storeName, optionalParameters); + } + + var existingIndexes = Array.prototype.slice.call(this.getIndexList()); + this.indexes.forEach(function(indexData){ + var indexName = indexData.name; + + if(!indexName){ + preventSuccessCallback = true; + this.onError(new Error('Cannot create index: No index name given.')); + } + + this.normalizeIndexData(indexData); + + if(this.hasIndex(indexName)){ + // check if it complies + var actualIndex = this.store.index(indexName); + var complies = this.indexComplies(actualIndex, indexData); + if(!complies){ + // index differs, need to delete and re-create + this.store.deleteIndex(indexName); + this.store.createIndex(indexName, indexData.keyPath, { unique: indexData.unique, multiEntry: indexData.multiEntry }); + } + + existingIndexes.splice(existingIndexes.indexOf(indexName), 1); + } else { + this.store.createIndex(indexName, indexData.keyPath, { unique: indexData.unique, multiEntry: indexData.multiEntry }); + } + + }, this); + + if (existingIndexes.length) { + existingIndexes.forEach(function(_indexName){ + this.store.deleteIndex(_indexName); + }, this); + } + + }.bind(this); + }, + + /** + * Deletes the database used for this store if the IDB implementations + * provides that functionality. + */ + deleteDatabase: function () { + if (this.idb.deleteDatabase) { + this.idb.deleteDatabase(this.dbName); + } + }, + + /********************* + * data manipulation * + *********************/ + + /** + * Puts an object into the store. If an entry with the given id exists, + * it will be overwritten. This method has a different signature for inline + * keys and out-of-line keys; please see the examples below. + * + * @param {*} [key] The key to store. This is only needed if IDBWrapper + * is set to use out-of-line keys. For inline keys - the default scenario - + * this can be omitted. + * @param {Object} value The data object to store. + * @param {Function} [onSuccess] A callback that is called if insertion + * was successful. + * @param {Function} [onError] A callback that is called if insertion + * failed. + * @returns {IDBTransaction} The transaction used for this operation. + * @example + // Storing an object, using inline keys (the default scenario): + var myCustomer = { + customerid: 2346223, + lastname: 'Doe', + firstname: 'John' + }; + myCustomerStore.put(myCustomer, mySuccessHandler, myErrorHandler); + // Note that passing success- and error-handlers is optional. + * @example + // Storing an object, using out-of-line keys: + var myCustomer = { + lastname: 'Doe', + firstname: 'John' + }; + myCustomerStore.put(2346223, myCustomer, mySuccessHandler, myErrorHandler); + // Note that passing success- and error-handlers is optional. + */ + put: function (key, value, onSuccess, onError) { + if (this.keyPath !== null) { + onError = onSuccess; + onSuccess = value; + value = key; + } + onError || (onError = defaultErrorHandler); + onSuccess || (onSuccess = noop); + + var hasSuccess = false, + result = null, + putRequest; + + var putTransaction = this.db.transaction([this.storeName], this.consts.READ_WRITE); + putTransaction.oncomplete = function () { + var callback = hasSuccess ? onSuccess : onError; + callback(result); + }; + putTransaction.onabort = onError; + putTransaction.onerror = onError; + + if (this.keyPath !== null) { // in-line keys + this._addIdPropertyIfNeeded(value); + putRequest = putTransaction.objectStore(this.storeName).put(value); + } else { // out-of-line keys + putRequest = putTransaction.objectStore(this.storeName).put(value, key); + } + putRequest.onsuccess = function (event) { + hasSuccess = true; + result = event.target.result; + }; + putRequest.onerror = onError; + + return putTransaction; + }, + + /** + * Retrieves an object from the store. If no entry exists with the given id, + * the success handler will be called with null as first and only argument. + * + * @param {*} key The id of the object to fetch. + * @param {Function} [onSuccess] A callback that is called if fetching + * was successful. Will receive the object as only argument. + * @param {Function} [onError] A callback that will be called if an error + * occurred during the operation. + * @returns {IDBTransaction} The transaction used for this operation. + */ + get: function (key, onSuccess, onError) { + onError || (onError = defaultErrorHandler); + onSuccess || (onSuccess = noop); + + var hasSuccess = false, + result = null; + + var getTransaction = this.db.transaction([this.storeName], this.consts.READ_ONLY); + getTransaction.oncomplete = function () { + var callback = hasSuccess ? onSuccess : onError; + callback(result); + }; + getTransaction.onabort = onError; + getTransaction.onerror = onError; + var getRequest = getTransaction.objectStore(this.storeName).get(key); + getRequest.onsuccess = function (event) { + hasSuccess = true; + result = event.target.result; + }; + getRequest.onerror = onError; + + return getTransaction; + }, + + /** + * Removes an object from the store. + * + * @param {*} key The id of the object to remove. + * @param {Function} [onSuccess] A callback that is called if the removal + * was successful. + * @param {Function} [onError] A callback that will be called if an error + * occurred during the operation. + * @returns {IDBTransaction} The transaction used for this operation. + */ + remove: function (key, onSuccess, onError) { + onError || (onError = defaultErrorHandler); + onSuccess || (onSuccess = noop); + + var hasSuccess = false, + result = null; + + var removeTransaction = this.db.transaction([this.storeName], this.consts.READ_WRITE); + removeTransaction.oncomplete = function () { + var callback = hasSuccess ? onSuccess : onError; + callback(result); + }; + removeTransaction.onabort = onError; + removeTransaction.onerror = onError; + + var deleteRequest = removeTransaction.objectStore(this.storeName)['delete'](key); + deleteRequest.onsuccess = function (event) { + hasSuccess = true; + result = event.target.result; + }; + deleteRequest.onerror = onError; + + return removeTransaction; + }, + + /** + * Runs a batch of put and/or remove operations on the store. + * + * @param {Array} dataArray An array of objects containing the operation to run + * and the data object (for put operations). + * @param {Function} [onSuccess] A callback that is called if all operations + * were successful. + * @param {Function} [onError] A callback that is called if an error + * occurred during one of the operations. + * @returns {IDBTransaction} The transaction used for this operation. + */ + batch: function (dataArray, onSuccess, onError) { + onError || (onError = defaultErrorHandler); + onSuccess || (onSuccess = noop); + + if(Object.prototype.toString.call(dataArray) != '[object Array]'){ + onError(new Error('dataArray argument must be of type Array.')); + } + var batchTransaction = this.db.transaction([this.storeName] , this.consts.READ_WRITE); + batchTransaction.oncomplete = function () { + var callback = hasSuccess ? onSuccess : onError; + callback(hasSuccess); + }; + batchTransaction.onabort = onError; + batchTransaction.onerror = onError; + + var count = dataArray.length; + var called = false; + var hasSuccess = false; + + var onItemSuccess = function () { + count--; + if (count === 0 && !called) { + called = true; + hasSuccess = true; + } + }; + + dataArray.forEach(function (operation) { + var type = operation.type; + var key = operation.key; + var value = operation.value; + + var onItemError = function (err) { + batchTransaction.abort(); + if (!called) { + called = true; + onError(err, type, key); + } + }; + + if (type == 'remove') { + var deleteRequest = batchTransaction.objectStore(this.storeName)['delete'](key); + deleteRequest.onsuccess = onItemSuccess; + deleteRequest.onerror = onItemError; + } else if (type == 'put') { + var putRequest; + if (this.keyPath !== null) { // in-line keys + this._addIdPropertyIfNeeded(value); + putRequest = batchTransaction.objectStore(this.storeName).put(value); + } else { // out-of-line keys + putRequest = batchTransaction.objectStore(this.storeName).put(value, key); + } + putRequest.onsuccess = onItemSuccess; + putRequest.onerror = onItemError; + } + }, this); + + return batchTransaction; + }, + + /** + * Takes an array of objects and stores them in a single transaction. + * + * @param {Array} dataArray An array of objects to store + * @param {Function} [onSuccess] A callback that is called if all operations + * were successful. + * @param {Function} [onError] A callback that is called if an error + * occurred during one of the operations. + * @returns {IDBTransaction} The transaction used for this operation. + */ + putBatch: function (dataArray, onSuccess, onError) { + var batchData = dataArray.map(function(item){ + return { type: 'put', value: item }; + }); + + return this.batch(batchData, onSuccess, onError); + }, + + /** + * Takes an array of keys and removes matching objects in a single + * transaction. + * + * @param {Array} keyArray An array of keys to remove + * @param {Function} [onSuccess] A callback that is called if all operations + * were successful. + * @param {Function} [onError] A callback that is called if an error + * occurred during one of the operations. + * @returns {IDBTransaction} The transaction used for this operation. + */ + removeBatch: function (keyArray, onSuccess, onError) { + var batchData = keyArray.map(function(key){ + return { type: 'remove', key: key }; + }); + + return this.batch(batchData, onSuccess, onError); + }, + + /** + * Takes an array of keys and fetches matching objects + * + * @param {Array} keyArray An array of keys identifying the objects to fetch + * @param {Function} [onSuccess] A callback that is called if all operations + * were successful. + * @param {Function} [onError] A callback that is called if an error + * occurred during one of the operations. + * @param {String} [arrayType='sparse'] The type of array to pass to the + * success handler. May be one of 'sparse', 'dense' or 'skip'. Defaults to + * 'sparse'. This parameter specifies how to handle the situation if a get + * operation did not throw an error, but there was no matching object in + * the database. In most cases, 'sparse' provides the most desired + * behavior. See the examples for details. + * @returns {IDBTransaction} The transaction used for this operation. + * @example + // given that there are two objects in the database with the keypath + // values 1 and 2, and the call looks like this: + myStore.getBatch([1, 5, 2], onError, function (data) { … }, arrayType); + + // this is what the `data` array will be like: + + // arrayType == 'sparse': + // data is a sparse array containing two entries and having a length of 3: + [Object, 2: Object] + 0: Object + 2: Object + length: 3 + __proto__: Array[0] + // calling forEach on data will result in the callback being called two + // times, with the index parameter matching the index of the key in the + // keyArray. + + // arrayType == 'dense': + // data is a dense array containing three entries and having a length of 3, + // where data[1] is of type undefined: + [Object, undefined, Object] + 0: Object + 1: undefined + 2: Object + length: 3 + __proto__: Array[0] + // calling forEach on data will result in the callback being called three + // times, with the index parameter matching the index of the key in the + // keyArray, but the second call will have undefined as first argument. + + // arrayType == 'skip': + // data is a dense array containing two entries and having a length of 2: + [Object, Object] + 0: Object + 1: Object + length: 2 + __proto__: Array[0] + // calling forEach on data will result in the callback being called two + // times, with the index parameter not matching the index of the key in the + // keyArray. + */ + getBatch: function (keyArray, onSuccess, onError, arrayType) { + onError || (onError = defaultErrorHandler); + onSuccess || (onSuccess = noop); + arrayType || (arrayType = 'sparse'); + + if(Object.prototype.toString.call(keyArray) != '[object Array]'){ + onError(new Error('keyArray argument must be of type Array.')); + } + var batchTransaction = this.db.transaction([this.storeName] , this.consts.READ_ONLY); + batchTransaction.oncomplete = function () { + var callback = hasSuccess ? onSuccess : onError; + callback(result); + }; + batchTransaction.onabort = onError; + batchTransaction.onerror = onError; + + var data = []; + var count = keyArray.length; + var called = false; + var hasSuccess = false; + var result = null; + + var onItemSuccess = function (event) { + if (event.target.result || arrayType == 'dense') { + data.push(event.target.result); + } else if (arrayType == 'sparse') { + data.length++; + } + count--; + if (count === 0) { + called = true; + hasSuccess = true; + result = data; + } + }; + + keyArray.forEach(function (key) { + + var onItemError = function (err) { + called = true; + result = err; + onError(err); + batchTransaction.abort(); + }; + + var getRequest = batchTransaction.objectStore(this.storeName).get(key); + getRequest.onsuccess = onItemSuccess; + getRequest.onerror = onItemError; + + }, this); + + return batchTransaction; + }, + + /** + * Fetches all entries in the store. + * + * @param {Function} [onSuccess] A callback that is called if the operation + * was successful. Will receive an array of objects. + * @param {Function} [onError] A callback that will be called if an error + * occurred during the operation. + * @returns {IDBTransaction} The transaction used for this operation. + */ + getAll: function (onSuccess, onError) { + onError || (onError = defaultErrorHandler); + onSuccess || (onSuccess = noop); + var getAllTransaction = this.db.transaction([this.storeName], this.consts.READ_ONLY); + var store = getAllTransaction.objectStore(this.storeName); + if (store.getAll) { + this._getAllNative(getAllTransaction, store, onSuccess, onError); + } else { + this._getAllCursor(getAllTransaction, store, onSuccess, onError); + } + + return getAllTransaction; + }, + + /** + * Implements getAll for IDB implementations that have a non-standard + * getAll() method. + * + * @param {Object} getAllTransaction An open READ transaction. + * @param {Object} store A reference to the store. + * @param {Function} onSuccess A callback that will be called if the + * operation was successful. + * @param {Function} onError A callback that will be called if an + * error occurred during the operation. + * @private + */ + _getAllNative: function (getAllTransaction, store, onSuccess, onError) { + var hasSuccess = false, + result = null; + + getAllTransaction.oncomplete = function () { + var callback = hasSuccess ? onSuccess : onError; + callback(result); + }; + getAllTransaction.onabort = onError; + getAllTransaction.onerror = onError; + + var getAllRequest = store.getAll(); + getAllRequest.onsuccess = function (event) { + hasSuccess = true; + result = event.target.result; + }; + getAllRequest.onerror = onError; + }, + + /** + * Implements getAll for IDB implementations that do not have a getAll() + * method. + * + * @param {Object} getAllTransaction An open READ transaction. + * @param {Object} store A reference to the store. + * @param {Function} onSuccess A callback that will be called if the + * operation was successful. + * @param {Function} onError A callback that will be called if an + * error occurred during the operation. + * @private + */ + _getAllCursor: function (getAllTransaction, store, onSuccess, onError) { + var all = [], + hasSuccess = false, + result = null; + + getAllTransaction.oncomplete = function () { + var callback = hasSuccess ? onSuccess : onError; + callback(result); + }; + getAllTransaction.onabort = onError; + getAllTransaction.onerror = onError; + + var cursorRequest = store.openCursor(); + cursorRequest.onsuccess = function (event) { + var cursor = event.target.result; + if (cursor) { + all.push(cursor.value); + cursor['continue'](); + } + else { + hasSuccess = true; + result = all; + } + }; + cursorRequest.onError = onError; + }, + + /** + * Clears the store, i.e. deletes all entries in the store. + * + * @param {Function} [onSuccess] A callback that will be called if the + * operation was successful. + * @param {Function} [onError] A callback that will be called if an + * error occurred during the operation. + * @returns {IDBTransaction} The transaction used for this operation. + */ + clear: function (onSuccess, onError) { + onError || (onError = defaultErrorHandler); + onSuccess || (onSuccess = noop); + + var hasSuccess = false, + result = null; + + var clearTransaction = this.db.transaction([this.storeName], this.consts.READ_WRITE); + clearTransaction.oncomplete = function () { + var callback = hasSuccess ? onSuccess : onError; + callback(result); + }; + clearTransaction.onabort = onError; + clearTransaction.onerror = onError; + + var clearRequest = clearTransaction.objectStore(this.storeName).clear(); + clearRequest.onsuccess = function (event) { + hasSuccess = true; + result = event.target.result; + }; + clearRequest.onerror = onError; + + return clearTransaction; + }, + + /** + * Checks if an id property needs to present on a object and adds one if + * necessary. + * + * @param {Object} dataObj The data object that is about to be stored + * @private + */ + _addIdPropertyIfNeeded: function (dataObj) { + if (!this.features.hasAutoIncrement && typeof dataObj[this.keyPath] == 'undefined') { + dataObj[this.keyPath] = this._insertIdCount++ + Date.now(); + } + }, + + /************ + * indexing * + ************/ + + /** + * Returns a DOMStringList of index names of the store. + * + * @return {DOMStringList} The list of index names + */ + getIndexList: function () { + return this.store.indexNames; + }, + + /** + * Checks if an index with the given name exists in the store. + * + * @param {String} indexName The name of the index to look for + * @return {Boolean} Whether the store contains an index with the given name + */ + hasIndex: function (indexName) { + return this.store.indexNames.contains(indexName); + }, + + /** + * Normalizes an object containing index data and assures that all + * properties are set. + * + * @param {Object} indexData The index data object to normalize + * @param {String} indexData.name The name of the index + * @param {String} [indexData.keyPath] The key path of the index + * @param {Boolean} [indexData.unique] Whether the index is unique + * @param {Boolean} [indexData.multiEntry] Whether the index is multi entry + */ + normalizeIndexData: function (indexData) { + indexData.keyPath = indexData.keyPath || indexData.name; + indexData.unique = !!indexData.unique; + indexData.multiEntry = !!indexData.multiEntry; + }, + + /** + * Checks if an actual index complies with an expected index. + * + * @param {Object} actual The actual index found in the store + * @param {Object} expected An Object describing an expected index + * @return {Boolean} Whether both index definitions are identical + */ + indexComplies: function (actual, expected) { + var complies = ['keyPath', 'unique', 'multiEntry'].every(function (key) { + // IE10 returns undefined for no multiEntry + if (key == 'multiEntry' && actual[key] === undefined && expected[key] === false) { + return true; + } + // Compound keys + if (key == 'keyPath' && Object.prototype.toString.call(expected[key]) == '[object Array]') { + var exp = expected.keyPath; + var act = actual.keyPath; + + // IE10 can't handle keyPath sequences and stores them as a string. + // The index will be unusable there, but let's still return true if + // the keyPath sequence matches. + if (typeof act == 'string') { + return exp.toString() == act; + } + + // Chrome/Opera stores keyPath squences as DOMStringList, Firefox + // as Array + if ( ! (typeof act.contains == 'function' || typeof act.indexOf == 'function') ) { + return false; + } + + if (act.length !== exp.length) { + return false; + } + + for (var i = 0, m = exp.length; i<m; i++) { + if ( ! ( (act.contains && act.contains(exp[i])) || act.indexOf(exp[i] !== -1) )) { + return false; + } + } + return true; + } + return expected[key] == actual[key]; + }); + return complies; + }, + + /********** + * cursor * + **********/ + + /** + * Iterates over the store using the given options and calling onItem + * for each entry matching the options. + * + * @param {Function} onItem A callback to be called for each match + * @param {Object} [options] An object defining specific options + * @param {Object} [options.index=null] An IDBIndex to operate on + * @param {String} [options.order=ASC] The order in which to provide the + * results, can be 'DESC' or 'ASC' + * @param {Boolean} [options.autoContinue=true] Whether to automatically + * iterate the cursor to the next result + * @param {Boolean} [options.filterDuplicates=false] Whether to exclude + * duplicate matches + * @param {Object} [options.keyRange=null] An IDBKeyRange to use + * @param {Boolean} [options.writeAccess=false] Whether grant write access + * to the store in the onItem callback + * @param {Function} [options.onEnd=null] A callback to be called after + * iteration has ended + * @param {Function} [options.onError=throw] A callback to be called + * if an error occurred during the operation. + * @returns {IDBTransaction} The transaction used for this operation. + */ + iterate: function (onItem, options) { + options = mixin({ + index: null, + order: 'ASC', + autoContinue: true, + filterDuplicates: false, + keyRange: null, + writeAccess: false, + onEnd: null, + onError: defaultErrorHandler + }, options || {}); + + var directionType = options.order.toLowerCase() == 'desc' ? 'PREV' : 'NEXT'; + if (options.filterDuplicates) { + directionType += '_NO_DUPLICATE'; + } + + var hasSuccess = false; + var cursorTransaction = this.db.transaction([this.storeName], this.consts[options.writeAccess ? 'READ_WRITE' : 'READ_ONLY']); + var cursorTarget = cursorTransaction.objectStore(this.storeName); + if (options.index) { + cursorTarget = cursorTarget.index(options.index); + } + + cursorTransaction.oncomplete = function () { + if (!hasSuccess) { + options.onError(null); + return; + } + if (options.onEnd) { + options.onEnd(); + } else { + onItem(null); + } + }; + cursorTransaction.onabort = options.onError; + cursorTransaction.onerror = options.onError; + + var cursorRequest = cursorTarget.openCursor(options.keyRange, this.consts[directionType]); + cursorRequest.onerror = options.onError; + cursorRequest.onsuccess = function (event) { + var cursor = event.target.result; + if (cursor) { + onItem(cursor.value, cursor, cursorTransaction); + if (options.autoContinue) { + cursor['continue'](); + } + } else { + hasSuccess = true; + } + }; + + return cursorTransaction; + }, + + /** + * Runs a query against the store and passes an array containing matched + * objects to the success handler. + * + * @param {Function} onSuccess A callback to be called when the operation + * was successful. + * @param {Object} [options] An object defining specific query options + * @param {Object} [options.index=null] An IDBIndex to operate on + * @param {String} [options.order=ASC] The order in which to provide the + * results, can be 'DESC' or 'ASC' + * @param {Boolean} [options.filterDuplicates=false] Whether to exclude + * duplicate matches + * @param {Object} [options.keyRange=null] An IDBKeyRange to use + * @param {Function} [options.onError=throw] A callback to be called if an error + * occurred during the operation. + * @returns {IDBTransaction} The transaction used for this operation. + */ + query: function (onSuccess, options) { + var result = []; + options = options || {}; + options.onEnd = function () { + onSuccess(result); + }; + return this.iterate(function (item) { + result.push(item); + }, options); + }, + + /** + * + * Runs a query against the store, but only returns the number of matches + * instead of the matches itself. + * + * @param {Function} onSuccess A callback to be called if the opration + * was successful. + * @param {Object} [options] An object defining specific options + * @param {Object} [options.index=null] An IDBIndex to operate on + * @param {Object} [options.keyRange=null] An IDBKeyRange to use + * @param {Function} [options.onError=throw] A callback to be called if an error + * occurred during the operation. + * @returns {IDBTransaction} The transaction used for this operation. + */ + count: function (onSuccess, options) { + + options = mixin({ + index: null, + keyRange: null + }, options || {}); + + var onError = options.onError || defaultErrorHandler; + + var hasSuccess = false, + result = null; + + var cursorTransaction = this.db.transaction([this.storeName], this.consts.READ_ONLY); + cursorTransaction.oncomplete = function () { + var callback = hasSuccess ? onSuccess : onError; + callback(result); + }; + cursorTransaction.onabort = onError; + cursorTransaction.onerror = onError; + + var cursorTarget = cursorTransaction.objectStore(this.storeName); + if (options.index) { + cursorTarget = cursorTarget.index(options.index); + } + var countRequest = cursorTarget.count(options.keyRange); + countRequest.onsuccess = function (evt) { + hasSuccess = true; + result = evt.target.result; + }; + countRequest.onError = onError; + + return cursorTransaction; + }, + + /**************/ + /* key ranges */ + /**************/ + + /** + * Creates a key range using specified options. This key range can be + * handed over to the count() and iterate() methods. + * + * Note: You must provide at least one or both of "lower" or "upper" value. + * + * @param {Object} options The options for the key range to create + * @param {*} [options.lower] The lower bound + * @param {Boolean} [options.excludeLower] Whether to exclude the lower + * bound passed in options.lower from the key range + * @param {*} [options.upper] The upper bound + * @param {Boolean} [options.excludeUpper] Whether to exclude the upper + * bound passed in options.upper from the key range + * @param {*} [options.only] A single key value. Use this if you need a key + * range that only includes one value for a key. Providing this + * property invalidates all other properties. + * @return {Object} The IDBKeyRange representing the specified options + */ + makeKeyRange: function(options){ + /*jshint onecase:true */ + var keyRange, + hasLower = typeof options.lower != 'undefined', + hasUpper = typeof options.upper != 'undefined', + isOnly = typeof options.only != 'undefined'; + + switch(true){ + case isOnly: + keyRange = this.keyRange.only(options.only); + break; + case hasLower && hasUpper: + keyRange = this.keyRange.bound(options.lower, options.upper, options.excludeLower, options.excludeUpper); + break; + case hasLower: + keyRange = this.keyRange.lowerBound(options.lower, options.excludeLower); + break; + case hasUpper: + keyRange = this.keyRange.upperBound(options.upper, options.excludeUpper); + break; + default: + throw new Error('Cannot create KeyRange. Provide one or both of "lower" or "upper" value, or an "only" value.'); + } + + return keyRange; + + } + + }; + + /** helpers **/ + + var noop = function () { + }; + var empty = {}; + var mixin = function (target, source) { + var name, s; + for (name in source) { + s = source[name]; + if (s !== empty[name] && s !== target[name]) { + target[name] = s; + } + } + return target; + }; + + IDBStore.version = IDBStore.prototype.version; + + return IDBStore; + +}, this); + +},{}],51:[function(_dereq_,module,exports){ +var Buffer = _dereq_('buffer').Buffer; + +module.exports = isBuffer; + +function isBuffer (o) { + return Buffer.isBuffer(o) + || /\[object (.+Array|Array.+)\]/.test(Object.prototype.toString.call(o)); +} + +},{"buffer":17}],52:[function(_dereq_,module,exports){ +(function (Buffer){ + +exports.compare = function (a, b) { + + if(Buffer.isBuffer(a)) { + var l = Math.min(a.length, b.length) + for(var i = 0; i < l; i++) { + var cmp = a[i] - b[i] + if(cmp) return cmp + } + return a.length - b.length + } + + return a < b ? -1 : a > b ? 1 : 0 +} + +function has(obj, key) { + return Object.hasOwnProperty.call(obj, key) +} + +// to be compatible with the current abstract-leveldown tests +// nullish or empty strings. +// I could use !!val but I want to permit numbers and booleans, +// if possible. + +function isDef (val) { + return val !== undefined && val !== '' +} + +function has (range, name) { + return Object.hasOwnProperty.call(range, name) +} + +function hasKey(range, name) { + return Object.hasOwnProperty.call(range, name) && name +} + +var lowerBoundKey = exports.lowerBoundKey = function (range) { + return ( + hasKey(range, 'gt') + || hasKey(range, 'gte') + || hasKey(range, 'min') + || (range.reverse ? hasKey(range, 'end') : hasKey(range, 'start')) + || undefined + ) +} + +var lowerBound = exports.lowerBound = function (range) { + var k = lowerBoundKey(range) + return k && range[k] + return ( + has(range, 'gt') ? range.gt + : has(range, 'gte') ? range.gte + : has(range, 'min') ? range.min + : has(range, 'start') && !range.reverse ? range.start + : has(range, 'end') && range.reverse ? range.end + : undefined + ) +} + +exports.lowerBoundInclusive = function (range) { + return has(range, 'gt') ? false : true +} + +exports.upperBoundInclusive = + function (range) { + return has(range, 'lt') || !range.minEx ? false : true + } + +var lowerBoundExclusive = exports.lowerBoundExclusive = + function (range) { + return has(range, 'gt') || range.minEx ? true : false + } + +var upperBoundExclusive = exports.upperBoundExclusive = + function (range) { + return has(range, 'lt') ? true : false + } + +var upperBoundKey = exports.upperBoundKey = function (range) { + return ( + hasKey(range, 'lt') + || hasKey(range, 'lte') + || hasKey(range, 'max') + || (range.reverse ? hasKey(range, 'start') : hasKey(range, 'end')) + || undefined + ) +} + +var upperBound = exports.upperBound = function (range) { + var k = upperBoundKey(range) + return k && range[k] +} + +function id (e) { return e } + +exports.toLtgt = function (range, _range, map, lower, upper) { + _range = _range || {} + map = map || id + var defaults = arguments.length > 3 + var lb = exports.lowerBoundKey(range) + var ub = exports.upperBoundKey(range) + if(lb) { + if(lb === 'gt') _range.gt = map(range.gt) + else _range.gte = map(range[lb]) + } + else if(defaults) + _range.gte = lower + + if(ub) { + if(ub === 'lt') _range.lt = map(range.lt) + else _range.lte = map(range[ub]) + } + else if(defaults) + _range.lte = upper + + _range.reverse = !!range.reverse + + return _range +} + +exports.contains = function (range, key, compare) { + compare = compare || exports.compare + + var lb = lowerBound(range) + if(isDef(lb)) { + var cmp = compare(key, lb) + if(cmp < 0 || (cmp === 0 && lowerBoundExclusive(range))) + return false + } + + var ub = upperBound(range) + if(isDef(ub)) { + var cmp = compare(key, ub) + if(cmp > 0 || (cmp === 0) && upperBoundExclusive(range)) + return false + } + + return true +} + +exports.filter = function (range, compare) { + return function (key) { + return exports.contains(range, key, compare) + } +} + +}).call(this,_dereq_("buffer").Buffer) +},{"buffer":17}],53:[function(_dereq_,module,exports){ +(function (Buffer){ +/** + * Convert a typed array to a Buffer without a copy + * + * Author: Feross Aboukhadijeh <feross@feross.org> <http://feross.org> + * License: MIT + * + * `npm install typedarray-to-buffer` + */ + +module.exports = function (arr) { + if (typeof Buffer._augment === 'function' && Buffer.TYPED_ARRAY_SUPPORT) { + // If `Buffer` is from the `buffer` module and this browser supports typed arrays, + // then augment it with all the `Buffer` methods. + return Buffer._augment(arr) + } else { + // Otherwise, fallback to creating a `Buffer` with a copy. + return new Buffer(arr) + } +} + +}).call(this,_dereq_("buffer").Buffer) +},{"buffer":17}],54:[function(_dereq_,module,exports){ +module.exports = hasKeys + +function hasKeys(source) { + return source !== null && + (typeof source === "object" || + typeof source === "function") +} + +},{}],55:[function(_dereq_,module,exports){ +var Keys = _dereq_("object-keys") +var hasKeys = _dereq_("./has-keys") + +module.exports = extend + +function extend() { + var target = {} + + for (var i = 0; i < arguments.length; i++) { + var source = arguments[i] + + if (!hasKeys(source)) { + continue + } + + var keys = Keys(source) + + for (var j = 0; j < keys.length; j++) { + var name = keys[j] + target[name] = source[name] + } + } + + return target +} + +},{"./has-keys":54,"object-keys":57}],56:[function(_dereq_,module,exports){ +var hasOwn = Object.prototype.hasOwnProperty; +var toString = Object.prototype.toString; + +var isFunction = function (fn) { + var isFunc = (typeof fn === 'function' && !(fn instanceof RegExp)) || toString.call(fn) === '[object Function]'; + if (!isFunc && typeof window !== 'undefined') { + isFunc = fn === window.setTimeout || fn === window.alert || fn === window.confirm || fn === window.prompt; + } + return isFunc; +}; + +module.exports = function forEach(obj, fn) { + if (!isFunction(fn)) { + throw new TypeError('iterator must be a function'); + } + var i, k, + isString = typeof obj === 'string', + l = obj.length, + context = arguments.length > 2 ? arguments[2] : null; + if (l === +l) { + for (i = 0; i < l; i++) { + if (context === null) { + fn(isString ? obj.charAt(i) : obj[i], i, obj); + } else { + fn.call(context, isString ? obj.charAt(i) : obj[i], i, obj); + } + } + } else { + for (k in obj) { + if (hasOwn.call(obj, k)) { + if (context === null) { + fn(obj[k], k, obj); + } else { + fn.call(context, obj[k], k, obj); + } + } + } + } +}; + + +},{}],57:[function(_dereq_,module,exports){ +module.exports = Object.keys || _dereq_('./shim'); + + +},{"./shim":59}],58:[function(_dereq_,module,exports){ +var toString = Object.prototype.toString; + +module.exports = function isArguments(value) { + var str = toString.call(value); + var isArguments = str === '[object Arguments]'; + if (!isArguments) { + isArguments = str !== '[object Array]' + && value !== null + && typeof value === 'object' + && typeof value.length === 'number' + && value.length >= 0 + && toString.call(value.callee) === '[object Function]'; + } + return isArguments; +}; + + +},{}],59:[function(_dereq_,module,exports){ +(function () { + "use strict"; + + // modified from https://github.com/kriskowal/es5-shim + var has = Object.prototype.hasOwnProperty, + toString = Object.prototype.toString, + forEach = _dereq_('./foreach'), + isArgs = _dereq_('./isArguments'), + hasDontEnumBug = !({'toString': null}).propertyIsEnumerable('toString'), + hasProtoEnumBug = (function () {}).propertyIsEnumerable('prototype'), + dontEnums = [ + "toString", + "toLocaleString", + "valueOf", + "hasOwnProperty", + "isPrototypeOf", + "propertyIsEnumerable", + "constructor" + ], + keysShim; + + keysShim = function keys(object) { + var isObject = object !== null && typeof object === 'object', + isFunction = toString.call(object) === '[object Function]', + isArguments = isArgs(object), + theKeys = []; + + if (!isObject && !isFunction && !isArguments) { + throw new TypeError("Object.keys called on a non-object"); + } + + if (isArguments) { + forEach(object, function (value) { + theKeys.push(value); + }); + } else { + var name, + skipProto = hasProtoEnumBug && isFunction; + + for (name in object) { + if (!(skipProto && name === 'prototype') && has.call(object, name)) { + theKeys.push(name); + } + } + } + + if (hasDontEnumBug) { + var ctor = object.constructor, + skipConstructor = ctor && ctor.prototype === object; + + forEach(dontEnums, function (dontEnum) { + if (!(skipConstructor && dontEnum === 'constructor') && has.call(object, dontEnum)) { + theKeys.push(dontEnum); + } + }); + } + return theKeys; + }; + + module.exports = keysShim; +}()); + + +},{"./foreach":56,"./isArguments":58}],60:[function(_dereq_,module,exports){ +function addOperation (type, key, value, options) { + var operation = { + type: type, + key: key, + value: value, + options: options + } + + if (options && options.prefix) { + operation.prefix = options.prefix + delete options.prefix + } + + this._operations.push(operation) + + return this +} + +function Batch(sdb) { + this._operations = [] + this._sdb = sdb + + this.put = addOperation.bind(this, 'put') + this.del = addOperation.bind(this, 'del') +} + +var B = Batch.prototype + + +B.clear = function () { + this._operations = [] +} + +B.write = function (cb) { + this._sdb.batch(this._operations, cb) +} + +module.exports = Batch + +},{}],61:[function(_dereq_,module,exports){ +(function (process){ +var EventEmitter = _dereq_('events').EventEmitter +var next = process.nextTick +var SubDb = _dereq_('./sub') +var Batch = _dereq_('./batch') +var fixRange = _dereq_('level-fix-range') + +var Hooks = _dereq_('level-hooks') + +module.exports = function (_db, options) { + function DB () {} + DB.prototype = _db + var db = new DB() + + if (db.sublevel) return db + + options = options || {} + + //use \xff (255) as the seperator, + //so that sections of the database will sort after the regular keys + var sep = options.sep = options.sep || '\xff' + db._options = options + + Hooks(db) + + db.sublevels = {} + + db.sublevel = function (prefix, options) { + if(db.sublevels[prefix]) + return db.sublevels[prefix] + return new SubDb(db, prefix, options || this._options) + } + + db.methods = {} + + db.prefix = function (key) { + return '' + (key || '') + } + + db.pre = function (range, hook) { + if(!hook) + hook = range, range = { + max : sep + } + return db.hooks.pre(range, hook) + } + + db.post = function (range, hook) { + if(!hook) + hook = range, range = { + max : sep + } + return db.hooks.post(range, hook) + } + + function safeRange(fun) { + return function (opts) { + opts = opts || {} + opts = fixRange(opts) + + if(opts.reverse) opts.start = opts.start || sep + else opts.end = opts.end || sep + + return fun.call(db, opts) + } + } + + db.readStream = + db.createReadStream = safeRange(db.createReadStream) + db.keyStream = + db.createKeyStream = safeRange(db.createKeyStream) + db.valuesStream = + db.createValueStream = safeRange(db.createValueStream) + + var batch = db.batch + db.batch = function (changes, opts, cb) { + if(!Array.isArray(changes)) + return new Batch(db) + changes.forEach(function (e) { + if(e.prefix) { + if('function' === typeof e.prefix.prefix) + e.key = e.prefix.prefix(e.key) + else if('string' === typeof e.prefix) + e.key = e.prefix + e.key + } + }) + batch.call(db, changes, opts, cb) + } + return db +} + + +}).call(this,_dereq_('_process')) +},{"./batch":60,"./sub":72,"_process":24,"events":21,"level-fix-range":62,"level-hooks":64}],62:[function(_dereq_,module,exports){ +var clone = _dereq_('clone') + +module.exports = +function fixRange(opts) { + opts = clone(opts) + + var reverse = opts.reverse + var end = opts.max || opts.end + var start = opts.min || opts.start + + var range = [start, end] + if(start != null && end != null) + range.sort() + if(reverse) + range = range.reverse() + + opts.start = range[0] + opts.end = range[1] + + delete opts.min + delete opts.max + + return opts +} + +},{"clone":63}],63:[function(_dereq_,module,exports){ +(function (Buffer){ +'use strict'; + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + +// shim for Node's 'util' package +// DO NOT REMOVE THIS! It is required for compatibility with EnderJS (http://enderjs.com/). +var util = { + isArray: function (ar) { + return Array.isArray(ar) || (typeof ar === 'object' && objectToString(ar) === '[object Array]'); + }, + isDate: function (d) { + return typeof d === 'object' && objectToString(d) === '[object Date]'; + }, + isRegExp: function (re) { + return typeof re === 'object' && objectToString(re) === '[object RegExp]'; + }, + getRegExpFlags: function (re) { + var flags = ''; + re.global && (flags += 'g'); + re.ignoreCase && (flags += 'i'); + re.multiline && (flags += 'm'); + return flags; + } +}; + + +if (typeof module === 'object') + module.exports = clone; + +/** + * Clones (copies) an Object using deep copying. + * + * This function supports circular references by default, but if you are certain + * there are no circular references in your object, you can save some CPU time + * by calling clone(obj, false). + * + * Caution: if `circular` is false and `parent` contains circular references, + * your program may enter an infinite loop and crash. + * + * @param `parent` - the object to be cloned + * @param `circular` - set to true if the object to be cloned may contain + * circular references. (optional - true by default) + * @param `depth` - set to a number if the object is only to be cloned to + * a particular depth. (optional - defaults to Infinity) + * @param `prototype` - sets the prototype to be used when cloning an object. + * (optional - defaults to parent prototype). +*/ + +function clone(parent, circular, depth, prototype) { + // maintain two arrays for circular references, where corresponding parents + // and children have the same index + var allParents = []; + var allChildren = []; + + var useBuffer = typeof Buffer != 'undefined'; + + if (typeof circular == 'undefined') + circular = true; + + if (typeof depth == 'undefined') + depth = Infinity; + + // recurse this function so we don't reset allParents and allChildren + function _clone(parent, depth) { + // cloning null always returns null + if (parent === null) + return null; + + if (depth == 0) + return parent; + + var child; + var proto; + if (typeof parent != 'object') { + return parent; + } + + if (util.isArray(parent)) { + child = []; + } else if (util.isRegExp(parent)) { + child = new RegExp(parent.source, util.getRegExpFlags(parent)); + if (parent.lastIndex) child.lastIndex = parent.lastIndex; + } else if (util.isDate(parent)) { + child = new Date(parent.getTime()); + } else if (useBuffer && Buffer.isBuffer(parent)) { + child = new Buffer(parent.length); + parent.copy(child); + return child; + } else { + if (typeof prototype == 'undefined') { + proto = Object.getPrototypeOf(parent); + child = Object.create(proto); + } + else { + child = Object.create(prototype); + proto = prototype; + } + } + + if (circular) { + var index = allParents.indexOf(parent); + + if (index != -1) { + return allChildren[index]; + } + allParents.push(parent); + allChildren.push(child); + } + + for (var i in parent) { + var attrs; + if (proto) { + attrs = Object.getOwnPropertyDescriptor(proto, i); + } + + if (attrs && attrs.set == null) { + continue; + } + child[i] = _clone(parent[i], depth - 1); + } + + return child; + } + + return _clone(parent, depth); +} + +/** + * Simple flat clone using prototype, accepts only objects, usefull for property + * override on FLAT configuration object (no nested props). + * + * USE WITH CAUTION! This may not behave as you wish if you do not know how this + * works. + */ +clone.clonePrototype = function(parent) { + if (parent === null) + return null; + + var c = function () {}; + c.prototype = parent; + return new c(); +}; + +}).call(this,_dereq_("buffer").Buffer) +},{"buffer":17}],64:[function(_dereq_,module,exports){ +var ranges = _dereq_('string-range') + +module.exports = function (db) { + + if(db.hooks) { + return + } + + var posthooks = [] + var prehooks = [] + + function getPrefix (p) { + return p && ( + 'string' === typeof p ? p + : 'string' === typeof p.prefix ? p.prefix + : 'function' === typeof p.prefix ? p.prefix() + : '' + ) + } + + function getKeyEncoding (db) { + if(db && db._getKeyEncoding) + return db._getKeyEncoding(db) + } + + function getValueEncoding (db) { + if(db && db._getValueEncoding) + return db._getValueEncoding(db) + } + + function remover (array, item) { + return function () { + var i = array.indexOf(item) + if(!~i) return false + array.splice(i, 1) + return true + } + } + + db.hooks = { + post: function (prefix, hook) { + if(!hook) hook = prefix, prefix = '' + var h = {test: ranges.checker(prefix), hook: hook} + posthooks.push(h) + return remover(posthooks, h) + }, + pre: function (prefix, hook) { + if(!hook) hook = prefix, prefix = '' + var h = { + test: ranges.checker(prefix), + hook: hook, + safe: false !== prefix.safe + } + prehooks.push(h) + return remover(prehooks, h) + }, + posthooks: posthooks, + prehooks: prehooks + } + + //POST HOOKS + + function each (e) { + if(e && e.type) { + posthooks.forEach(function (h) { + if(h.test(e.key)) h.hook(e) + }) + } + } + + db.on('put', function (key, val) { + each({type: 'put', key: key, value: val}) + }) + db.on('del', function (key, val) { + each({type: 'del', key: key, value: val}) + }) + db.on('batch', function onBatch (ary) { + ary.forEach(each) + }) + + //PRE HOOKS + + var put = db.put + var del = db.del + var batch = db.batch + + function callHooks (isBatch, b, opts, cb) { + try { + b.forEach(function hook(e, i) { + prehooks.forEach(function (h) { + if(h.test(String(e.key))) { + //optimize this? + //maybe faster to not create a new object each time? + //have one object and expose scope to it? + var context = { + add: function (ch, db) { + if(typeof ch === 'undefined') { + return this + } + if(ch === false) + return delete b[i] + var prefix = ( + getPrefix(ch.prefix) || + getPrefix(db) || + h.prefix || '' + ) + //don't leave a circular json object there incase using multilevel. + if(prefix) ch.prefix = prefix + ch.key = prefix + ch.key + if(h.safe && h.test(String(ch.key))) { + //this usually means a stack overflow. + throw new Error('prehook cannot insert into own range') + } + var ke = ch.keyEncoding || getKeyEncoding(ch.prefix) + var ve = ch.valueEncoding || getValueEncoding(ch.prefix) + if(ke) ch.keyEncoding = ke + if(ve) ch.valueEncoding = ve + + b.push(ch) + hook(ch, b.length - 1) + return this + }, + put: function (ch, db) { + if('object' === typeof ch) ch.type = 'put' + return this.add(ch, db) + }, + del: function (ch, db) { + if('object' === typeof ch) ch.type = 'del' + return this.add(ch, db) + }, + veto: function () { + return this.add(false) + } + } + h.hook.call(context, e, context.add, b) + } + }) + }) + } catch (err) { + return (cb || opts)(err) + } + b = b.filter(function (e) { + return e && e.type //filter out empty items + }) + + if(b.length == 1 && !isBatch) { + var change = b[0] + return change.type == 'put' + ? put.call(db, change.key, change.value, opts, cb) + : del.call(db, change.key, opts, cb) + } + return batch.call(db, b, opts, cb) + } + + db.put = function (key, value, opts, cb ) { + var batch = [{key: key, value: value, type: 'put'}] + return callHooks(false, batch, opts, cb) + } + + db.del = function (key, opts, cb) { + var batch = [{key: key, type: 'del'}] + return callHooks(false, batch, opts, cb) + } + + db.batch = function (batch, opts, cb) { + return callHooks(true, batch, opts, cb) + } +} + +},{"string-range":65}],65:[function(_dereq_,module,exports){ + +//force to a valid range +var range = exports.range = function (obj) { + return null == obj ? {} : 'string' === typeof range ? { + min: range, max: range + '\xff' + } : obj +} + +//turn into a sub range. +var prefix = exports.prefix = function (range, within, term) { + range = exports.range(range) + var _range = {} + term = term || '\xff' + if(range instanceof RegExp || 'function' == typeof range) { + _range.min = within + _range.max = within + term, + _range.inner = function (k) { + var j = k.substring(within.length) + if(range.test) + return range.test(j) + return range(j) + } + } + else if('object' === typeof range) { + _range.min = within + (range.min || range.start || '') + _range.max = within + (range.max || range.end || (term || '~')) + _range.reverse = !!range.reverse + } + return _range +} + +//return a function that checks a range +var checker = exports.checker = function (range) { + if(!range) range = {} + + if ('string' === typeof range) + return function (key) { + return key.indexOf(range) == 0 + } + else if(range instanceof RegExp) + return function (key) { + return range.test(key) + } + else if('object' === typeof range) + return function (key) { + var min = range.min || range.start + var max = range.max || range.end + + // fixes keys passed as ints from sublevels + key = String(key) + + return ( + !min || key >= min + ) && ( + !max || key <= max + ) && ( + !range.inner || ( + range.inner.test + ? range.inner.test(key) + : range.inner(key) + ) + ) + } + else if('function' === typeof range) + return range +} +//check if a key is within a range. +var satifies = exports.satisfies = function (key, range) { + return checker(range)(key) +} + + + +},{}],66:[function(_dereq_,module,exports){ +module.exports=_dereq_(54) +},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/has-keys.js":54}],67:[function(_dereq_,module,exports){ +arguments[4][55][0].apply(exports,arguments) +},{"./has-keys":66,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/index.js":55,"object-keys":68}],68:[function(_dereq_,module,exports){ +arguments[4][57][0].apply(exports,arguments) +},{"./shim":71,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/index.js":57}],69:[function(_dereq_,module,exports){ + +var hasOwn = Object.prototype.hasOwnProperty; +var toString = Object.prototype.toString; + +module.exports = function forEach (obj, fn, ctx) { + if (toString.call(fn) !== '[object Function]') { + throw new TypeError('iterator must be a function'); + } + var l = obj.length; + if (l === +l) { + for (var i = 0; i < l; i++) { + fn.call(ctx, obj[i], i, obj); + } + } else { + for (var k in obj) { + if (hasOwn.call(obj, k)) { + fn.call(ctx, obj[k], k, obj); + } + } + } +}; + + +},{}],70:[function(_dereq_,module,exports){ + +/**! + * is + * the definitive JavaScript type testing library + * + * @copyright 2013 Enrico Marino + * @license MIT + */ + +var objProto = Object.prototype; +var owns = objProto.hasOwnProperty; +var toString = objProto.toString; +var isActualNaN = function (value) { + return value !== value; +}; +var NON_HOST_TYPES = { + "boolean": 1, + "number": 1, + "string": 1, + "undefined": 1 +}; + +/** + * Expose `is` + */ + +var is = module.exports = {}; + +/** + * Test general. + */ + +/** + * is.type + * Test if `value` is a type of `type`. + * + * @param {Mixed} value value to test + * @param {String} type type + * @return {Boolean} true if `value` is a type of `type`, false otherwise + * @api public + */ + +is.a = +is.type = function (value, type) { + return typeof value === type; +}; + +/** + * is.defined + * Test if `value` is defined. + * + * @param {Mixed} value value to test + * @return {Boolean} true if 'value' is defined, false otherwise + * @api public + */ + +is.defined = function (value) { + return value !== undefined; +}; + +/** + * is.empty + * Test if `value` is empty. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is empty, false otherwise + * @api public + */ + +is.empty = function (value) { + var type = toString.call(value); + var key; + + if ('[object Array]' === type || '[object Arguments]' === type) { + return value.length === 0; + } + + if ('[object Object]' === type) { + for (key in value) if (owns.call(value, key)) return false; + return true; + } + + if ('[object String]' === type) { + return '' === value; + } + + return false; +}; + +/** + * is.equal + * Test if `value` is equal to `other`. + * + * @param {Mixed} value value to test + * @param {Mixed} other value to compare with + * @return {Boolean} true if `value` is equal to `other`, false otherwise + */ + +is.equal = function (value, other) { + var type = toString.call(value) + var key; + + if (type !== toString.call(other)) { + return false; + } + + if ('[object Object]' === type) { + for (key in value) { + if (!is.equal(value[key], other[key])) { + return false; + } + } + return true; + } + + if ('[object Array]' === type) { + key = value.length; + if (key !== other.length) { + return false; + } + while (--key) { + if (!is.equal(value[key], other[key])) { + return false; + } + } + return true; + } + + if ('[object Function]' === type) { + return value.prototype === other.prototype; + } + + if ('[object Date]' === type) { + return value.getTime() === other.getTime(); + } + + return value === other; +}; + +/** + * is.hosted + * Test if `value` is hosted by `host`. + * + * @param {Mixed} value to test + * @param {Mixed} host host to test with + * @return {Boolean} true if `value` is hosted by `host`, false otherwise + * @api public + */ + +is.hosted = function (value, host) { + var type = typeof host[value]; + return type === 'object' ? !!host[value] : !NON_HOST_TYPES[type]; +}; + +/** + * is.instance + * Test if `value` is an instance of `constructor`. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is an instance of `constructor` + * @api public + */ + +is.instance = is['instanceof'] = function (value, constructor) { + return value instanceof constructor; +}; + +/** + * is.null + * Test if `value` is null. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is null, false otherwise + * @api public + */ + +is['null'] = function (value) { + return value === null; +}; + +/** + * is.undefined + * Test if `value` is undefined. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is undefined, false otherwise + * @api public + */ + +is.undefined = function (value) { + return value === undefined; +}; + +/** + * Test arguments. + */ + +/** + * is.arguments + * Test if `value` is an arguments object. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is an arguments object, false otherwise + * @api public + */ + +is.arguments = function (value) { + var isStandardArguments = '[object Arguments]' === toString.call(value); + var isOldArguments = !is.array(value) && is.arraylike(value) && is.object(value) && is.fn(value.callee); + return isStandardArguments || isOldArguments; +}; + +/** + * Test array. + */ + +/** + * is.array + * Test if 'value' is an array. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is an array, false otherwise + * @api public + */ + +is.array = function (value) { + return '[object Array]' === toString.call(value); +}; + +/** + * is.arguments.empty + * Test if `value` is an empty arguments object. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is an empty arguments object, false otherwise + * @api public + */ +is.arguments.empty = function (value) { + return is.arguments(value) && value.length === 0; +}; + +/** + * is.array.empty + * Test if `value` is an empty array. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is an empty array, false otherwise + * @api public + */ +is.array.empty = function (value) { + return is.array(value) && value.length === 0; +}; + +/** + * is.arraylike + * Test if `value` is an arraylike object. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is an arguments object, false otherwise + * @api public + */ + +is.arraylike = function (value) { + return !!value && !is.boolean(value) + && owns.call(value, 'length') + && isFinite(value.length) + && is.number(value.length) + && value.length >= 0; +}; + +/** + * Test boolean. + */ + +/** + * is.boolean + * Test if `value` is a boolean. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is a boolean, false otherwise + * @api public + */ + +is.boolean = function (value) { + return '[object Boolean]' === toString.call(value); +}; + +/** + * is.false + * Test if `value` is false. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is false, false otherwise + * @api public + */ + +is['false'] = function (value) { + return is.boolean(value) && (value === false || value.valueOf() === false); +}; + +/** + * is.true + * Test if `value` is true. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is true, false otherwise + * @api public + */ + +is['true'] = function (value) { + return is.boolean(value) && (value === true || value.valueOf() === true); +}; + +/** + * Test date. + */ + +/** + * is.date + * Test if `value` is a date. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is a date, false otherwise + * @api public + */ + +is.date = function (value) { + return '[object Date]' === toString.call(value); +}; + +/** + * Test element. + */ + +/** + * is.element + * Test if `value` is an html element. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is an HTML Element, false otherwise + * @api public + */ + +is.element = function (value) { + return value !== undefined + && typeof HTMLElement !== 'undefined' + && value instanceof HTMLElement + && value.nodeType === 1; +}; + +/** + * Test error. + */ + +/** + * is.error + * Test if `value` is an error object. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is an error object, false otherwise + * @api public + */ + +is.error = function (value) { + return '[object Error]' === toString.call(value); +}; + +/** + * Test function. + */ + +/** + * is.fn / is.function (deprecated) + * Test if `value` is a function. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is a function, false otherwise + * @api public + */ + +is.fn = is['function'] = function (value) { + var isAlert = typeof window !== 'undefined' && value === window.alert; + return isAlert || '[object Function]' === toString.call(value); +}; + +/** + * Test number. + */ + +/** + * is.number + * Test if `value` is a number. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is a number, false otherwise + * @api public + */ + +is.number = function (value) { + return '[object Number]' === toString.call(value); +}; + +/** + * is.infinite + * Test if `value` is positive or negative infinity. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is positive or negative Infinity, false otherwise + * @api public + */ +is.infinite = function (value) { + return value === Infinity || value === -Infinity; +}; + +/** + * is.decimal + * Test if `value` is a decimal number. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is a decimal number, false otherwise + * @api public + */ + +is.decimal = function (value) { + return is.number(value) && !isActualNaN(value) && !is.infinite(value) && value % 1 !== 0; +}; + +/** + * is.divisibleBy + * Test if `value` is divisible by `n`. + * + * @param {Number} value value to test + * @param {Number} n dividend + * @return {Boolean} true if `value` is divisible by `n`, false otherwise + * @api public + */ + +is.divisibleBy = function (value, n) { + var isDividendInfinite = is.infinite(value); + var isDivisorInfinite = is.infinite(n); + var isNonZeroNumber = is.number(value) && !isActualNaN(value) && is.number(n) && !isActualNaN(n) && n !== 0; + return isDividendInfinite || isDivisorInfinite || (isNonZeroNumber && value % n === 0); +}; + +/** + * is.int + * Test if `value` is an integer. + * + * @param value to test + * @return {Boolean} true if `value` is an integer, false otherwise + * @api public + */ + +is.int = function (value) { + return is.number(value) && !isActualNaN(value) && value % 1 === 0; +}; + +/** + * is.maximum + * Test if `value` is greater than 'others' values. + * + * @param {Number} value value to test + * @param {Array} others values to compare with + * @return {Boolean} true if `value` is greater than `others` values + * @api public + */ + +is.maximum = function (value, others) { + if (isActualNaN(value)) { + throw new TypeError('NaN is not a valid value'); + } else if (!is.arraylike(others)) { + throw new TypeError('second argument must be array-like'); + } + var len = others.length; + + while (--len >= 0) { + if (value < others[len]) { + return false; + } + } + + return true; +}; + +/** + * is.minimum + * Test if `value` is less than `others` values. + * + * @param {Number} value value to test + * @param {Array} others values to compare with + * @return {Boolean} true if `value` is less than `others` values + * @api public + */ + +is.minimum = function (value, others) { + if (isActualNaN(value)) { + throw new TypeError('NaN is not a valid value'); + } else if (!is.arraylike(others)) { + throw new TypeError('second argument must be array-like'); + } + var len = others.length; + + while (--len >= 0) { + if (value > others[len]) { + return false; + } + } + + return true; +}; + +/** + * is.nan + * Test if `value` is not a number. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is not a number, false otherwise + * @api public + */ + +is.nan = function (value) { + return !is.number(value) || value !== value; +}; + +/** + * is.even + * Test if `value` is an even number. + * + * @param {Number} value value to test + * @return {Boolean} true if `value` is an even number, false otherwise + * @api public + */ + +is.even = function (value) { + return is.infinite(value) || (is.number(value) && value === value && value % 2 === 0); +}; + +/** + * is.odd + * Test if `value` is an odd number. + * + * @param {Number} value value to test + * @return {Boolean} true if `value` is an odd number, false otherwise + * @api public + */ + +is.odd = function (value) { + return is.infinite(value) || (is.number(value) && value === value && value % 2 !== 0); +}; + +/** + * is.ge + * Test if `value` is greater than or equal to `other`. + * + * @param {Number} value value to test + * @param {Number} other value to compare with + * @return {Boolean} + * @api public + */ + +is.ge = function (value, other) { + if (isActualNaN(value) || isActualNaN(other)) { + throw new TypeError('NaN is not a valid value'); + } + return !is.infinite(value) && !is.infinite(other) && value >= other; +}; + +/** + * is.gt + * Test if `value` is greater than `other`. + * + * @param {Number} value value to test + * @param {Number} other value to compare with + * @return {Boolean} + * @api public + */ + +is.gt = function (value, other) { + if (isActualNaN(value) || isActualNaN(other)) { + throw new TypeError('NaN is not a valid value'); + } + return !is.infinite(value) && !is.infinite(other) && value > other; +}; + +/** + * is.le + * Test if `value` is less than or equal to `other`. + * + * @param {Number} value value to test + * @param {Number} other value to compare with + * @return {Boolean} if 'value' is less than or equal to 'other' + * @api public + */ + +is.le = function (value, other) { + if (isActualNaN(value) || isActualNaN(other)) { + throw new TypeError('NaN is not a valid value'); + } + return !is.infinite(value) && !is.infinite(other) && value <= other; +}; + +/** + * is.lt + * Test if `value` is less than `other`. + * + * @param {Number} value value to test + * @param {Number} other value to compare with + * @return {Boolean} if `value` is less than `other` + * @api public + */ + +is.lt = function (value, other) { + if (isActualNaN(value) || isActualNaN(other)) { + throw new TypeError('NaN is not a valid value'); + } + return !is.infinite(value) && !is.infinite(other) && value < other; +}; + +/** + * is.within + * Test if `value` is within `start` and `finish`. + * + * @param {Number} value value to test + * @param {Number} start lower bound + * @param {Number} finish upper bound + * @return {Boolean} true if 'value' is is within 'start' and 'finish' + * @api public + */ +is.within = function (value, start, finish) { + if (isActualNaN(value) || isActualNaN(start) || isActualNaN(finish)) { + throw new TypeError('NaN is not a valid value'); + } else if (!is.number(value) || !is.number(start) || !is.number(finish)) { + throw new TypeError('all arguments must be numbers'); + } + var isAnyInfinite = is.infinite(value) || is.infinite(start) || is.infinite(finish); + return isAnyInfinite || (value >= start && value <= finish); +}; + +/** + * Test object. + */ + +/** + * is.object + * Test if `value` is an object. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is an object, false otherwise + * @api public + */ + +is.object = function (value) { + return value && '[object Object]' === toString.call(value); +}; + +/** + * is.hash + * Test if `value` is a hash - a plain object literal. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is a hash, false otherwise + * @api public + */ + +is.hash = function (value) { + return is.object(value) && value.constructor === Object && !value.nodeType && !value.setInterval; +}; + +/** + * Test regexp. + */ + +/** + * is.regexp + * Test if `value` is a regular expression. + * + * @param {Mixed} value value to test + * @return {Boolean} true if `value` is a regexp, false otherwise + * @api public + */ + +is.regexp = function (value) { + return '[object RegExp]' === toString.call(value); +}; + +/** + * Test string. + */ + +/** + * is.string + * Test if `value` is a string. + * + * @param {Mixed} value value to test + * @return {Boolean} true if 'value' is a string, false otherwise + * @api public + */ + +is.string = function (value) { + return '[object String]' === toString.call(value); +}; + + +},{}],71:[function(_dereq_,module,exports){ +(function () { + "use strict"; + + // modified from https://github.com/kriskowal/es5-shim + var has = Object.prototype.hasOwnProperty, + is = _dereq_('is'), + forEach = _dereq_('foreach'), + hasDontEnumBug = !({'toString': null}).propertyIsEnumerable('toString'), + dontEnums = [ + "toString", + "toLocaleString", + "valueOf", + "hasOwnProperty", + "isPrototypeOf", + "propertyIsEnumerable", + "constructor" + ], + keysShim; + + keysShim = function keys(object) { + if (!is.object(object) && !is.array(object)) { + throw new TypeError("Object.keys called on a non-object"); + } + + var name, theKeys = []; + for (name in object) { + if (has.call(object, name)) { + theKeys.push(name); + } + } + + if (hasDontEnumBug) { + forEach(dontEnums, function (dontEnum) { + if (has.call(object, dontEnum)) { + theKeys.push(dontEnum); + } + }); + } + return theKeys; + }; + + module.exports = keysShim; +}()); + + +},{"foreach":69,"is":70}],72:[function(_dereq_,module,exports){ +var EventEmitter = _dereq_('events').EventEmitter +var inherits = _dereq_('util').inherits +var ranges = _dereq_('string-range') +var fixRange = _dereq_('level-fix-range') +var xtend = _dereq_('xtend') +var Batch = _dereq_('./batch') + +inherits(SubDB, EventEmitter) + +function SubDB (db, prefix, options) { + if('string' === typeof options) { + console.error('db.sublevel(name, seperator<string>) is depreciated') + console.error('use db.sublevel(name, {sep: separator})) if you must') + options = {sep: options} + } + if(!(this instanceof SubDB)) return new SubDB(db, prefix, options) + if(!db) throw new Error('must provide db') + if(!prefix) throw new Error('must provide prefix') + + options = options || {} + options.sep = options.sep || '\xff' + + this._parent = db + this._options = options + this.options = options + this._prefix = prefix + this._root = root(this) + db.sublevels[prefix] = this + this.sublevels = {} + this.methods = {} + var self = this + this.hooks = { + pre: function () { + return self.pre.apply(self, arguments) + }, + post: function () { + return self.post.apply(self, arguments) + } + } +} + +var SDB = SubDB.prototype + +SDB._key = function (key) { + var sep = this._options.sep + return sep + + this._prefix + + sep + + key +} + +SDB._getOptsAndCb = function (opts, cb) { + if (typeof opts == 'function') { + cb = opts + opts = {} + } + return { opts: xtend(opts, this._options), cb: cb } +} + +SDB.sublevel = function (prefix, options) { + if(this.sublevels[prefix]) + return this.sublevels[prefix] + return new SubDB(this, prefix, options || this._options) +} + +SDB.put = function (key, value, opts, cb) { + var res = this._getOptsAndCb(opts, cb) + this._root.put(this.prefix(key), value, res.opts, res.cb) +} + +SDB.get = function (key, opts, cb) { + var res = this._getOptsAndCb(opts, cb) + this._root.get(this.prefix(key), res.opts, res.cb) +} + +SDB.del = function (key, opts, cb) { + var res = this._getOptsAndCb(opts, cb) + this._root.del(this.prefix(key), res.opts, res.cb) +} + +SDB.batch = function (changes, opts, cb) { + if(!Array.isArray(changes)) + return new Batch(this) + var self = this, + res = this._getOptsAndCb(opts, cb) + changes.forEach(function (ch) { + + //OH YEAH, WE NEED TO VALIDATE THAT UPDATING THIS KEY/PREFIX IS ALLOWED + if('string' === typeof ch.prefix) + ch.key = ch.prefix + ch.key + else + ch.key = (ch.prefix || self).prefix(ch.key) + + if(ch.prefix) ch.prefix = null + }) + this._root.batch(changes, res.opts, res.cb) +} + +SDB._getKeyEncoding = function () { + if(this.options.keyEncoding) + return this.options.keyEncoding + if(this._parent && this._parent._getKeyEncoding) + return this._parent._getKeyEncoding() +} + +SDB._getValueEncoding = function () { + if(this.options.valueEncoding) + return this.options.valueEncoding + if(this._parent && this._parent._getValueEncoding) + return this._parent._getValueEncoding() +} + +SDB.prefix = function (key) { + var sep = this._options.sep + return this._parent.prefix() + sep + this._prefix + sep + (key || '') +} + +SDB.keyStream = +SDB.createKeyStream = function (opts) { + opts = opts || {} + opts.keys = true + opts.values = false + return this.createReadStream(opts) +} + +SDB.valueStream = +SDB.createValueStream = function (opts) { + opts = opts || {} + opts.keys = false + opts.values = true + opts.keys = false + return this.createReadStream(opts) +} + +function selectivelyMerge(_opts, opts) { + [ 'valueEncoding' + , 'encoding' + , 'keyEncoding' + , 'reverse' + , 'values' + , 'keys' + , 'limit' + , 'fillCache' + ] + .forEach(function (k) { + if (opts.hasOwnProperty(k)) _opts[k] = opts[k] + }) +} + +SDB.readStream = +SDB.createReadStream = function (opts) { + opts = opts || {} + var r = root(this) + var p = this.prefix() + + var _opts = ranges.prefix(opts, p) + selectivelyMerge(_opts, xtend(opts, this._options)) + + var s = r.createReadStream(_opts) + + if(_opts.values === false) { + var read = s.read + if (read) { + s.read = function (size) { + var val = read.call(this, size) + if (val) val = val.substring(p.length) + return val + } + } else { + var emit = s.emit + s.emit = function (event, val) { + if(event === 'data') { + emit.call(this, 'data', val.substring(p.length)) + } else + emit.call(this, event, val) + } + } + return s + } else if(_opts.keys === false) + return s + else { + var read = s.read + if (read) { + s.read = function (size) { + var d = read.call(this, size) + if (d) d.key = d.key.substring(p.length) + return d + } + } else { + s.on('data', function (d) { + //mutate the prefix! + //this doesn't work for createKeyStream admittedly. + d.key = d.key.substring(p.length) + }) + } + return s + } +} + + +SDB.writeStream = +SDB.createWriteStream = function () { + var r = root(this) + var p = this.prefix() + var ws = r.createWriteStream.apply(r, arguments) + var write = ws.write + + var encoding = this._options.encoding + var valueEncoding = this._options.valueEncoding + var keyEncoding = this._options.keyEncoding + + // slight optimization, if no encoding was specified at all, + // which will be the case most times, make write not check at all + var nocheck = !encoding && !valueEncoding && !keyEncoding + + ws.write = nocheck + ? function (data) { + data.key = p + data.key + return write.call(ws, data) + } + : function (data) { + data.key = p + data.key + + // not merging all options here since this happens on every write and things could get slowed down + // at this point we only consider encoding important to propagate + if (encoding && typeof data.encoding === 'undefined') + data.encoding = encoding + if (valueEncoding && typeof data.valueEncoding === 'undefined') + data.valueEncoding = valueEncoding + if (keyEncoding && typeof data.keyEncoding === 'undefined') + data.keyEncoding = keyEncoding + + return write.call(ws, data) + } + return ws +} + +SDB.approximateSize = function () { + var r = root(db) + return r.approximateSize.apply(r, arguments) +} + +function root(db) { + if(!db._parent) return db + return root(db._parent) +} + +SDB.pre = function (range, hook) { + if(!hook) hook = range, range = null + range = ranges.prefix(range, this.prefix(), this._options.sep) + var r = root(this._parent) + var p = this.prefix() + return r.hooks.pre(fixRange(range), function (ch, add, batch) { + hook({ + key: ch.key.substring(p.length), + value: ch.value, + type: ch.type + }, function (ch, _p) { + //maybe remove the second add arg now + //that op can have prefix? + add(ch, ch.prefix ? _p : (_p || p)) + }, batch) + }) +} + +SDB.post = function (range, hook) { + if(!hook) hook = range, range = null + var r = root(this._parent) + var p = this.prefix() + range = ranges.prefix(range, p, this._options.sep) + return r.hooks.post(fixRange(range), function (data) { + hook({key: data.key.substring(p.length), value: data.value, type: data.type}) + }) +} + +var exports = module.exports = SubDB + + +},{"./batch":60,"events":21,"level-fix-range":62,"string-range":65,"util":39,"xtend":67}],73:[function(_dereq_,module,exports){ +/* Copyright (c) 2012-2014 LevelUP contributors + * See list at <https://github.com/rvagg/node-levelup#contributing> + * MIT License + * <https://github.com/rvagg/node-levelup/blob/master/LICENSE.md> + */ + +var util = _dereq_('./util') + , WriteError = _dereq_('./errors').WriteError + + , getOptions = util.getOptions + , dispatchError = util.dispatchError + +function Batch (levelup) { + this._levelup = levelup + this.batch = levelup.db.batch() + this.ops = [] +} + +Batch.prototype.put = function (key_, value_, options) { + options = getOptions(this._levelup, options) + + var key = util.encodeKey(key_, options) + , value = util.encodeValue(value_, options) + + try { + this.batch.put(key, value) + } catch (e) { + throw new WriteError(e) + } + this.ops.push({ type : 'put', key : key, value : value }) + + return this +} + +Batch.prototype.del = function (key_, options) { + options = getOptions(this._levelup, options) + + var key = util.encodeKey(key_, options) + + try { + this.batch.del(key) + } catch (err) { + throw new WriteError(err) + } + this.ops.push({ type : 'del', key : key }) + + return this +} + +Batch.prototype.clear = function () { + try { + this.batch.clear() + } catch (err) { + throw new WriteError(err) + } + + this.ops = [] + return this +} + +Batch.prototype.write = function (callback) { + var levelup = this._levelup + , ops = this.ops + + try { + this.batch.write(function (err) { + if (err) + return dispatchError(levelup, new WriteError(err), callback) + levelup.emit('batch', ops) + if (callback) + callback() + }) + } catch (err) { + throw new WriteError(err) + } +} + +module.exports = Batch + +},{"./errors":74,"./util":77}],74:[function(_dereq_,module,exports){ +/* Copyright (c) 2012-2014 LevelUP contributors + * See list at <https://github.com/rvagg/node-levelup#contributing> + * MIT License + * <https://github.com/rvagg/node-levelup/blob/master/LICENSE.md> + */ + +var createError = _dereq_('errno').create + , LevelUPError = createError('LevelUPError') + , NotFoundError = createError('NotFoundError', LevelUPError) + +NotFoundError.prototype.notFound = true +NotFoundError.prototype.status = 404 + +module.exports = { + LevelUPError : LevelUPError + , InitializationError : createError('InitializationError', LevelUPError) + , OpenError : createError('OpenError', LevelUPError) + , ReadError : createError('ReadError', LevelUPError) + , WriteError : createError('WriteError', LevelUPError) + , NotFoundError : NotFoundError + , EncodingError : createError('EncodingError', LevelUPError) +} + +},{"errno":85}],75:[function(_dereq_,module,exports){ +(function (process){ +/* Copyright (c) 2012-2014 LevelUP contributors + * See list at <https://github.com/rvagg/node-levelup#contributing> + * MIT License + * <https://github.com/rvagg/node-levelup/blob/master/LICENSE.md> + */ + +var EventEmitter = _dereq_('events').EventEmitter + , inherits = _dereq_('util').inherits + , extend = _dereq_('xtend') + , prr = _dereq_('prr') + , DeferredLevelDOWN = _dereq_('deferred-leveldown') + + , WriteError = _dereq_('./errors').WriteError + , ReadError = _dereq_('./errors').ReadError + , NotFoundError = _dereq_('./errors').NotFoundError + , OpenError = _dereq_('./errors').OpenError + , EncodingError = _dereq_('./errors').EncodingError + , InitializationError = _dereq_('./errors').InitializationError + + , ReadStream = _dereq_('./read-stream') + , WriteStream = _dereq_('./write-stream') + , util = _dereq_('./util') + , Batch = _dereq_('./batch') + + , getOptions = util.getOptions + , defaultOptions = util.defaultOptions + , getLevelDOWN = util.getLevelDOWN + , dispatchError = util.dispatchError + +function getCallback (options, callback) { + return typeof options == 'function' ? options : callback +} + +// Possible LevelUP#_status values: +// - 'new' - newly created, not opened or closed +// - 'opening' - waiting for the database to be opened, post open() +// - 'open' - successfully opened the database, available for use +// - 'closing' - waiting for the database to be closed, post close() +// - 'closed' - database has been successfully closed, should not be +// used except for another open() operation + +function LevelUP (location, options, callback) { + if (!(this instanceof LevelUP)) + return new LevelUP(location, options, callback) + + var error + + EventEmitter.call(this) + this.setMaxListeners(Infinity) + + if (typeof location == 'function') { + options = typeof options == 'object' ? options : {} + options.db = location + location = null + } else if (typeof location == 'object' && typeof location.db == 'function') { + options = location + location = null + } + + if (typeof options == 'function') { + callback = options + options = {} + } + + if ((!options || typeof options.db != 'function') && typeof location != 'string') { + error = new InitializationError( + 'Must provide a location for the database') + if (callback) { + return process.nextTick(function () { + callback(error) + }) + } + throw error + } + + options = getOptions(this, options) + this.options = extend(defaultOptions, options) + this._status = 'new' + // set this.location as enumerable but not configurable or writable + prr(this, 'location', location, 'e') + + this.open(callback) +} + +inherits(LevelUP, EventEmitter) + +LevelUP.prototype.open = function (callback) { + var self = this + , dbFactory + , db + + if (this.isOpen()) { + if (callback) + process.nextTick(function () { callback(null, self) }) + return this + } + + if (this._isOpening()) { + return callback && this.once( + 'open' + , function () { callback(null, self) } + ) + } + + this.emit('opening') + + this._status = 'opening' + this.db = new DeferredLevelDOWN(this.location) + dbFactory = this.options.db || getLevelDOWN() + db = dbFactory(this.location) + + db.open(this.options, function (err) { + if (err) { + return dispatchError(self, new OpenError(err), callback) + } else { + self.db.setDb(db) + self.db = db + self._status = 'open' + if (callback) + callback(null, self) + self.emit('open') + self.emit('ready') + } + }) +} + +LevelUP.prototype.close = function (callback) { + var self = this + + if (this.isOpen()) { + this._status = 'closing' + this.db.close(function () { + self._status = 'closed' + self.emit('closed') + if (callback) + callback.apply(null, arguments) + }) + this.emit('closing') + this.db = null + } else if (this._status == 'closed' && callback) { + return process.nextTick(callback) + } else if (this._status == 'closing' && callback) { + this.once('closed', callback) + } else if (this._isOpening()) { + this.once('open', function () { + self.close(callback) + }) + } +} + +LevelUP.prototype.isOpen = function () { + return this._status == 'open' +} + +LevelUP.prototype._isOpening = function () { + return this._status == 'opening' +} + +LevelUP.prototype.isClosed = function () { + return (/^clos/).test(this._status) +} + +LevelUP.prototype.get = function (key_, options, callback) { + var self = this + , key + + callback = getCallback(options, callback) + + if (typeof callback != 'function') { + return dispatchError( + this + , new ReadError('get() requires key and callback arguments') + ) + } + + if (!this._isOpening() && !this.isOpen()) { + return dispatchError( + this + , new ReadError('Database is not open') + , callback + ) + } + + options = util.getOptions(this, options) + key = util.encodeKey(key_, options) + + options.asBuffer = util.isValueAsBuffer(options) + + this.db.get(key, options, function (err, value) { + if (err) { + if ((/notfound/i).test(err)) { + err = new NotFoundError( + 'Key not found in database [' + key_ + ']', err) + } else { + err = new ReadError(err) + } + return dispatchError(self, err, callback) + } + if (callback) { + try { + value = util.decodeValue(value, options) + } catch (e) { + return callback(new EncodingError(e)) + } + callback(null, value) + } + }) +} + +LevelUP.prototype.put = function (key_, value_, options, callback) { + var self = this + , key + , value + + callback = getCallback(options, callback) + + if (key_ === null || key_ === undefined + || value_ === null || value_ === undefined) { + return dispatchError( + this + , new WriteError('put() requires key and value arguments') + , callback + ) + } + + if (!this._isOpening() && !this.isOpen()) { + return dispatchError( + this + , new WriteError('Database is not open') + , callback + ) + } + + options = getOptions(this, options) + key = util.encodeKey(key_, options) + value = util.encodeValue(value_, options) + + this.db.put(key, value, options, function (err) { + if (err) { + return dispatchError(self, new WriteError(err), callback) + } else { + self.emit('put', key_, value_) + if (callback) + callback() + } + }) +} + +LevelUP.prototype.del = function (key_, options, callback) { + var self = this + , key + + callback = getCallback(options, callback) + + if (key_ === null || key_ === undefined) { + return dispatchError( + this + , new WriteError('del() requires a key argument') + , callback + ) + } + + if (!this._isOpening() && !this.isOpen()) { + return dispatchError( + this + , new WriteError('Database is not open') + , callback + ) + } + + options = getOptions(this, options) + key = util.encodeKey(key_, options) + + this.db.del(key, options, function (err) { + if (err) { + return dispatchError(self, new WriteError(err), callback) + } else { + self.emit('del', key_) + if (callback) + callback() + } + }) +} + +LevelUP.prototype.batch = function (arr_, options, callback) { + var self = this + , keyEnc + , valueEnc + , arr + + if (!arguments.length) + return new Batch(this) + + callback = getCallback(options, callback) + + if (!Array.isArray(arr_)) { + return dispatchError( + this + , new WriteError('batch() requires an array argument') + , callback + ) + } + + if (!this._isOpening() && !this.isOpen()) { + return dispatchError( + this + , new WriteError('Database is not open') + , callback + ) + } + + options = getOptions(this, options) + keyEnc = options.keyEncoding + valueEnc = options.valueEncoding + + arr = arr_.map(function (e) { + if (e.type === undefined || e.key === undefined) + return {} + + // inherit encoding + var kEnc = e.keyEncoding || keyEnc + , vEnc = e.valueEncoding || e.encoding || valueEnc + , o + + // If we're not dealing with plain utf8 strings or plain + // Buffers then we have to do some work on the array to + // encode the keys and/or values. This includes JSON types. + + if (kEnc != 'utf8' && kEnc != 'binary' + || vEnc != 'utf8' && vEnc != 'binary') { + o = { + type: e.type + , key: util.encodeKey(e.key, options, e) + } + + if (e.value !== undefined) + o.value = util.encodeValue(e.value, options, e) + + return o + } else { + return e + } + }) + + this.db.batch(arr, options, function (err) { + if (err) { + return dispatchError(self, new WriteError(err), callback) + } else { + self.emit('batch', arr_) + if (callback) + callback() + } + }) +} + +// DEPRECATED: prefer accessing LevelDOWN for this: db.db.approximateSize() +LevelUP.prototype.approximateSize = function (start_, end_, callback) { + var self = this + , start + , end + + if (start_ === null || start_ === undefined + || end_ === null || end_ === undefined + || typeof callback != 'function') { + return dispatchError( + this + , new ReadError('approximateSize() requires start, end and callback arguments') + , callback + ) + } + + start = util.encodeKey(start_, this.options) + end = util.encodeKey(end_, this.options) + + if (!this._isOpening() && !this.isOpen()) { + return dispatchError( + this + , new WriteError('Database is not open') + , callback + ) + } + + this.db.approximateSize(start, end, function (err, size) { + if (err) { + return dispatchError(self, new OpenError(err), callback) + } else if (callback) { + callback(null, size) + } + }) +} + +LevelUP.prototype.readStream = +LevelUP.prototype.createReadStream = function (options) { + var self = this + options = extend(this.options, options) + return new ReadStream( + options + , this + , function (options) { + return self.db.iterator(options) + } + ) +} + +LevelUP.prototype.keyStream = +LevelUP.prototype.createKeyStream = function (options) { + return this.createReadStream(extend(options, { keys: true, values: false })) +} + +LevelUP.prototype.valueStream = +LevelUP.prototype.createValueStream = function (options) { + return this.createReadStream(extend(options, { keys: false, values: true })) +} + +LevelUP.prototype.writeStream = +LevelUP.prototype.createWriteStream = function (options) { + return new WriteStream(extend(options), this) +} + +LevelUP.prototype.toString = function () { + return 'LevelUP' +} + +function utilStatic (name) { + return function (location, callback) { + getLevelDOWN()[name](location, callback || function () {}) + } +} + +module.exports = LevelUP +module.exports.copy = util.copy +// DEPRECATED: prefer accessing LevelDOWN for this: require('leveldown').destroy() +module.exports.destroy = utilStatic('destroy') +// DEPRECATED: prefer accessing LevelDOWN for this: require('leveldown').repair() +module.exports.repair = utilStatic('repair') + +}).call(this,_dereq_('_process')) +},{"./batch":73,"./errors":74,"./read-stream":76,"./util":77,"./write-stream":78,"_process":24,"deferred-leveldown":80,"events":21,"prr":86,"util":39,"xtend":96}],76:[function(_dereq_,module,exports){ +/* Copyright (c) 2012-2014 LevelUP contributors + * See list at <https://github.com/rvagg/node-levelup#contributing> + * MIT License <https://github.com/rvagg/node-levelup/blob/master/LICENSE.md> + */ + +// NOTE: we are fixed to readable-stream@1.0.x for now +// for pure Streams2 across Node versions +var Readable = _dereq_('readable-stream').Readable + , inherits = _dereq_('util').inherits + , extend = _dereq_('xtend') + , EncodingError = _dereq_('./errors').EncodingError + , util = _dereq_('./util') + + , defaultOptions = { keys: true, values: true } + + , makeKeyValueData = function (key, value) { + return { + key: util.decodeKey(key, this._options) + , value: util.decodeValue(value, this._options) + } + } + , makeKeyData = function (key) { + return util.decodeKey(key, this._options) + } + , makeValueData = function (_, value) { + return util.decodeValue(value, this._options) + } + , makeNoData = function () { return null } + +function ReadStream (options, db, iteratorFactory) { + if (!(this instanceof ReadStream)) + return new ReadStream(options, db, iteratorFactory) + + Readable.call(this, { objectMode: true, highWaterMark: options.highWaterMark }) + + // purely to keep `db` around until we're done so it's not GCed if the user doesn't keep a ref + this._db = db + + options = this._options = extend(defaultOptions, options) + + this._keyEncoding = options.keyEncoding || options.encoding + this._valueEncoding = options.valueEncoding || options.encoding + + if (typeof this._options.start != 'undefined') + this._options.start = util.encodeKey(this._options.start, this._options) + if (typeof this._options.end != 'undefined') + this._options.end = util.encodeKey(this._options.end, this._options) + if (typeof this._options.limit != 'number') + this._options.limit = -1 + + this._options.keyAsBuffer = util.isKeyAsBuffer(this._options) + + this._options.valueAsBuffer = util.isValueAsBuffer(this._options) + + this._makeData = this._options.keys && this._options.values + ? makeKeyValueData : this._options.keys + ? makeKeyData : this._options.values + ? makeValueData : makeNoData + + var self = this + if (!this._db.isOpen()) { + this._db.once('ready', function () { + if (!self._destroyed) { + self._iterator = iteratorFactory(self._options) + } + }) + } else + this._iterator = iteratorFactory(this._options) +} + +inherits(ReadStream, Readable) + +ReadStream.prototype._read = function read () { + var self = this + if (!self._db.isOpen()) { + return self._db.once('ready', function () { read.call(self) }) + } + if (self._destroyed) + return + + self._iterator.next(function(err, key, value) { + if (err || (key === undefined && value === undefined)) { + if (!err && !self._destroyed) + self.push(null) + return self._cleanup(err) + } + + try { + value = self._makeData(key, value) + } catch (e) { + return self._cleanup(new EncodingError(e)) + } + if (!self._destroyed) + self.push(value) + }) +} + +ReadStream.prototype._cleanup = function (err) { + if (this._destroyed) + return + + this._destroyed = true + + var self = this + if (err) + self.emit('error', err) + + if (self._iterator) { + self._iterator.end(function () { + self._iterator = null + self.emit('close') + }) + } else { + self.emit('close') + } +} + +ReadStream.prototype.destroy = function () { + this._cleanup() +} + +ReadStream.prototype.toString = function () { + return 'LevelUP.ReadStream' +} + +module.exports = ReadStream + +},{"./errors":74,"./util":77,"readable-stream":95,"util":39,"xtend":96}],77:[function(_dereq_,module,exports){ +(function (process,Buffer){ +/* Copyright (c) 2012-2014 LevelUP contributors + * See list at <https://github.com/rvagg/node-levelup#contributing> + * MIT License + * <https://github.com/rvagg/node-levelup/blob/master/LICENSE.md> + */ + +var extend = _dereq_('xtend') + , LevelUPError = _dereq_('./errors').LevelUPError + + , encodingNames = [ + 'hex' + , 'utf8' + , 'utf-8' + , 'ascii' + , 'binary' + , 'base64' + , 'ucs2' + , 'ucs-2' + , 'utf16le' + , 'utf-16le' + ] + + , defaultOptions = { + createIfMissing : true + , errorIfExists : false + , keyEncoding : 'utf8' + , valueEncoding : 'utf8' + , compression : true + } + + , leveldown + + , encodings = (function () { + function isBinary (data) { + return data === undefined || data === null || Buffer.isBuffer(data) + } + + var encodings = {} + encodings.utf8 = encodings['utf-8'] = { + encode : function (data) { + return isBinary(data) ? data : String(data) + } + , decode : function (data) { + return data + } + , buffer : false + , type : 'utf8' + } + encodings.json = { + encode : JSON.stringify + , decode : JSON.parse + , buffer : false + , type : 'json' + } + encodingNames.forEach(function (type) { + if (encodings[type]) + return + encodings[type] = { + encode : function (data) { + return isBinary(data) ? data : new Buffer(data, type) + } + , decode : function (buffer) { + return process.browser ? buffer.toString(type) : buffer; + } + , buffer : true + , type : type // useful for debugging purposes + } + }) + return encodings + })() + + , encodingOpts = (function () { + var eo = {} + encodingNames.forEach(function (e) { + eo[e] = { valueEncoding : e } + }) + return eo + }()) + +function copy (srcdb, dstdb, callback) { + srcdb.readStream() + .pipe(dstdb.writeStream()) + .on('close', callback ? callback : function () {}) + .on('error', callback ? callback : function (err) { throw err }) +} + +function getOptions (levelup, options) { + var s = typeof options == 'string' // just an encoding + if (!s && options && options.encoding && !options.valueEncoding) + options.valueEncoding = options.encoding + return extend( + (levelup && levelup.options) || {} + , s ? encodingOpts[options] || encodingOpts[defaultOptions.valueEncoding] + : options + ) +} + +function getLevelDOWN () { + if (leveldown) + return leveldown + + var requiredVersion = _dereq_('../package.json').devDependencies.leveldown + , missingLevelDOWNError = 'Could not locate LevelDOWN, try `npm install leveldown`' + , leveldownVersion + + try { + leveldownVersion = _dereq_('leveldown/package').version + } catch (e) { + throw new LevelUPError(missingLevelDOWNError) + } + + if (!_dereq_('semver').satisfies(leveldownVersion, requiredVersion)) { + throw new LevelUPError( + 'Installed version of LevelDOWN (' + + leveldownVersion + + ') does not match required version (' + + requiredVersion + + ')' + ) + } + + try { + return leveldown = _dereq_('leveldown') + } catch (e) { + throw new LevelUPError(missingLevelDOWNError) + } +} + +function dispatchError (levelup, error, callback) { + return typeof callback == 'function' + ? callback(error) + : levelup.emit('error', error) +} + +function getKeyEncoder (options, op) { + var type = ((op && op.keyEncoding) || options.keyEncoding) || 'utf8' + return encodings[type] || type +} + +function getValueEncoder (options, op) { + var type = (((op && (op.valueEncoding || op.encoding)) + || options.valueEncoding || options.encoding)) || 'utf8' + return encodings[type] || type +} + +function encodeKey (key, options, op) { + return getKeyEncoder(options, op).encode(key) +} + +function encodeValue (value, options, op) { + return getValueEncoder(options, op).encode(value) +} + +function decodeKey (key, options) { + return getKeyEncoder(options).decode(key) +} + +function decodeValue (value, options) { + return getValueEncoder(options).decode(value) +} + +function isValueAsBuffer (options, op) { + return getValueEncoder(options, op).buffer +} + +function isKeyAsBuffer (options, op) { + return getKeyEncoder(options, op).buffer +} + +module.exports = { + defaultOptions : defaultOptions + , copy : copy + , getOptions : getOptions + , getLevelDOWN : getLevelDOWN + , dispatchError : dispatchError + , encodeKey : encodeKey + , encodeValue : encodeValue + , isValueAsBuffer : isValueAsBuffer + , isKeyAsBuffer : isKeyAsBuffer + , decodeValue : decodeValue + , decodeKey : decodeKey +} + +}).call(this,_dereq_('_process'),_dereq_("buffer").Buffer) +},{"../package.json":97,"./errors":74,"_process":24,"buffer":17,"leveldown":"leveldown","leveldown/package":16,"semver":16,"xtend":96}],78:[function(_dereq_,module,exports){ +(function (process,global){ +/* Copyright (c) 2012-2014 LevelUP contributors + * See list at <https://github.com/rvagg/node-levelup#contributing> + * MIT License + * <https://github.com/rvagg/node-levelup/blob/master/LICENSE.md> + */ + +var Stream = _dereq_('stream').Stream + , inherits = _dereq_('util').inherits + , extend = _dereq_('xtend') + , bl = _dereq_('bl') + + , setImmediate = global.setImmediate || process.nextTick + + , getOptions = _dereq_('./util').getOptions + + , defaultOptions = { type: 'put' } + +function WriteStream (options, db) { + if (!(this instanceof WriteStream)) + return new WriteStream(options, db) + + Stream.call(this) + this._options = extend(defaultOptions, getOptions(db, options)) + this._db = db + this._buffer = [] + this._status = 'init' + this._end = false + this.writable = true + this.readable = false + + var self = this + , ready = function () { + if (!self.writable) + return + self._status = 'ready' + self.emit('ready') + self._process() + } + + if (db.isOpen()) + setImmediate(ready) + else + db.once('ready', ready) +} + +inherits(WriteStream, Stream) + +WriteStream.prototype.write = function (data) { + if (!this.writable) + return false + this._buffer.push(data) + if (this._status != 'init') + this._processDelayed() + if (this._options.maxBufferLength && + this._buffer.length > this._options.maxBufferLength) { + this._writeBlock = true + return false + } + return true +} + +WriteStream.prototype.end = function (data) { + var self = this + if (data) + this.write(data) + setImmediate(function () { + self._end = true + self._process() + }) +} + +WriteStream.prototype.destroy = function () { + this.writable = false + this.end() +} + +WriteStream.prototype.destroySoon = function () { + this.end() +} + +WriteStream.prototype.add = function (entry) { + if (!entry.props) + return + if (entry.props.Directory) + entry.pipe(this._db.writeStream(this._options)) + else if (entry.props.File || entry.File || entry.type == 'File') + this._write(entry) + return true +} + +WriteStream.prototype._processDelayed = function () { + var self = this + setImmediate(function () { + self._process() + }) +} + +WriteStream.prototype._process = function () { + var buffer + , self = this + + , cb = function (err) { + if (!self.writable) + return + if (self._status != 'closed') + self._status = 'ready' + if (err) { + self.writable = false + return self.emit('error', err) + } + self._process() + } + + if (self._status != 'ready' && self.writable) { + if (self._buffer.length && self._status != 'closed') + self._processDelayed() + return + } + + if (self._buffer.length && self.writable) { + self._status = 'writing' + buffer = self._buffer + self._buffer = [] + + self._db.batch(buffer.map(function (d) { + return { + type : d.type || self._options.type + , key : d.key + , value : d.value + , keyEncoding : d.keyEncoding || self._options.keyEncoding + , valueEncoding : d.valueEncoding + || d.encoding + || self._options.valueEncoding + } + }), cb) + + if (self._writeBlock) { + self._writeBlock = false + self.emit('drain') + } + + // don't allow close until callback has returned + return + } + + if (self._end && self._status != 'closed') { + self._status = 'closed' + self.writable = false + self.emit('close') + } +} + +WriteStream.prototype._write = function (entry) { + var key = entry.path || entry.props.path + , self = this + + if (!key) + return + + entry.pipe(bl(function (err, data) { + if (err) { + self.writable = false + return self.emit('error', err) + } + + if (self._options.fstreamRoot && + key.indexOf(self._options.fstreamRoot) > -1) + key = key.substr(self._options.fstreamRoot.length + 1) + + self.write({ key: key, value: data.slice(0) }) + })) +} + +WriteStream.prototype.toString = function () { + return 'LevelUP.WriteStream' +} + +module.exports = WriteStream + +}).call(this,_dereq_('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./util":77,"_process":24,"bl":79,"stream":36,"util":39,"xtend":96}],79:[function(_dereq_,module,exports){ +(function (Buffer){ +var DuplexStream = _dereq_('readable-stream').Duplex + , util = _dereq_('util') + +function BufferList (callback) { + if (!(this instanceof BufferList)) + return new BufferList(callback) + + this._bufs = [] + this.length = 0 + + if (typeof callback == 'function') { + this._callback = callback + + var piper = function (err) { + if (this._callback) { + this._callback(err) + this._callback = null + } + }.bind(this) + + this.on('pipe', function (src) { + src.on('error', piper) + }) + this.on('unpipe', function (src) { + src.removeListener('error', piper) + }) + } + else if (Buffer.isBuffer(callback)) + this.append(callback) + else if (Array.isArray(callback)) { + callback.forEach(function (b) { + Buffer.isBuffer(b) && this.append(b) + }.bind(this)) + } + + DuplexStream.call(this) +} + +util.inherits(BufferList, DuplexStream) + +BufferList.prototype._offset = function (offset) { + var tot = 0, i = 0, _t + for (; i < this._bufs.length; i++) { + _t = tot + this._bufs[i].length + if (offset < _t) + return [ i, offset - tot ] + tot = _t + } +} + +BufferList.prototype.append = function (buf) { + this._bufs.push(Buffer.isBuffer(buf) ? buf : new Buffer(buf)) + this.length += buf.length + return this +} + +BufferList.prototype._write = function (buf, encoding, callback) { + this.append(buf) + if (callback) + callback() +} + +BufferList.prototype._read = function (size) { + if (!this.length) + return this.push(null) + size = Math.min(size, this.length) + this.push(this.slice(0, size)) + this.consume(size) +} + +BufferList.prototype.end = function (chunk) { + DuplexStream.prototype.end.call(this, chunk) + + if (this._callback) { + this._callback(null, this.slice()) + this._callback = null + } +} + +BufferList.prototype.get = function (index) { + return this.slice(index, index + 1)[0] +} + +BufferList.prototype.slice = function (start, end) { + return this.copy(null, 0, start, end) +} + +BufferList.prototype.copy = function (dst, dstStart, srcStart, srcEnd) { + if (typeof srcStart != 'number' || srcStart < 0) + srcStart = 0 + if (typeof srcEnd != 'number' || srcEnd > this.length) + srcEnd = this.length + if (srcStart >= this.length) + return dst || new Buffer(0) + if (srcEnd <= 0) + return dst || new Buffer(0) + + var copy = !!dst + , off = this._offset(srcStart) + , len = srcEnd - srcStart + , bytes = len + , bufoff = (copy && dstStart) || 0 + , start = off[1] + , l + , i + + // copy/slice everything + if (srcStart === 0 && srcEnd == this.length) { + if (!copy) // slice, just return a full concat + return Buffer.concat(this._bufs) + + // copy, need to copy individual buffers + for (i = 0; i < this._bufs.length; i++) { + this._bufs[i].copy(dst, bufoff) + bufoff += this._bufs[i].length + } + + return dst + } + + // easy, cheap case where it's a subset of one of the buffers + if (bytes <= this._bufs[off[0]].length - start) { + return copy + ? this._bufs[off[0]].copy(dst, dstStart, start, start + bytes) + : this._bufs[off[0]].slice(start, start + bytes) + } + + if (!copy) // a slice, we need something to copy in to + dst = new Buffer(len) + + for (i = off[0]; i < this._bufs.length; i++) { + l = this._bufs[i].length - start + + if (bytes > l) { + this._bufs[i].copy(dst, bufoff, start) + } else { + this._bufs[i].copy(dst, bufoff, start, start + bytes) + break + } + + bufoff += l + bytes -= l + + if (start) + start = 0 + } + + return dst +} + +BufferList.prototype.toString = function (encoding, start, end) { + return this.slice(start, end).toString(encoding) +} + +BufferList.prototype.consume = function (bytes) { + while (this._bufs.length) { + if (bytes > this._bufs[0].length) { + bytes -= this._bufs[0].length + this.length -= this._bufs[0].length + this._bufs.shift() + } else { + this._bufs[0] = this._bufs[0].slice(bytes) + this.length -= bytes + break + } + } + return this +} + +BufferList.prototype.duplicate = function () { + var i = 0 + , copy = new BufferList() + + for (; i < this._bufs.length; i++) + copy.append(this._bufs[i]) + + return copy +} + +BufferList.prototype.destroy = function () { + this._bufs.length = 0; + this.length = 0; + this.push(null); +} + +;(function () { + var methods = { + 'readDoubleBE' : 8 + , 'readDoubleLE' : 8 + , 'readFloatBE' : 4 + , 'readFloatLE' : 4 + , 'readInt32BE' : 4 + , 'readInt32LE' : 4 + , 'readUInt32BE' : 4 + , 'readUInt32LE' : 4 + , 'readInt16BE' : 2 + , 'readInt16LE' : 2 + , 'readUInt16BE' : 2 + , 'readUInt16LE' : 2 + , 'readInt8' : 1 + , 'readUInt8' : 1 + } + + for (var m in methods) { + (function (m) { + BufferList.prototype[m] = function (offset) { + return this.slice(offset, offset + methods[m])[m](0) + } + }(m)) + } +}()) + +module.exports = BufferList + +}).call(this,_dereq_("buffer").Buffer) +},{"buffer":17,"readable-stream":95,"util":39}],80:[function(_dereq_,module,exports){ +(function (process,Buffer){ +var util = _dereq_('util') + , AbstractLevelDOWN = _dereq_('abstract-leveldown').AbstractLevelDOWN + +function DeferredLevelDOWN (location) { + AbstractLevelDOWN.call(this, typeof location == 'string' ? location : '') // optional location, who cares? + this._db = undefined + this._operations = [] +} + +util.inherits(DeferredLevelDOWN, AbstractLevelDOWN) + +// called by LevelUP when we have a real DB to take its place +DeferredLevelDOWN.prototype.setDb = function (db) { + this._db = db + this._operations.forEach(function (op) { + db[op.method].apply(db, op.args) + }) +} + +DeferredLevelDOWN.prototype._open = function (options, callback) { + return process.nextTick(callback) +} + +// queue a new deferred operation +DeferredLevelDOWN.prototype._operation = function (method, args) { + if (this._db) + return this._db[method].apply(this._db, args) + this._operations.push({ method: method, args: args }) +} + +// deferrables +'put get del batch approximateSize'.split(' ').forEach(function (m) { + DeferredLevelDOWN.prototype['_' + m] = function () { + this._operation(m, arguments) + } +}) + +DeferredLevelDOWN.prototype._isBuffer = function (obj) { + return Buffer.isBuffer(obj) +} + +// don't need to implement this as LevelUP's ReadStream checks for 'ready' state +DeferredLevelDOWN.prototype._iterator = function () { + throw new TypeError('not implemented') +} + +module.exports = DeferredLevelDOWN + +}).call(this,_dereq_('_process'),_dereq_("buffer").Buffer) +},{"_process":24,"abstract-leveldown":83,"buffer":17,"util":39}],81:[function(_dereq_,module,exports){ +module.exports=_dereq_(46) +},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/abstract-leveldown/abstract-chained-batch.js":46,"_process":24}],82:[function(_dereq_,module,exports){ +module.exports=_dereq_(47) +},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/abstract-leveldown/abstract-iterator.js":47,"_process":24}],83:[function(_dereq_,module,exports){ +module.exports=_dereq_(48) +},{"./abstract-chained-batch":81,"./abstract-iterator":82,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/abstract-leveldown/abstract-leveldown.js":48,"_process":24,"buffer":17,"xtend":96}],84:[function(_dereq_,module,exports){ +var prr = _dereq_('prr') + +function init (type, message, cause) { + prr(this, { + type : type + , name : type + // can be passed just a 'cause' + , cause : typeof message != 'string' ? message : cause + , message : !!message && typeof message != 'string' ? message.message : message + + }, 'ewr') +} + +// generic prototype, not intended to be actually used - helpful for `instanceof` +function CustomError (message, cause) { + Error.call(this) + if (Error.captureStackTrace) + Error.captureStackTrace(this, arguments.callee) + init.call(this, 'CustomError', message, cause) +} + +CustomError.prototype = new Error() + +function createError (errno, type, proto) { + var err = function (message, cause) { + init.call(this, type, message, cause) + //TODO: the specificity here is stupid, errno should be available everywhere + if (type == 'FilesystemError') { + this.code = this.cause.code + this.path = this.cause.path + this.errno = this.cause.errno + this.message = + (errno.errno[this.cause.errno] + ? errno.errno[this.cause.errno].description + : this.cause.message) + + (this.cause.path ? ' [' + this.cause.path + ']' : '') + } + Error.call(this) + if (Error.captureStackTrace) + Error.captureStackTrace(this, arguments.callee) + } + err.prototype = !!proto ? new proto() : new CustomError() + return err +} + +module.exports = function (errno) { + var ce = function (type, proto) { + return createError(errno, type, proto) + } + return { + CustomError : CustomError + , FilesystemError : ce('FilesystemError') + , createError : ce + } +} + +},{"prr":86}],85:[function(_dereq_,module,exports){ +var all = module.exports.all = [ + { + "errno": -1, + "code": "UNKNOWN", + "description": "unknown error" + }, + { + "errno": 0, + "code": "OK", + "description": "success" + }, + { + "errno": 1, + "code": "EOF", + "description": "end of file" + }, + { + "errno": 2, + "code": "EADDRINFO", + "description": "getaddrinfo error" + }, + { + "errno": 3, + "code": "EACCES", + "description": "permission denied" + }, + { + "errno": 4, + "code": "EAGAIN", + "description": "resource temporarily unavailable" + }, + { + "errno": 5, + "code": "EADDRINUSE", + "description": "address already in use" + }, + { + "errno": 6, + "code": "EADDRNOTAVAIL", + "description": "address not available" + }, + { + "errno": 7, + "code": "EAFNOSUPPORT", + "description": "address family not supported" + }, + { + "errno": 8, + "code": "EALREADY", + "description": "connection already in progress" + }, + { + "errno": 9, + "code": "EBADF", + "description": "bad file descriptor" + }, + { + "errno": 10, + "code": "EBUSY", + "description": "resource busy or locked" + }, + { + "errno": 11, + "code": "ECONNABORTED", + "description": "software caused connection abort" + }, + { + "errno": 12, + "code": "ECONNREFUSED", + "description": "connection refused" + }, + { + "errno": 13, + "code": "ECONNRESET", + "description": "connection reset by peer" + }, + { + "errno": 14, + "code": "EDESTADDRREQ", + "description": "destination address required" + }, + { + "errno": 15, + "code": "EFAULT", + "description": "bad address in system call argument" + }, + { + "errno": 16, + "code": "EHOSTUNREACH", + "description": "host is unreachable" + }, + { + "errno": 17, + "code": "EINTR", + "description": "interrupted system call" + }, + { + "errno": 18, + "code": "EINVAL", + "description": "invalid argument" + }, + { + "errno": 19, + "code": "EISCONN", + "description": "socket is already connected" + }, + { + "errno": 20, + "code": "EMFILE", + "description": "too many open files" + }, + { + "errno": 21, + "code": "EMSGSIZE", + "description": "message too long" + }, + { + "errno": 22, + "code": "ENETDOWN", + "description": "network is down" + }, + { + "errno": 23, + "code": "ENETUNREACH", + "description": "network is unreachable" + }, + { + "errno": 24, + "code": "ENFILE", + "description": "file table overflow" + }, + { + "errno": 25, + "code": "ENOBUFS", + "description": "no buffer space available" + }, + { + "errno": 26, + "code": "ENOMEM", + "description": "not enough memory" + }, + { + "errno": 27, + "code": "ENOTDIR", + "description": "not a directory" + }, + { + "errno": 28, + "code": "EISDIR", + "description": "illegal operation on a directory" + }, + { + "errno": 29, + "code": "ENONET", + "description": "machine is not on the network" + }, + { + "errno": 31, + "code": "ENOTCONN", + "description": "socket is not connected" + }, + { + "errno": 32, + "code": "ENOTSOCK", + "description": "socket operation on non-socket" + }, + { + "errno": 33, + "code": "ENOTSUP", + "description": "operation not supported on socket" + }, + { + "errno": 34, + "code": "ENOENT", + "description": "no such file or directory" + }, + { + "errno": 35, + "code": "ENOSYS", + "description": "function not implemented" + }, + { + "errno": 36, + "code": "EPIPE", + "description": "broken pipe" + }, + { + "errno": 37, + "code": "EPROTO", + "description": "protocol error" + }, + { + "errno": 38, + "code": "EPROTONOSUPPORT", + "description": "protocol not supported" + }, + { + "errno": 39, + "code": "EPROTOTYPE", + "description": "protocol wrong type for socket" + }, + { + "errno": 40, + "code": "ETIMEDOUT", + "description": "connection timed out" + }, + { + "errno": 41, + "code": "ECHARSET", + "description": "invalid Unicode character" + }, + { + "errno": 42, + "code": "EAIFAMNOSUPPORT", + "description": "address family for hostname not supported" + }, + { + "errno": 44, + "code": "EAISERVICE", + "description": "servname not supported for ai_socktype" + }, + { + "errno": 45, + "code": "EAISOCKTYPE", + "description": "ai_socktype not supported" + }, + { + "errno": 46, + "code": "ESHUTDOWN", + "description": "cannot send after transport endpoint shutdown" + }, + { + "errno": 47, + "code": "EEXIST", + "description": "file already exists" + }, + { + "errno": 48, + "code": "ESRCH", + "description": "no such process" + }, + { + "errno": 49, + "code": "ENAMETOOLONG", + "description": "name too long" + }, + { + "errno": 50, + "code": "EPERM", + "description": "operation not permitted" + }, + { + "errno": 51, + "code": "ELOOP", + "description": "too many symbolic links encountered" + }, + { + "errno": 52, + "code": "EXDEV", + "description": "cross-device link not permitted" + }, + { + "errno": 53, + "code": "ENOTEMPTY", + "description": "directory not empty" + }, + { + "errno": 54, + "code": "ENOSPC", + "description": "no space left on device" + }, + { + "errno": 55, + "code": "EIO", + "description": "i/o error" + }, + { + "errno": 56, + "code": "EROFS", + "description": "read-only file system" + }, + { + "errno": 57, + "code": "ENODEV", + "description": "no such device" + }, + { + "errno": 58, + "code": "ESPIPE", + "description": "invalid seek" + }, + { + "errno": 59, + "code": "ECANCELED", + "description": "operation canceled" + } +] + + +module.exports.errno = { + '-1': all[0] + , '0': all[1] + , '1': all[2] + , '2': all[3] + , '3': all[4] + , '4': all[5] + , '5': all[6] + , '6': all[7] + , '7': all[8] + , '8': all[9] + , '9': all[10] + , '10': all[11] + , '11': all[12] + , '12': all[13] + , '13': all[14] + , '14': all[15] + , '15': all[16] + , '16': all[17] + , '17': all[18] + , '18': all[19] + , '19': all[20] + , '20': all[21] + , '21': all[22] + , '22': all[23] + , '23': all[24] + , '24': all[25] + , '25': all[26] + , '26': all[27] + , '27': all[28] + , '28': all[29] + , '29': all[30] + , '31': all[31] + , '32': all[32] + , '33': all[33] + , '34': all[34] + , '35': all[35] + , '36': all[36] + , '37': all[37] + , '38': all[38] + , '39': all[39] + , '40': all[40] + , '41': all[41] + , '42': all[42] + , '44': all[43] + , '45': all[44] + , '46': all[45] + , '47': all[46] + , '48': all[47] + , '49': all[48] + , '50': all[49] + , '51': all[50] + , '52': all[51] + , '53': all[52] + , '54': all[53] + , '55': all[54] + , '56': all[55] + , '57': all[56] + , '58': all[57] + , '59': all[58] +} + + +module.exports.code = { + 'UNKNOWN': all[0] + , 'OK': all[1] + , 'EOF': all[2] + , 'EADDRINFO': all[3] + , 'EACCES': all[4] + , 'EAGAIN': all[5] + , 'EADDRINUSE': all[6] + , 'EADDRNOTAVAIL': all[7] + , 'EAFNOSUPPORT': all[8] + , 'EALREADY': all[9] + , 'EBADF': all[10] + , 'EBUSY': all[11] + , 'ECONNABORTED': all[12] + , 'ECONNREFUSED': all[13] + , 'ECONNRESET': all[14] + , 'EDESTADDRREQ': all[15] + , 'EFAULT': all[16] + , 'EHOSTUNREACH': all[17] + , 'EINTR': all[18] + , 'EINVAL': all[19] + , 'EISCONN': all[20] + , 'EMFILE': all[21] + , 'EMSGSIZE': all[22] + , 'ENETDOWN': all[23] + , 'ENETUNREACH': all[24] + , 'ENFILE': all[25] + , 'ENOBUFS': all[26] + , 'ENOMEM': all[27] + , 'ENOTDIR': all[28] + , 'EISDIR': all[29] + , 'ENONET': all[30] + , 'ENOTCONN': all[31] + , 'ENOTSOCK': all[32] + , 'ENOTSUP': all[33] + , 'ENOENT': all[34] + , 'ENOSYS': all[35] + , 'EPIPE': all[36] + , 'EPROTO': all[37] + , 'EPROTONOSUPPORT': all[38] + , 'EPROTOTYPE': all[39] + , 'ETIMEDOUT': all[40] + , 'ECHARSET': all[41] + , 'EAIFAMNOSUPPORT': all[42] + , 'EAISERVICE': all[43] + , 'EAISOCKTYPE': all[44] + , 'ESHUTDOWN': all[45] + , 'EEXIST': all[46] + , 'ESRCH': all[47] + , 'ENAMETOOLONG': all[48] + , 'EPERM': all[49] + , 'ELOOP': all[50] + , 'EXDEV': all[51] + , 'ENOTEMPTY': all[52] + , 'ENOSPC': all[53] + , 'EIO': all[54] + , 'EROFS': all[55] + , 'ENODEV': all[56] + , 'ESPIPE': all[57] + , 'ECANCELED': all[58] +} + + +module.exports.custom = _dereq_("./custom")(module.exports) +module.exports.create = module.exports.custom.createError +},{"./custom":84}],86:[function(_dereq_,module,exports){ +/*! + * prr + * (c) 2013 Rod Vagg <rod@vagg.org> + * https://github.com/rvagg/prr + * License: MIT + */ + +(function (name, context, definition) { + if (typeof module != 'undefined' && module.exports) + module.exports = definition() + else + context[name] = definition() +})('prr', this, function() { + + var setProperty = typeof Object.defineProperty == 'function' + ? function (obj, key, options) { + Object.defineProperty(obj, key, options) + return obj + } + : function (obj, key, options) { // < es5 + obj[key] = options.value + return obj + } + + , makeOptions = function (value, options) { + var oo = typeof options == 'object' + , os = !oo && typeof options == 'string' + , op = function (p) { + return oo + ? !!options[p] + : os + ? options.indexOf(p[0]) > -1 + : false + } + + return { + enumerable : op('enumerable') + , configurable : op('configurable') + , writable : op('writable') + , value : value + } + } + + , prr = function (obj, key, value, options) { + var k + + options = makeOptions(value, options) + + if (typeof key == 'object') { + for (k in key) { + if (Object.hasOwnProperty.call(key, k)) { + options.value = key[k] + setProperty(obj, k, options) + } + } + return obj + } + + return setProperty(obj, key, options) + } + + return prr +}) +},{}],87:[function(_dereq_,module,exports){ +module.exports=_dereq_(26) +},{"./_stream_readable":89,"./_stream_writable":91,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_duplex.js":26,"_process":24,"core-util-is":92,"inherits":44}],88:[function(_dereq_,module,exports){ +module.exports=_dereq_(27) +},{"./_stream_transform":90,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_passthrough.js":27,"core-util-is":92,"inherits":44}],89:[function(_dereq_,module,exports){ +module.exports=_dereq_(28) +},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_readable.js":28,"_process":24,"buffer":17,"core-util-is":92,"events":21,"inherits":44,"isarray":93,"stream":36,"string_decoder/":94}],90:[function(_dereq_,module,exports){ +module.exports=_dereq_(29) +},{"./_stream_duplex":87,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_transform.js":29,"core-util-is":92,"inherits":44}],91:[function(_dereq_,module,exports){ +module.exports=_dereq_(30) +},{"./_stream_duplex":87,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_writable.js":30,"_process":24,"buffer":17,"core-util-is":92,"inherits":44,"stream":36}],92:[function(_dereq_,module,exports){ +module.exports=_dereq_(31) +},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/node_modules/core-util-is/lib/util.js":31,"buffer":17}],93:[function(_dereq_,module,exports){ +module.exports=_dereq_(22) +},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/isarray/index.js":22}],94:[function(_dereq_,module,exports){ +module.exports=_dereq_(37) +},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/string_decoder/index.js":37,"buffer":17}],95:[function(_dereq_,module,exports){ +module.exports=_dereq_(33) +},{"./lib/_stream_duplex.js":87,"./lib/_stream_passthrough.js":88,"./lib/_stream_readable.js":89,"./lib/_stream_transform.js":90,"./lib/_stream_writable.js":91,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/readable.js":33,"stream":36}],96:[function(_dereq_,module,exports){ +module.exports=_dereq_(49) +},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/abstract-leveldown/node_modules/xtend/index.js":49}],97:[function(_dereq_,module,exports){ +module.exports={ + "name": "levelup", + "description": "Fast & simple storage - a Node.js-style LevelDB wrapper", + "version": "0.18.6", + "contributors": [ + { + "name": "Rod Vagg", + "email": "r@va.gg", + "url": "https://github.com/rvagg" + }, + { + "name": "John Chesley", + "email": "john@chesl.es", + "url": "https://github.com/chesles/" + }, + { + "name": "Jake Verbaten", + "email": "raynos2@gmail.com", + "url": "https://github.com/raynos" + }, + { + "name": "Dominic Tarr", + "email": "dominic.tarr@gmail.com", + "url": "https://github.com/dominictarr" + }, + { + "name": "Max Ogden", + "email": "max@maxogden.com", + "url": "https://github.com/maxogden" + }, + { + "name": "Lars-Magnus Skog", + "email": "lars.magnus.skog@gmail.com", + "url": "https://github.com/ralphtheninja" + }, + { + "name": "David Björklund", + "email": "david.bjorklund@gmail.com", + "url": "https://github.com/kesla" + }, + { + "name": "Julian Gruber", + "email": "julian@juliangruber.com", + "url": "https://github.com/juliangruber" + }, + { + "name": "Paolo Fragomeni", + "email": "paolo@async.ly", + "url": "https://github.com/hij1nx" + }, + { + "name": "Anton Whalley", + "email": "anton.whalley@nearform.com", + "url": "https://github.com/No9" + }, + { + "name": "Matteo Collina", + "email": "matteo.collina@gmail.com", + "url": "https://github.com/mcollina" + }, + { + "name": "Pedro Teixeira", + "email": "pedro.teixeira@gmail.com", + "url": "https://github.com/pgte" + }, + { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "https://github.com/substack" + } + ], + "repository": { + "type": "git", + "url": "https://github.com/rvagg/node-levelup.git" + }, + "homepage": "https://github.com/rvagg/node-levelup", + "keywords": [ + "leveldb", + "stream", + "database", + "db", + "store", + "storage", + "json" + ], + "main": "lib/levelup.js", + "dependencies": { + "bl": "~0.8.1", + "deferred-leveldown": "~0.2.0", + "errno": "~0.1.1", + "prr": "~0.0.0", + "readable-stream": "~1.0.26", + "semver": "~2.3.1", + "xtend": "~3.0.0" + }, + "devDependencies": { + "leveldown": "~0.10.0", + "bustermove": "*", + "tap": "*", + "referee": "*", + "rimraf": "*", + "async": "*", + "fstream": "*", + "tar": "*", + "mkfiletree": "*", + "readfiletree": "*", + "slow-stream": ">=0.0.4", + "delayed": "*", + "boganipsum": "*", + "du": "*", + "memdown": "*", + "msgpack-js": "*" + }, + "browser": { + "leveldown": false, + "leveldown/package": false, + "semver": false + }, + "scripts": { + "test": "tap test/*-test.js --stderr", + "functionaltests": "node ./test/functional/fstream-test.js && node ./test/functional/binary-data-test.js && node ./test/functional/compat-test.js", + "alltests": "npm test && npm run-script functionaltests" + }, + "license": "MIT", + "gitHead": "213e989e2b75273e2b44c23f84f95e35bff7ea11", + "bugs": { + "url": "https://github.com/rvagg/node-levelup/issues" + }, + "_id": "levelup@0.18.6", + "_shasum": "e6a01cb089616c8ecc0291c2a9bd3f0c44e3e5eb", + "_from": "levelup@~0.18.4", + "_npmVersion": "1.4.14", + "_npmUser": { + "name": "rvagg", + "email": "rod@vagg.org" + }, + "maintainers": [ + { + "name": "rvagg", + "email": "rod@vagg.org" + } + ], + "dist": { + "shasum": "e6a01cb089616c8ecc0291c2a9bd3f0c44e3e5eb", + "tarball": "http://127.0.0.1:5080/tarballs/levelup/0.18.6.tgz" + }, + "_resolved": "http://127.0.0.1:5080/tarballs/levelup/0.18.6.tgz", + "readme": "ERROR: No README data found!" +} + +},{}],98:[function(_dereq_,module,exports){ +'use strict'; + +module.exports = INTERNAL; + +function INTERNAL() {} +},{}],99:[function(_dereq_,module,exports){ +'use strict'; +var Promise = _dereq_('./promise'); +var reject = _dereq_('./reject'); +var resolve = _dereq_('./resolve'); +var INTERNAL = _dereq_('./INTERNAL'); +var handlers = _dereq_('./handlers'); +module.exports = all; +function all(iterable) { + if (Object.prototype.toString.call(iterable) !== '[object Array]') { + return reject(new TypeError('must be an array')); + } + + var len = iterable.length; + var called = false; + if (!len) { + return resolve([]); + } + + var values = new Array(len); + var resolved = 0; + var i = -1; + var promise = new Promise(INTERNAL); + + while (++i < len) { + allResolver(iterable[i], i); + } + return promise; + function allResolver(value, i) { + resolve(value).then(resolveFromAll, function (error) { + if (!called) { + called = true; + handlers.reject(promise, error); + } + }); + function resolveFromAll(outValue) { + values[i] = outValue; + if (++resolved === len & !called) { + called = true; + handlers.resolve(promise, values); + } + } + } +} +},{"./INTERNAL":98,"./handlers":100,"./promise":102,"./reject":105,"./resolve":106}],100:[function(_dereq_,module,exports){ +'use strict'; +var tryCatch = _dereq_('./tryCatch'); +var resolveThenable = _dereq_('./resolveThenable'); +var states = _dereq_('./states'); + +exports.resolve = function (self, value) { + var result = tryCatch(getThen, value); + if (result.status === 'error') { + return exports.reject(self, result.value); + } + var thenable = result.value; + + if (thenable) { + resolveThenable.safely(self, thenable); + } else { + self.state = states.FULFILLED; + self.outcome = value; + var i = -1; + var len = self.queue.length; + while (++i < len) { + self.queue[i].callFulfilled(value); + } + } + return self; +}; +exports.reject = function (self, error) { + self.state = states.REJECTED; + self.outcome = error; + var i = -1; + var len = self.queue.length; + while (++i < len) { + self.queue[i].callRejected(error); + } + return self; +}; + +function getThen(obj) { + // Make sure we only access the accessor once as required by the spec + var then = obj && obj.then; + if (obj && typeof obj === 'object' && typeof then === 'function') { + return function appyThen() { + then.apply(obj, arguments); + }; + } +} +},{"./resolveThenable":107,"./states":108,"./tryCatch":109}],101:[function(_dereq_,module,exports){ +module.exports = exports = _dereq_('./promise'); + +exports.resolve = _dereq_('./resolve'); +exports.reject = _dereq_('./reject'); +exports.all = _dereq_('./all'); +exports.race = _dereq_('./race'); +},{"./all":99,"./promise":102,"./race":104,"./reject":105,"./resolve":106}],102:[function(_dereq_,module,exports){ +'use strict'; + +var unwrap = _dereq_('./unwrap'); +var INTERNAL = _dereq_('./INTERNAL'); +var resolveThenable = _dereq_('./resolveThenable'); +var states = _dereq_('./states'); +var QueueItem = _dereq_('./queueItem'); + +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); + } +} + +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)); + } + + return promise; +}; + +},{"./INTERNAL":98,"./queueItem":103,"./resolveThenable":107,"./states":108,"./unwrap":110}],103:[function(_dereq_,module,exports){ +'use strict'; +var handlers = _dereq_('./handlers'); +var unwrap = _dereq_('./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":100,"./unwrap":110}],104:[function(_dereq_,module,exports){ +'use strict'; +var Promise = _dereq_('./promise'); +var reject = _dereq_('./reject'); +var resolve = _dereq_('./resolve'); +var INTERNAL = _dereq_('./INTERNAL'); +var handlers = _dereq_('./handlers'); +module.exports = race; +function race(iterable) { + if (Object.prototype.toString.call(iterable) !== '[object Array]') { + return reject(new TypeError('must be an array')); + } + + var len = iterable.length; + var called = false; + if (!len) { + return resolve([]); + } + + var resolved = 0; + var i = -1; + var promise = new Promise(INTERNAL); + + while (++i < len) { + resolver(iterable[i]); + } + return promise; + function resolver(value) { + resolve(value).then(function (response) { + if (!called) { + called = true; + handlers.resolve(promise, response); + } + }, function (error) { + if (!called) { + called = true; + handlers.reject(promise, error); + } + }); + } +} +},{"./INTERNAL":98,"./handlers":100,"./promise":102,"./reject":105,"./resolve":106}],105:[function(_dereq_,module,exports){ +'use strict'; + +var Promise = _dereq_('./promise'); +var INTERNAL = _dereq_('./INTERNAL'); +var handlers = _dereq_('./handlers'); +module.exports = reject; + +function reject(reason) { + var promise = new Promise(INTERNAL); + return handlers.reject(promise, reason); +} +},{"./INTERNAL":98,"./handlers":100,"./promise":102}],106:[function(_dereq_,module,exports){ +'use strict'; + +var Promise = _dereq_('./promise'); +var INTERNAL = _dereq_('./INTERNAL'); +var handlers = _dereq_('./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":98,"./handlers":100,"./promise":102}],107:[function(_dereq_,module,exports){ +'use strict'; +var handlers = _dereq_('./handlers'); +var tryCatch = _dereq_('./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":100,"./tryCatch":109}],108:[function(_dereq_,module,exports){ +// Lazy man's symbols for states + +exports.REJECTED = ['REJECTED']; +exports.FULFILLED = ['FULFILLED']; +exports.PENDING = ['PENDING']; +},{}],109:[function(_dereq_,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; +} +},{}],110:[function(_dereq_,module,exports){ +'use strict'; + +var immediate = _dereq_('immediate'); +var handlers = _dereq_('./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":100,"immediate":111}],111:[function(_dereq_,module,exports){ +'use strict'; +var types = [ + _dereq_('./nextTick'), + _dereq_('./mutation.js'), + _dereq_('./messageChannel'), + _dereq_('./stateChange'), + _dereq_('./timeout') +]; +var draining; +var queue = []; +//named nextTick for less confusing stack traces +function nextTick() { + draining = true; + var i, oldQueue; + var len = queue.length; + while (len) { + oldQueue = queue; + queue = []; + i = -1; + while (++i < len) { + oldQueue[i](); + } + len = queue.length; + } + draining = false; +} +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; + } +} +module.exports = immediate; +function immediate(task) { + if (queue.push(task) === 1 && !draining) { + scheduleDrain(); + } +} +},{"./messageChannel":112,"./mutation.js":113,"./nextTick":16,"./stateChange":114,"./timeout":115}],112:[function(_dereq_,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 : {}) +},{}],113:[function(_dereq_,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 : {}) +},{}],114:[function(_dereq_,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 <script> 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 : {}) +},{}],115:[function(_dereq_,module,exports){ +'use strict'; +exports.test = function () { + return true; +}; + +exports.install = function (t) { + return function () { + setTimeout(t, 0); + }; +}; +},{}],116:[function(_dereq_,module,exports){ +"use strict"; + +// Extends method +// (taken from http://code.jquery.com/jquery-1.9.0.js) +// Populate the class2type map +var class2type = {}; + +var types = [ + "Boolean", "Number", "String", "Function", "Array", + "Date", "RegExp", "Object", "Error" +]; +for (var i = 0; i < types.length; i++) { + var typename = types[i]; + class2type["[object " + typename + "]"] = typename.toLowerCase(); +} + +var core_toString = class2type.toString; +var core_hasOwn = class2type.hasOwnProperty; + +function type(obj) { + if (obj === null) { + return String(obj); + } + return typeof obj === "object" || typeof obj === "function" ? + class2type[core_toString.call(obj)] || "object" : + typeof obj; +} + +function isWindow(obj) { + return obj !== null && obj === obj.window; +} + +function isPlainObject(obj) { + // Must be an Object. + // Because of IE, we also have to check the presence of + // the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if (!obj || type(obj) !== "object" || obj.nodeType || isWindow(obj)) { + return false; + } + + try { + // Not own constructor property must be Object + if (obj.constructor && + !core_hasOwn.call(obj, "constructor") && + !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + var key; + for (key in obj) {} + + return key === undefined || core_hasOwn.call(obj, key); +} + + +function isFunction(obj) { + return type(obj) === "function"; +} + +var isArray = Array.isArray || function (obj) { + return type(obj) === "array"; +}; + +function extend() { + // originally extend() was recursive, but this ended up giving us + // "call stack exceeded", so it's been unrolled to use a literal stack + // (see https://github.com/pouchdb/pouchdb/issues/2543) + var stack = []; + var i = -1; + var len = arguments.length; + var args = new Array(len); + while (++i < len) { + args[i] = arguments[i]; + } + var container = {}; + stack.push({args: args, result: {container: container, key: 'key'}}); + var next; + while ((next = stack.pop())) { + extendInner(stack, next.args, next.result); + } + return container.key; +} + +function extendInner(stack, args, result) { + var options, name, src, copy, copyIsArray, clone, + target = args[0] || {}, + i = 1, + length = args.length, + deep = false, + numericStringRegex = /\d+/, + optionsIsArray; + + // Handle a deep copy situation + if (typeof target === "boolean") { + deep = target; + target = args[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if (typeof target !== "object" && !isFunction(target)) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if (length === i) { + /* jshint validthis: true */ + target = this; + --i; + } + + for (; i < length; i++) { + // Only deal with non-null/undefined values + if ((options = args[i]) != null) { + optionsIsArray = isArray(options); + // Extend the base object + for (name in options) { + //if (options.hasOwnProperty(name)) { + if (!(name in Object.prototype)) { + if (optionsIsArray && !numericStringRegex.test(name)) { + continue; + } + + src = target[name]; + copy = options[name]; + + // Prevent never-ending loop + if (target === copy) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if (deep && copy && (isPlainObject(copy) || + (copyIsArray = isArray(copy)))) { + if (copyIsArray) { + copyIsArray = false; + clone = src && isArray(src) ? src : []; + + } else { + clone = src && isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + stack.push({ + args: [deep, clone, copy], + result: { + container: target, + key: name + } + }); + + // Don't bring in undefined values + } else if (copy !== undefined) { + if (!(isArray(options) && isFunction(copy))) { + target[name] = copy; + } + } + } + } + } + } + + // "Return" the modified object by setting the key + // on the given container + result.container[result.key] = target; +} + + +module.exports = extend; + + + +},{}],117:[function(_dereq_,module,exports){ +/*jshint bitwise:false*/ +/*global unescape*/ + +(function (factory) { + if (typeof exports === 'object') { + // Node/CommonJS + module.exports = factory(); + } else if (typeof define === 'function' && define.amd) { + // AMD + define(factory); + } else { + // Browser globals (with support for web workers) + var glob; + try { + glob = window; + } catch (e) { + glob = self; + } + + glob.SparkMD5 = factory(); + } +}(function (undefined) { + + 'use strict'; + + //////////////////////////////////////////////////////////////////////////// + + /* + * Fastest md5 implementation around (JKM md5) + * Credits: Joseph Myers + * + * @see http://www.myersdaily.org/joseph/javascript/md5-text.html + * @see http://jsperf.com/md5-shootout/7 + */ + + /* this function is much faster, + so if possible we use it. Some IEs + are the only ones I know of that + need the idiotic second function, + generated by an if clause. */ + var add32 = function (a, b) { + return (a + b) & 0xFFFFFFFF; + }, + + cmn = function (q, a, b, x, s, t) { + a = add32(add32(a, q), add32(x, t)); + return add32((a << s) | (a >>> (32 - s)), b); + }, + + ff = function (a, b, c, d, x, s, t) { + return cmn((b & c) | ((~b) & d), a, b, x, s, t); + }, + + gg = function (a, b, c, d, x, s, t) { + return cmn((b & d) | (c & (~d)), a, b, x, s, t); + }, + + hh = function (a, b, c, d, x, s, t) { + return cmn(b ^ c ^ d, a, b, x, s, t); + }, + + ii = function (a, b, c, d, x, s, t) { + return cmn(c ^ (b | (~d)), a, b, x, s, t); + }, + + md5cycle = function (x, k) { + var a = x[0], + b = x[1], + c = x[2], + d = x[3]; + + a = ff(a, b, c, d, k[0], 7, -680876936); + d = ff(d, a, b, c, k[1], 12, -389564586); + c = ff(c, d, a, b, k[2], 17, 606105819); + b = ff(b, c, d, a, k[3], 22, -1044525330); + a = ff(a, b, c, d, k[4], 7, -176418897); + d = ff(d, a, b, c, k[5], 12, 1200080426); + c = ff(c, d, a, b, k[6], 17, -1473231341); + b = ff(b, c, d, a, k[7], 22, -45705983); + a = ff(a, b, c, d, k[8], 7, 1770035416); + d = ff(d, a, b, c, k[9], 12, -1958414417); + c = ff(c, d, a, b, k[10], 17, -42063); + b = ff(b, c, d, a, k[11], 22, -1990404162); + a = ff(a, b, c, d, k[12], 7, 1804603682); + d = ff(d, a, b, c, k[13], 12, -40341101); + c = ff(c, d, a, b, k[14], 17, -1502002290); + b = ff(b, c, d, a, k[15], 22, 1236535329); + + a = gg(a, b, c, d, k[1], 5, -165796510); + d = gg(d, a, b, c, k[6], 9, -1069501632); + c = gg(c, d, a, b, k[11], 14, 643717713); + b = gg(b, c, d, a, k[0], 20, -373897302); + a = gg(a, b, c, d, k[5], 5, -701558691); + d = gg(d, a, b, c, k[10], 9, 38016083); + c = gg(c, d, a, b, k[15], 14, -660478335); + b = gg(b, c, d, a, k[4], 20, -405537848); + a = gg(a, b, c, d, k[9], 5, 568446438); + d = gg(d, a, b, c, k[14], 9, -1019803690); + c = gg(c, d, a, b, k[3], 14, -187363961); + b = gg(b, c, d, a, k[8], 20, 1163531501); + a = gg(a, b, c, d, k[13], 5, -1444681467); + d = gg(d, a, b, c, k[2], 9, -51403784); + c = gg(c, d, a, b, k[7], 14, 1735328473); + b = gg(b, c, d, a, k[12], 20, -1926607734); + + a = hh(a, b, c, d, k[5], 4, -378558); + d = hh(d, a, b, c, k[8], 11, -2022574463); + c = hh(c, d, a, b, k[11], 16, 1839030562); + b = hh(b, c, d, a, k[14], 23, -35309556); + a = hh(a, b, c, d, k[1], 4, -1530992060); + d = hh(d, a, b, c, k[4], 11, 1272893353); + c = hh(c, d, a, b, k[7], 16, -155497632); + b = hh(b, c, d, a, k[10], 23, -1094730640); + a = hh(a, b, c, d, k[13], 4, 681279174); + d = hh(d, a, b, c, k[0], 11, -358537222); + c = hh(c, d, a, b, k[3], 16, -722521979); + b = hh(b, c, d, a, k[6], 23, 76029189); + a = hh(a, b, c, d, k[9], 4, -640364487); + d = hh(d, a, b, c, k[12], 11, -421815835); + c = hh(c, d, a, b, k[15], 16, 530742520); + b = hh(b, c, d, a, k[2], 23, -995338651); + + a = ii(a, b, c, d, k[0], 6, -198630844); + d = ii(d, a, b, c, k[7], 10, 1126891415); + c = ii(c, d, a, b, k[14], 15, -1416354905); + b = ii(b, c, d, a, k[5], 21, -57434055); + a = ii(a, b, c, d, k[12], 6, 1700485571); + d = ii(d, a, b, c, k[3], 10, -1894986606); + c = ii(c, d, a, b, k[10], 15, -1051523); + b = ii(b, c, d, a, k[1], 21, -2054922799); + a = ii(a, b, c, d, k[8], 6, 1873313359); + d = ii(d, a, b, c, k[15], 10, -30611744); + c = ii(c, d, a, b, k[6], 15, -1560198380); + b = ii(b, c, d, a, k[13], 21, 1309151649); + a = ii(a, b, c, d, k[4], 6, -145523070); + d = ii(d, a, b, c, k[11], 10, -1120210379); + c = ii(c, d, a, b, k[2], 15, 718787259); + b = ii(b, c, d, a, k[9], 21, -343485551); + + x[0] = add32(a, x[0]); + x[1] = add32(b, x[1]); + x[2] = add32(c, x[2]); + x[3] = add32(d, x[3]); + }, + + /* there needs to be support for Unicode here, + * unless we pretend that we can redefine the MD-5 + * algorithm for multi-byte characters (perhaps + * by adding every four 16-bit characters and + * shortening the sum to 32 bits). Otherwise + * I suggest performing MD-5 as if every character + * was two bytes--e.g., 0040 0025 = @%--but then + * how will an ordinary MD-5 sum be matched? + * There is no way to standardize text to something + * like UTF-8 before transformation; speed cost is + * utterly prohibitive. The JavaScript standard + * itself needs to look at this: it should start + * providing access to strings as preformed UTF-8 + * 8-bit unsigned value arrays. + */ + md5blk = function (s) { + var md5blks = [], + i; /* Andy King said do it this way. */ + + for (i = 0; i < 64; i += 4) { + md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); + } + return md5blks; + }, + + md5blk_array = function (a) { + var md5blks = [], + i; /* Andy King said do it this way. */ + + for (i = 0; i < 64; i += 4) { + md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24); + } + return md5blks; + }, + + md51 = function (s) { + var n = s.length, + state = [1732584193, -271733879, -1732584194, 271733878], + i, + length, + tail, + tmp, + lo, + hi; + + for (i = 64; i <= n; i += 64) { + md5cycle(state, md5blk(s.substring(i - 64, i))); + } + s = s.substring(i - 64); + length = s.length; + tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3); + } + tail[i >> 2] |= 0x80 << ((i % 4) << 3); + if (i > 55) { + md5cycle(state, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + + // Beware that the final length might not fit in 32 bits so we take care of that + tmp = n * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + + tail[14] = lo; + tail[15] = hi; + + md5cycle(state, tail); + return state; + }, + + md51_array = function (a) { + var n = a.length, + state = [1732584193, -271733879, -1732584194, 271733878], + i, + length, + tail, + tmp, + lo, + hi; + + for (i = 64; i <= n; i += 64) { + md5cycle(state, md5blk_array(a.subarray(i - 64, i))); + } + + // Not sure if it is a bug, however IE10 will always produce a sub array of length 1 + // containing the last element of the parent array if the sub array specified starts + // beyond the length of the parent array - weird. + // https://connect.microsoft.com/IE/feedback/details/771452/typed-array-subarray-issue + a = (i - 64) < n ? a.subarray(i - 64) : new Uint8Array(0); + + length = a.length; + tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= a[i] << ((i % 4) << 3); + } + + tail[i >> 2] |= 0x80 << ((i % 4) << 3); + if (i > 55) { + md5cycle(state, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + + // Beware that the final length might not fit in 32 bits so we take care of that + tmp = n * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + + tail[14] = lo; + tail[15] = hi; + + md5cycle(state, tail); + + return state; + }, + + hex_chr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'], + + rhex = function (n) { + var s = '', + j; + for (j = 0; j < 4; j += 1) { + s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]; + } + return s; + }, + + hex = function (x) { + var i; + for (i = 0; i < x.length; i += 1) { + x[i] = rhex(x[i]); + } + return x.join(''); + }, + + md5 = function (s) { + return hex(md51(s)); + }, + + + + //////////////////////////////////////////////////////////////////////////// + + /** + * SparkMD5 OOP implementation. + * + * Use this class to perform an incremental md5, otherwise use the + * static methods instead. + */ + SparkMD5 = function () { + // call reset to init the instance + this.reset(); + }; + + + // In some cases the fast add32 function cannot be used.. + if (md5('hello') !== '5d41402abc4b2a76b9719d911017c592') { + add32 = function (x, y) { + var lsw = (x & 0xFFFF) + (y & 0xFFFF), + msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xFFFF); + }; + } + + + /** + * Appends a string. + * A conversion will be applied if an utf8 string is detected. + * + * @param {String} str The string to be appended + * + * @return {SparkMD5} The instance itself + */ + SparkMD5.prototype.append = function (str) { + // converts the string to utf8 bytes if necessary + if (/[\u0080-\uFFFF]/.test(str)) { + str = unescape(encodeURIComponent(str)); + } + + // then append as binary + this.appendBinary(str); + + return this; + }; + + /** + * Appends a binary string. + * + * @param {String} contents The binary string to be appended + * + * @return {SparkMD5} The instance itself + */ + SparkMD5.prototype.appendBinary = function (contents) { + this._buff += contents; + this._length += contents.length; + + var length = this._buff.length, + i; + + for (i = 64; i <= length; i += 64) { + md5cycle(this._state, md5blk(this._buff.substring(i - 64, i))); + } + + this._buff = this._buff.substr(i - 64); + + return this; + }; + + /** + * Finishes the incremental computation, reseting the internal state and + * returning the result. + * Use the raw parameter to obtain the raw result instead of the hex one. + * + * @param {Boolean} raw True to get the raw result, false to get the hex result + * + * @return {String|Array} The result + */ + SparkMD5.prototype.end = function (raw) { + var buff = this._buff, + length = buff.length, + i, + tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + ret; + + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= buff.charCodeAt(i) << ((i % 4) << 3); + } + + this._finish(tail, length); + ret = !!raw ? this._state : hex(this._state); + + this.reset(); + + return ret; + }; + + /** + * Finish the final calculation based on the tail. + * + * @param {Array} tail The tail (will be modified) + * @param {Number} length The length of the remaining buffer + */ + SparkMD5.prototype._finish = function (tail, length) { + var i = length, + tmp, + lo, + hi; + + tail[i >> 2] |= 0x80 << ((i % 4) << 3); + if (i > 55) { + md5cycle(this._state, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + + // Do the final computation based on the tail and length + // Beware that the final length may not fit in 32 bits so we take care of that + tmp = this._length * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + + tail[14] = lo; + tail[15] = hi; + md5cycle(this._state, tail); + }; + + /** + * Resets the internal state of the computation. + * + * @return {SparkMD5} The instance itself + */ + SparkMD5.prototype.reset = function () { + this._buff = ""; + this._length = 0; + this._state = [1732584193, -271733879, -1732584194, 271733878]; + + return this; + }; + + /** + * Releases memory used by the incremental buffer and other aditional + * resources. If you plan to use the instance again, use reset instead. + */ + SparkMD5.prototype.destroy = function () { + delete this._state; + delete this._buff; + delete this._length; + }; + + + /** + * Performs the md5 hash on a string. + * A conversion will be applied if utf8 string is detected. + * + * @param {String} str The string + * @param {Boolean} raw True to get the raw result, false to get the hex result + * + * @return {String|Array} The result + */ + SparkMD5.hash = function (str, raw) { + // converts the string to utf8 bytes if necessary + if (/[\u0080-\uFFFF]/.test(str)) { + str = unescape(encodeURIComponent(str)); + } + + var hash = md51(str); + + return !!raw ? hash : hex(hash); + }; + + /** + * Performs the md5 hash on a binary string. + * + * @param {String} content The binary string + * @param {Boolean} raw True to get the raw result, false to get the hex result + * + * @return {String|Array} The result + */ + SparkMD5.hashBinary = function (content, raw) { + var hash = md51(content); + + return !!raw ? hash : hex(hash); + }; + + /** + * SparkMD5 OOP implementation for array buffers. + * + * Use this class to perform an incremental md5 ONLY for array buffers. + */ + SparkMD5.ArrayBuffer = function () { + // call reset to init the instance + this.reset(); + }; + + //////////////////////////////////////////////////////////////////////////// + + /** + * Appends an array buffer. + * + * @param {ArrayBuffer} arr The array to be appended + * + * @return {SparkMD5.ArrayBuffer} The instance itself + */ + SparkMD5.ArrayBuffer.prototype.append = function (arr) { + // TODO: we could avoid the concatenation here but the algorithm would be more complex + // if you find yourself needing extra performance, please make a PR. + var buff = this._concatArrayBuffer(this._buff, arr), + length = buff.length, + i; + + this._length += arr.byteLength; + + for (i = 64; i <= length; i += 64) { + md5cycle(this._state, md5blk_array(buff.subarray(i - 64, i))); + } + + // Avoids IE10 weirdness (documented above) + this._buff = (i - 64) < length ? buff.subarray(i - 64) : new Uint8Array(0); + + return this; + }; + + /** + * Finishes the incremental computation, reseting the internal state and + * returning the result. + * Use the raw parameter to obtain the raw result instead of the hex one. + * + * @param {Boolean} raw True to get the raw result, false to get the hex result + * + * @return {String|Array} The result + */ + SparkMD5.ArrayBuffer.prototype.end = function (raw) { + var buff = this._buff, + length = buff.length, + tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + i, + ret; + + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= buff[i] << ((i % 4) << 3); + } + + this._finish(tail, length); + ret = !!raw ? this._state : hex(this._state); + + this.reset(); + + return ret; + }; + + SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish; + + /** + * Resets the internal state of the computation. + * + * @return {SparkMD5.ArrayBuffer} The instance itself + */ + SparkMD5.ArrayBuffer.prototype.reset = function () { + this._buff = new Uint8Array(0); + this._length = 0; + this._state = [1732584193, -271733879, -1732584194, 271733878]; + + return this; + }; + + /** + * Releases memory used by the incremental buffer and other aditional + * resources. If you plan to use the instance again, use reset instead. + */ + SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy; + + /** + * Concats two array buffers, returning a new one. + * + * @param {ArrayBuffer} first The first array buffer + * @param {ArrayBuffer} second The second array buffer + * + * @return {ArrayBuffer} The new array buffer + */ + SparkMD5.ArrayBuffer.prototype._concatArrayBuffer = function (first, second) { + var firstLength = first.length, + result = new Uint8Array(firstLength + second.byteLength); + + result.set(first); + result.set(new Uint8Array(second), firstLength); + + return result; + }; + + /** + * Performs the md5 hash on an array buffer. + * + * @param {ArrayBuffer} arr The array buffer + * @param {Boolean} raw True to get the raw result, false to get the hex result + * + * @return {String|Array} The result + */ + SparkMD5.ArrayBuffer.hash = function (arr, raw) { + var hash = md51_array(new Uint8Array(arr)); + + return !!raw ? hash : hex(hash); + }; + + return SparkMD5; +})); + +},{}],118:[function(_dereq_,module,exports){ +module.exports=_dereq_(26) +},{"./_stream_readable":119,"./_stream_writable":121,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_duplex.js":26,"_process":24,"core-util-is":122,"inherits":44}],119:[function(_dereq_,module,exports){ +module.exports=_dereq_(28) +},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_readable.js":28,"_process":24,"buffer":17,"core-util-is":122,"events":21,"inherits":44,"isarray":123,"stream":36,"string_decoder/":124}],120:[function(_dereq_,module,exports){ +module.exports=_dereq_(29) +},{"./_stream_duplex":118,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_transform.js":29,"core-util-is":122,"inherits":44}],121:[function(_dereq_,module,exports){ +module.exports=_dereq_(30) +},{"./_stream_duplex":118,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_writable.js":30,"_process":24,"buffer":17,"core-util-is":122,"inherits":44,"stream":36}],122:[function(_dereq_,module,exports){ +module.exports=_dereq_(31) +},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/node_modules/core-util-is/lib/util.js":31,"buffer":17}],123:[function(_dereq_,module,exports){ +module.exports=_dereq_(22) +},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/isarray/index.js":22}],124:[function(_dereq_,module,exports){ +module.exports=_dereq_(37) +},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/string_decoder/index.js":37,"buffer":17}],125:[function(_dereq_,module,exports){ +module.exports=_dereq_(34) +},{"./lib/_stream_transform.js":120,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/transform.js":34}],126:[function(_dereq_,module,exports){ +module.exports=_dereq_(54) +},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/has-keys.js":54}],127:[function(_dereq_,module,exports){ +module.exports=_dereq_(55) +},{"./has-keys":126,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/index.js":55,"object-keys":129}],128:[function(_dereq_,module,exports){ +module.exports=_dereq_(56) +},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/foreach.js":56}],129:[function(_dereq_,module,exports){ +module.exports=_dereq_(57) +},{"./shim":131,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/index.js":57}],130:[function(_dereq_,module,exports){ +module.exports=_dereq_(58) +},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/isArguments.js":58}],131:[function(_dereq_,module,exports){ +module.exports=_dereq_(59) +},{"./foreach":128,"./isArguments":130,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/shim.js":59}],132:[function(_dereq_,module,exports){ +var Transform = _dereq_('readable-stream/transform') + , inherits = _dereq_('util').inherits + , xtend = _dereq_('xtend') + + +// a noop _transform function +function noop (chunk, enc, callback) { + callback(null, chunk) +} + + +// create a new export function, used by both the main export and +// the .ctor export, contains common logic for dealing with arguments +function through2 (construct) { + return function (options, transform, flush) { + if (typeof options == 'function') { + flush = transform + transform = options + options = {} + } + + if (typeof transform != 'function') + transform = noop + + if (typeof flush != 'function') + flush = null + + return construct(options, transform, flush) + } +} + + +// main export, just make me a transform stream! +module.exports = through2(function (options, transform, flush) { + var t2 = new Transform(options) + + t2._transform = transform + + if (flush) + t2._flush = flush + + return t2 +}) + + +// make me a reusable prototype that I can `new`, or implicitly `new` +// with a constructor call +module.exports.ctor = through2(function (options, transform, flush) { + function Through2 (override) { + if (!(this instanceof Through2)) + return new Through2(override) + + this.options = xtend(options, override) + + Transform.call(this, this.options) + } + + inherits(Through2, Transform) + + Through2.prototype._transform = transform + + if (flush) + Through2.prototype._flush = flush + + return Through2 +}) + + +module.exports.obj = through2(function (options, transform, flush) { + var t2 = new Transform(xtend({ objectMode: true }, options)) + + t2._transform = transform + + if (flush) + t2._flush = flush + + return t2 +}) + +},{"readable-stream/transform":125,"util":39,"xtend":127}],133:[function(_dereq_,module,exports){ +'use strict'; + +/** + * Stringify/parse functions that don't operate + * recursively, so they avoid call stack exceeded + * errors. + */ +exports.stringify = function stringify(input) { + var queue = []; + queue.push({obj: input}); + + var res = ''; + var next, obj, prefix, val, i, arrayPrefix, keys, k, key, value, objPrefix; + while ((next = queue.pop())) { + obj = next.obj; + prefix = next.prefix || ''; + val = next.val || ''; + res += prefix; + if (val) { + res += val; + } else if (typeof obj !== 'object') { + res += typeof obj === 'undefined' ? null : JSON.stringify(obj); + } else if (obj === null) { + res += 'null'; + } else if (Array.isArray(obj)) { + queue.push({val: ']'}); + for (i = obj.length - 1; i >= 0; i--) { + arrayPrefix = i === 0 ? '' : ','; + queue.push({obj: obj[i], prefix: arrayPrefix}); + } + queue.push({val: '['}); + } else { // object + keys = []; + for (k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + queue.push({val: '}'}); + for (i = keys.length - 1; i >= 0; i--) { + key = keys[i]; + value = obj[key]; + objPrefix = (i > 0 ? ',' : ''); + objPrefix += JSON.stringify(key) + ':'; + queue.push({obj: value, prefix: objPrefix}); + } + queue.push({val: '{'}); + } + } + return res; +}; + +// Convenience function for the parse function. +// This pop function is basically copied from +// pouchCollate.parseIndexableString +function pop(obj, stack, metaStack) { + var lastMetaElement = metaStack[metaStack.length - 1]; + if (obj === lastMetaElement.element) { + // popping a meta-element, e.g. an object whose value is another object + metaStack.pop(); + lastMetaElement = metaStack[metaStack.length - 1]; + } + var element = lastMetaElement.element; + var lastElementIndex = lastMetaElement.index; + if (Array.isArray(element)) { + element.push(obj); + } else if (lastElementIndex === stack.length - 2) { // obj with key+value + var key = stack.pop(); + element[key] = obj; + } else { + stack.push(obj); // obj with key only + } +} + +exports.parse = function (str) { + var stack = []; + var metaStack = []; // stack for arrays and objects + var i = 0; + var collationIndex,parsedNum,numChar; + var parsedString,lastCh,numConsecutiveSlashes,ch; + var arrayElement, objElement; + while (true) { + collationIndex = str[i++]; + if (collationIndex === '}' || + collationIndex === ']' || + typeof collationIndex === 'undefined') { + if (stack.length === 1) { + return stack.pop(); + } else { + pop(stack.pop(), stack, metaStack); + continue; + } + } + switch (collationIndex) { + case ' ': + case '\t': + case '\n': + case ':': + case ',': + break; + case 'n': + i += 3; // 'ull' + pop(null, stack, metaStack); + break; + case 't': + i += 3; // 'rue' + pop(true, stack, metaStack); + break; + case 'f': + i += 4; // 'alse' + pop(false, stack, metaStack); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + parsedNum = ''; + i--; + while (true) { + numChar = str[i++]; + if (/[\d\.\-e\+]/.test(numChar)) { + parsedNum += numChar; + } else { + i--; + break; + } + } + pop(parseFloat(parsedNum), stack, metaStack); + break; + case '"': + parsedString = ''; + lastCh = void 0; + numConsecutiveSlashes = 0; + while (true) { + ch = str[i++]; + if (ch !== '"' || (lastCh === '\\' && + numConsecutiveSlashes % 2 === 1)) { + parsedString += ch; + lastCh = ch; + if (lastCh === '\\') { + numConsecutiveSlashes++; + } else { + numConsecutiveSlashes = 0; + } + } else { + break; + } + } + pop(JSON.parse('"' + parsedString + '"'), stack, metaStack); + break; + case '[': + arrayElement = { element: [], index: stack.length }; + stack.push(arrayElement.element); + metaStack.push(arrayElement); + break; + case '{': + objElement = { element: {}, index: stack.length }; + stack.push(objElement.element); + metaStack.push(objElement); + break; + default: + throw new Error( + 'unexpectedly reached end of input: ' + collationIndex); + } + } +}; + +},{}],"adapter-config":[function(_dereq_,module,exports){ +'use strict'; + +module.exports = { + name: 'memory', + valid: function () { + return true; + }, + use_prefix: false +}; +},{}],"leveldown":[function(_dereq_,module,exports){ +(function (Buffer){ +module.exports = Level + +var IDB = _dereq_('idb-wrapper') +var AbstractLevelDOWN = _dereq_('abstract-leveldown').AbstractLevelDOWN +var util = _dereq_('util') +var Iterator = _dereq_('./iterator') +var isBuffer = _dereq_('isbuffer') +var xtend = _dereq_('xtend') +var toBuffer = _dereq_('typedarray-to-buffer') + +function Level(location) { + if (!(this instanceof Level)) return new Level(location) + if (!location) throw new Error("constructor requires at least a location argument") + this.IDBOptions = {} + this.location = location +} + +util.inherits(Level, AbstractLevelDOWN) + +Level.prototype._open = function(options, callback) { + var self = this + + var idbOpts = { + storeName: this.location, + autoIncrement: false, + keyPath: null, + onStoreReady: function () { + callback && callback(null, self.idb) + }, + onError: function(err) { + callback && callback(err) + } + } + + xtend(idbOpts, options) + this.IDBOptions = idbOpts + this.idb = new IDB(idbOpts) +} + +Level.prototype._get = function (key, options, callback) { + this.idb.get(key, function (value) { + if (value === undefined) { + // 'NotFound' error, consistent with LevelDOWN API + return callback(new Error('NotFound')) + } + // by default return buffers, unless explicitly told not to + var asBuffer = true + if (options.asBuffer === false) asBuffer = false + if (options.raw) asBuffer = false + if (asBuffer) { + if (value instanceof Uint8Array) value = toBuffer(value) + else value = new Buffer(String(value)) + } + return callback(null, value, key) + }, callback) +} + +Level.prototype._del = function(id, options, callback) { + this.idb.remove(id, callback, callback) +} + +Level.prototype._put = function (key, value, options, callback) { + if (value instanceof ArrayBuffer) { + value = toBuffer(new Uint8Array(value)) + } + var obj = this.convertEncoding(key, value, options) + if (Buffer.isBuffer(obj.value)) { + obj.value = new Uint8Array(value.toArrayBuffer()) + } + this.idb.put(obj.key, obj.value, function() { callback() }, callback) +} + +Level.prototype.convertEncoding = function(key, value, options) { + if (options.raw) return {key: key, value: value} + if (value) { + var stringed = value.toString() + if (stringed === 'NaN') value = 'NaN' + } + var valEnc = options.valueEncoding + var obj = {key: key, value: value} + if (value && (!valEnc || valEnc !== 'binary')) { + if (typeof obj.value !== 'object') { + obj.value = stringed + } + } + return obj +} + +Level.prototype.iterator = function (options) { + if (typeof options !== 'object') options = {} + return new Iterator(this.idb, options) +} + +Level.prototype._batch = function (array, options, callback) { + var op + var i + var k + var copiedOp + var currentOp + var modified = [] + + if (array.length === 0) return setTimeout(callback, 0) + + for (i = 0; i < array.length; i++) { + copiedOp = {} + currentOp = array[i] + modified[i] = copiedOp + + var converted = this.convertEncoding(currentOp.key, currentOp.value, options) + currentOp.key = converted.key + currentOp.value = converted.value + + for (k in currentOp) { + if (k === 'type' && currentOp[k] == 'del') { + copiedOp[k] = 'remove' + } else { + copiedOp[k] = currentOp[k] + } + } + } + + return this.idb.batch(modified, function(){ callback() }, callback) +} + +Level.prototype._close = function (callback) { + this.idb.db.close() + callback() +} + +Level.prototype._approximateSize = function (start, end, callback) { + var err = new Error('Not implemented') + if (callback) + return callback(err) + + throw err +} + +Level.prototype._isBuffer = function (obj) { + return Buffer.isBuffer(obj) +} + +Level.destroy = function (db, callback) { + if (typeof db === 'object') { + var prefix = db.IDBOptions.storePrefix || 'IDBWrapper-' + var dbname = db.location + } else { + var prefix = 'IDBWrapper-' + var dbname = db + } + var request = indexedDB.deleteDatabase(prefix + dbname) + request.onsuccess = function() { + callback() + } + request.onerror = function(err) { + callback(err) + } +} + +var checkKeyValue = Level.prototype._checkKeyValue = function (obj, type) { + if (obj === null || obj === undefined) + return new Error(type + ' cannot be `null` or `undefined`') + if (obj === null || obj === undefined) + return new Error(type + ' cannot be `null` or `undefined`') + if (isBuffer(obj) && obj.byteLength === 0) + return new Error(type + ' cannot be an empty ArrayBuffer') + if (String(obj) === '') + return new Error(type + ' cannot be an empty String') + if (obj.length === 0) + return new Error(type + ' cannot be an empty Array') +} + +}).call(this,_dereq_("buffer").Buffer) +},{"./iterator":45,"abstract-leveldown":48,"buffer":17,"idb-wrapper":50,"isbuffer":51,"typedarray-to-buffer":53,"util":39,"xtend":55}]},{},[11]); +
diff --git a/dist/pouchdb.memory.min.js b/dist/pouchdb.memory.min.js new file mode 100644 index 0000000..4090262 --- /dev/null +++ b/dist/pouchdb.memory.min.js
@@ -0,0 +1,13 @@ +// PouchDB in-memory plugin 3.2.0 +// Based on MemDOWN: https://github.com/rvagg/memdown +// +// (c) 2012-2014 Dale Harvey and the PouchDB team +// PouchDB may be freely distributed under the Apache license, version 2.0. +// For all details and documentation: +// http://pouchdb.com +require=function e(t,r,n){function o(s,a){if(!r[s]){if(!t[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(i)return i(s,!0);var c=new Error("Cannot find module '"+s+"'");throw c.code="MODULE_NOT_FOUND",c}var f=r[s]={exports:{}};t[s][0].call(f.exports,function(e){var r=t[s][1][e];return o(r?r:e)},f,f.exports,e,t,r,n)}return r[s].exports}for(var i="function"==typeof require&&require,s=0;s<n.length;s++)o(n[s]);return o}({"./lib/deps/migrate":[function(e,t,r){(function(e){"use strict";r.toSublevel=function(t,r,n){e.nextTick(function(){n()})},r.localAndMetaStores=function(t,r,n){e.nextTick(function(){n()})}}).call(this,e("_process"))},{_process:24}],1:[function(e,t){(function(r,n){"use strict";function o(e,t){return h.Promise.all(e.map(function(e){if(e.doc&&e.doc._attachments){var r=Object.keys(e.doc._attachments);return h.Promise.all(r.map(function(r){var n=e.doc._attachments[r];if(!("data"in n))return new h.Promise(function(o,i){t.binaryStore.get(n.digest,function(t,s){var a="";return t&&"NotFoundError"!==t.name?i(t):(t||(a=h.btoa(s)),e.doc._attachments[r]=h.extend(h.pick(n,["digest","content_type"]),{data:a}),void o())})})}))}}))}function i(e){var t=h.filterChange(e),r=e.doc_ids&&new h.Set(e.doc_ids);return function(e){return r&&!r.has(e.id)?!1:t(e)}}function s(e,t){function v(){q.docStore=U.sublevel(g,{valueEncoding:R}),q.bySeqStore=U.sublevel(m,{valueEncoding:"json"}),q.attachmentStore=U.sublevel(b,{valueEncoding:"json"}),q.binaryStore=U.sublevel(_,{valueEncoding:"binary"}),q.localStore=U.sublevel(w,{valueEncoding:"json"}),q.metaStore=U.sublevel(E,{valueEncoding:"json"}),p.localAndMetaStores(U,q,function(){q.metaStore.get(S,function(e,n){"undefined"==typeof U._updateSeq&&(U._updateSeq=n||0),q.metaStore.get(A,function(e,n){U._docCountQueue.docCount=e?0:n,I(function(e){e&&M.emit("error",e),q.metaStore.get(j,function(e,n){P=e?h.uuid():n,q.metaStore.put(j,P,function(){r.nextTick(function(){t(null,M)})})})})})})})}function I(e){return U._docCountQueue.running||!U._docCountQueue.queue.length||-1===U._docCountQueue.docCount?T(0,e):U._docCountQueue.docCount}function N(){if(!U._docCountQueue.running&&U._docCountQueue.queue.length&&-1!==U._docCountQueue.docCount){U._docCountQueue.running=!0;var e=U._docCountQueue.queue.shift();return U.isClosed()?e.callback(new Error("database is closed")):void q.metaStore.get(A,function(t,r){function n(t){U._docCountQueue.docCount=r,e.callback(t,r),U._docCountQueue.running=!1,N()}r=t?0:r,0===e.delta?n():q.metaStore.put(A,r+e.delta,n)})}}function T(e,t){U._docCountQueue.queue.push({delta:e,callback:t}),N()}function L(e){return h.getArguments(function(t){var n=t[t.length-1];t[t.length-1]=h.getArguments(function(e){n.apply(null,e),r.nextTick(function(){U._writeQueue.shift(),U._writeQueue.length&&U._writeQueue.peekFront()()})}),U._writeQueue.push(function(){e.apply(null,t)}),1===U._writeQueue.length&&U._writeQueue.peekFront()()})}function D(e){return("0000000000000000"+e).slice(-16)}function B(e){return parseInt(e,10)}function C(e,t){var r=e.data;if(r._id=e.metadata.id,"_rev"in r){if(r._rev!==e.metadata.rev)return t(new Error("wrong doc returned"))}else r._rev=e.metadata.rev;t(null,{doc:r,metadata:e.metadata})}e=h.clone(e);var P,U,M=this,q={},F=e.name;"undefined"==typeof e.createIfMissing&&(e.createIfMissing=!0);var V=e.db||u;"function"!=typeof V.destroy&&(V.destroy=function(e,t){t()});var W;k.has(V.name)?W=k.get(V.name):(W=new h.Map,k.set(V.name,W)),W.has(F)?(U=W.get(F),v()):W.set(F,c(a(F,e,function(r){return r?(W["delete"](F),t(r)):(U=W.get(F),U._docCountQueue={queue:[],running:!1,docCount:-1},U._writeQueue=new y,void(e.db||e.noMigrate?v():p.toSublevel(F,U,v)))}))),M.type=function(){return"leveldb"},M._id=function(e){e(null,P)},M._info=function(e){I(function(t,r){return t?e(t):void q.metaStore.get(S,function(t,n){return t&&(n=U._updateSeq),e(null,{doc_count:r,update_seq:n})})})},M._get=function(e,t,r){function n(e){o.push(e)}t=h.clone(t);var o=[];U.on("pouchdb-id-"+e,n),q.docStore.get(e,function(i,s){function a(e){u=e}if(U.removeListener("pouchdb-id-"+e,n),i||!s)return r(l.MISSING_DOC);if(h.isDeleted(s)&&!t.rev)return r(l.error(l.MISSING_DOC,"deleted"));var u,c=d.winningRev(s);c=t.rev?t.rev:c;var f=s.rev_map[c],p=o.filter(function(e){return e.metadata.seq===f});return p.length?C(p.pop(),r):(U.on("pouchdb-"+f,a),void q.bySeqStore.get(D(f),function(e,t){if(U.removeListener("pouchdb-"+f,a),u)return C(u,r);if(!t)return r(l.MISSING_DOC);if("_id"in t&&t._id!==s.id)return r(new Error("wrong doc returned"));if(t._id=s.id,"_rev"in t){if(t._rev!==c)return r(new Error("wrong doc returned"))}else t._rev=c;return r(null,{doc:t,metadata:s})}))})},M._getAttachment=function(e,t,o){var i=e.digest;q.binaryStore.get(i,function(i,s){var a;return i&&"NotFoundError"===i.name?(a=t.encode?"":r.browser?h.createBlob([""],{type:e.content_type}):new n(""),o(null,a)):i?o(i):(a=r.browser?t.encode?h.btoa(s):h.createBlob([h.fixBinary(s)],{type:e.content_type}):t.encode?h.btoa(s):s,void o(null,a))})},M._bulkDocs=L(function(e,t,n){function o(e,t){q.attachmentStore.get(e,function(r){if(r){var n=new Error("unknown stub attachment with digest "+e);n.status=412,t(n)}else t()})}function i(e){function t(){++i===r.length&&e(n)}var r=[];if(_.forEach(function(e){e&&e._attachments&&Object.keys(e._attachments).forEach(function(t){var n=e._attachments[t];n.stub&&r.push(n.digest)})}),!r.length)return e();var n,i=0;r.forEach(function(e){o(e,function(e){e&&!n&&(n=e),t()})})}function a(){var e=E;if(!(A>x)){if(e>=w.length)return 0===A?y():void 0;var t=w[e];if(E++,A++,t._id&&h.isLocalId(t._id))return void M[t._deleted?"_removeLocalNoLock":"_putLocalNoLock"](t,function(t){m[e]=t?t:{},A--,a()});if(b.has(t.metadata.id))return m[e]=l.REV_CONFLICT,A--,a();b.add(t.metadata.id),q.docStore.get(t.metadata.id,function(r,n){r?"NotFoundError"===r.name?u(t,e,function(){b["delete"](t.metadata.id),A--,a()}):(r.error=!0,m[e]=r,b["delete"](t.metadata.id),A--,a()):c(n,t,e,function(){b["delete"](t.metadata.id),A--,a()})}),g&&a()}}function u(e,r,n){return"was_delete"in t&&h.isDeleted(e.metadata)?(m[r]=l.MISSING_DOC,n()):void f(e,r,function(t){return t?n(t):h.isDeleted(e.metadata)?n():void T(1,n)})}function c(e,t,r,n){if(h.revExists(e,t.metadata.rev))return m[r]=t,void n();var o=h.isDeleted(e),i=h.isDeleted(t.metadata),s=/^1-/.test(t.metadata.rev);if(o&&!i&&g&&s){var a=t.data;a._rev=e.rev,a._id=t.metadata.id,t=h.parseDoc(a,g)}var u=d.merge(e.rev_tree,t.metadata.rev_tree[0],1e3),c=g&&(o&&i||!o&&g&&"new_leaf"!==u.conflicts||o&&!i&&"new_branch"===u.conflicts);if(c)return m[r]=l.REV_CONFLICT,n();var p=t.metadata.rev;t.metadata.rev_tree=u.tree,t.metadata.rev_map=e.rev_map;var v=0;(g||d.winningRev(t.metadata)===p)&&(v=o===i?0:i>o?-1:1),T(v,function(e){return e?n(e):void f(t,r,n)})}function f(e,t,o){function i(e){f||(e?(f=e,o(f)):d===y.length&&c())}function s(e){d++,i(e)}function a(e,t,r,n){return function(o){v(e,O+o,t,r,n)}}function u(e,t,r){return function(n){h.MD5(n).then(a(e,t,n,r))}}function c(){var r=e.metadata.rev_map[e.metadata.rev];r||(r=++U._updateSeq),e.metadata.rev_map[e.metadata.rev]=e.metadata.seq=r;var n=D(r);U.emit("pouchdb-id-"+e.metadata.id,e),U.emit("pouchdb-"+n,e),U.batch([{key:n,value:e.data,prefix:q.bySeqStore,type:"put",valueEncoding:"json"},{key:e.metadata.id,value:e.metadata,prefix:q.docStore,type:"put",valueEncoding:R}],function(r){return r||(U.emit("pouchdb-id-"+e.metadata.id,e),U.emit("pouchdb-"+n,e)),q.metaStore.put(S,U._updateSeq,function(r){return m[t]=r?r:e,o()})})}var f=null,d=0;e.data._id=e.metadata.id,e.data._rev=e.metadata.rev,h.isDeleted(e.metadata)&&(e.data._deleted=!0);for(var y=e.data._attachments?Object.keys(e.data._attachments):[],g=0;g<y.length;g++){var b=y[g],_=e.data._attachments[b];if(_.stub){var w=e.data._id,E=e.data._rev;p(w,E,_.digest,s)}else{var x;if("string"==typeof _.data)try{x=h.atob(_.data)}catch(k){return void n(h.extend({},l.BAD_ARG,{reason:"Attachments need to be base64 encoded"}))}else{if(r.browser){h.readAsBinaryString(_.data,u(e,b,s));continue}x=_.data}h.MD5(x).then(a(e,b,x,s))}}y.length||c()}function p(e,t,r,n){function o(){return new h.Promise(function(e,t){q.attachmentStore.get(r,function(r,n){return r&&"NotFoundError"!==r.name?t(r):void e(n)})})}function i(n){var o=[e,t].join("@"),i={};return n?n.refs&&(i.refs=n.refs,i.refs[o]=!0):(i.refs={},i.refs[o]=!0),new h.Promise(function(e,t){q.attachmentStore.put(r,i,function(r){return r?t(r):void e(!n)})})}var s=j[r]||h.Promise.resolve();j[r]=s.then(function(){return o().then(i).then(function(e){n(null,e)},n)})}function v(e,t,r,n,o){var i=e.data._attachments[r];delete i.data,i.digest=t,i.length=n.length;var s=e.metadata.id,a=e.metadata.rev;p(s,a,t,function(e,r){return e?o(e):0===n.length?o(e):r?void q.binaryStore.put(t,n,function(e){o(e)}):o(e)})}function y(){var e=m.map(function(e){if(!Object.keys(e).length)return{ok:!0};if(e.error)return e;var t=e.metadata,r=d.winningRev(t);return{ok:!0,id:t.id,rev:r}});s.Changes.notify(F),r.nextTick(function(){n(null,e)})}var g=t.new_edits,m=new Array(e.docs.length),b=new h.Set,_=e.docs,w=_.map(function(e){if(e._id&&h.isLocalId(e._id))return e;var t=h.parseDoc(e,g);return t.metadata&&!t.metadata.rev_map&&(t.metadata.rev_map={}),t}),E=0,k=w.filter(function(e){return e.error});if(k.length)return n(k[0]);var A=0,j={};i(function(e){return e?n(e):void a()})}),M._allDocs=function(e,t){e=h.clone(e),I(function(r,n){if(r)return t(r);var i={},s=e.skip||0;if(e.startkey&&(i.start=e.startkey),e.endkey&&(i.end=e.endkey),e.key&&(i.start=i.end=e.key),e.descending){i.reverse=!0;var a=i.start;i.start=i.end,i.end=a}var u;if(u="number"==typeof e.limit?e.limit:-1,0===u||"start"in i&&"end"in i&&i.start>i.end)return t(null,{total_rows:n,offset:e.skip,rows:[]});var c=[],l=q.docStore.readStream(i),p=f(function(t,r,n){function o(t,r){var o={id:t.id,key:t.id,value:{rev:d.winningRev(t)}};if(e.include_docs){o.doc=r,o.doc._rev=o.value.rev,e.conflicts&&(o.doc._conflicts=d.collectConflicts(t));for(var i in o.doc._attachments)o.doc._attachments.hasOwnProperty(i)&&(o.doc._attachments[i].stub=!0)}if(e.inclusive_end===!1&&t.id===e.endkey)return n();if(h.isDeleted(t)){if("ok"!==e.deleted)return n();o.value.deleted=!0,o.doc=null}c.push(o),n()}if(h.isDeleted(t.value)){if("ok"!==e.deleted)return void n()}else{if(s-->0)return void n();if(0===u--)return l.unpipe(),l.destroy(),void n()}var i=t.value;if(e.include_docs){var a=i.rev_map[d.winningRev(i)];q.bySeqStore.get(D(a),function(e,t){o(i,t)})}else o(i)},function(r){h.Promise.resolve().then(function(){return e.attachments&&o(c,q)}).then(function(){t(null,{total_rows:n,offset:e.skip,rows:c})},t),r()}).on("unpipe",function(){p.end()});l.on("error",t),l.pipe(p)})},M._changes=function(e){function t(){e.done=!0,v&&e.limit&&e.limit<u.length&&(u.length=e.limit),g.unpipe(m),g.destroy(),e.continuous||e.cancelled||h.Promise.resolve().then(function(){return e.include_docs&&e.attachments?o(u,q):void 0}).then(function(){e.complete(null,{results:u,last_seq:c})})}if(e=h.clone(e),e.continuous){var r=F+":"+h.uuid();return s.Changes.addListener(F,r,M,e),s.Changes.notify(F),{cancel:function(){s.Changes.removeListener(F,r)}}}var n,a=e.descending,u=[],c=0,l=0,p={reverse:a};"limit"in e&&e.limit>0&&(n=e.limit),p.reverse||(p.start=D(e.since?e.since+1:0));var v,y=i(e);v="returnDocs"in e?e.returnDocs:!0;var g=q.bySeqStore.readStream(p),m=f(function(r,i,s){return n&&l>=n?(t(),s()):e.cancelled||e.done?s():void q.docStore.get(r.value._id,function(t,n){if(e.cancelled||e.done||U.isClosed()||h.isLocalId(n.id))return s();var i=r.value;i._rev=d.winningRev(n);var a=e.processChange(i,n,e);a.seq=n.seq,c<n.seq&&(c=n.seq),B(r.key)===n.rev_map[a.doc._rev]&&y(a)&&(l++,e.attachments&&e.include_docs?o([a],q).then(function(){e.onChange(a)}):e.onChange(a),v&&u.push(a)),s()})},function(t){return e.cancelled?t():(v&&e.limit&&e.limit<u.length&&(u.length=e.limit),void t())}).on("unpipe",function(){m.end(),t()});return g.pipe(m),{cancel:function(){e.cancelled=!0,t()}}},M._close=function(e){return U.isClosed()?e(l.NOT_OPEN):void U.close(function(t){t?e(t):(W["delete"](F),e())})},M._getRevisionTree=function(e,t){q.docStore.get(e,function(e,r){e?t(l.MISSING_DOC):t(null,r.rev_tree)})},M._doCompaction=L(function(e,t,r){return t.length?void q.docStore.get(e,function(n,o){function i(e){if(e&&(f=e),++p===t.length){if(f)return r(e);a()}}function s(e){return e?r(e):void U.batch(c,r)}function a(){function r(e){e&&(o=e),++i===n.length&&s(o)}var n=Object.keys(l);if(!n.length)return s();var o,i=0,a=new h.Map;t.forEach(function(t){a.set(e+"@"+t,!0)}),n.forEach(function(e){q.attachmentStore.get(e,function(t,n){if(t)return"NotFoundError"===t.name?r():r(t);var o=Object.keys(n.refs||{}).filter(function(e){return!a.has(e)}),i={};o.forEach(function(e){i[e]=!0}),o.length?c.push({key:e,type:"put",valueEncoding:"json",value:{refs:i},prefix:q.attachmentStore}):c=c.concat([{key:e,type:"del",prefix:q.attachmentStore},{key:e,type:"del",prefix:q.binaryStore}]),r()})})}if(n)return r(n);var u=o.rev_map;d.traverseRevTree(o.rev_tree,function(e,r,n,o,i){var s=r+"-"+n;-1!==t.indexOf(s)&&(i.status="missing")});var c=[];c.push({key:o.id,value:o,type:"put",valueEncoding:R,prefix:q.docStore});var f,l={},p=0;t.forEach(function(e){var t=u[e];t&&(c.push({key:D(t),type:"del",prefix:q.bySeqStore}),q.bySeqStore.get(D(t),function(e,t){if(e)return"NotFoundError"===e.name?i():i(e);var r=Object.keys(t._attachments||{});r.forEach(function(e){var r=t._attachments[e].digest;l[r]=!0}),i()}))})}):r()}),M._getLocal=function(e,t){q.localStore.get(e,function(e,r){e?t(l.MISSING_DOC):t(null,r)})},M._putLocal=L(function(e,t){M._putLocalNoLock(e,t)}),M._putLocalNoLock=function(e,t){delete e._revisions;var r=e._rev,n=e._id;q.localStore.get(n,function(o,i){return o&&r?t(l.REV_CONFLICT):i&&i._rev!==r?t(l.REV_CONFLICT):(e._rev=r?"0-"+(parseInt(r.split("-")[1],10)+1):"0-1",void q.localStore.put(n,e,function(r){if(r)return t(r);var n={ok:!0,id:e._id,rev:e._rev};t(null,n)}))})},M._removeLocal=L(function(e,t){M._removeLocalNoLock(e,t)}),M._removeLocalNoLock=function(e,t){q.localStore.get(e._id,function(r,n){return r?t(r):n._rev!==e._rev?t(l.REV_CONFLICT):void q.localStore.del(e._id,function(r){if(r)return t(r);var n={ok:!0,id:e._id,rev:"0-0"};t(null,n)})})}}var a=e("levelup"),u=e("leveldown"),c=e("level-sublevel"),f=e("through2").obj,l=e("../deps/errors"),d=e("../merge"),h=e("../utils"),p=e("../deps/migrate"),v=e("vuvuzela"),y=e("double-ended-queue"),g="document-store",m="by-sequence",b="attach-store",_="attach-binary-store",w="local-store",E="meta-store",x=50,k=new h.Map,S="_local_last_update_seq",A="_local_doc_count",j="_local_uuid",O="md5-",R={encode:v.stringify,decode:v.parse,buffer:!1,type:"cheap-json"};s.valid=function(){return r&&!r.browser},s.destroy=h.toPromise(function(e,t,n){function o(e,t){"function"==typeof a.destroy?a.destroy(e,t):r.nextTick(n)}t=h.clone(t);var i,a=t.db||u;return k.has(a.name)?(i=k.get(a.name),void(i.has(e)?(s.Changes.removeAllListeners(e),i.get(e).close(function(){i["delete"](e),o(e,n)})):o(e,n))):o(e,n)}),s.use_prefix=!1,s.Changes=new h.Changes,t.exports=s}).call(this,e("_process"),e("buffer").Buffer)},{"../deps/errors":5,"../deps/migrate":7,"../merge":10,"../utils":13,_process:24,buffer:17,"double-ended-queue":43,"level-sublevel":61,leveldown:"leveldown",levelup:75,through2:132,vuvuzela:133}],2:[function(e,t){"use strict";function r(e,t){function r(t,r,n){if(e.binary||e.json||!e.processData||"string"==typeof t){if(!e.binary&&e.json&&"string"==typeof t)try{t=JSON.parse(t)}catch(o){return n(o)}}else t=JSON.stringify(t);Array.isArray(t)&&(t=t.map(function(e){var t;return e.ok?e:e.error&&"conflict"===e.error?(t=i.REV_CONFLICT,t.id=e.id,t):e.error&&"forbidden"===e.error?(t=i.FORBIDDEN,t.id=e.id,t.reason=e.reason,t):e.missing?(t=i.MISSING_DOC,t.missing=e.missing,t):e})),n(null,t,r)}function a(e,t){var r,n,o,s;try{r=JSON.parse(e.responseText);for(s in i)if(i.hasOwnProperty(s)&&i[s].name===r.error){o=i[s];break}o||(o=i.UNKNOWN_ERROR,e.status&&(o.status=e.status),e.statusText&&(e.name=e.statusText)),n=i.error(o,r.reason)}catch(a){for(var s in i)if(i.hasOwnProperty(s)&&i[s].status===e.status){o=i[s];break}o||(o=i.UNKNOWN_ERROR,e.status&&(o.status=e.status),e.statusText&&(e.name=e.statusText)),n=i.error(o)}e.withCredentials&&0===e.status&&(n.status=405,n.statusText="Method Not Allowed"),t(n)}var u=!1,c=s.getArguments(function(e){u||(t.apply(this,e),u=!0)});"function"==typeof e&&(c=e,e={}),e=s.clone(e);var f={method:"GET",headers:{},json:!0,processData:!0,timeout:1e4,cache:!1};if(e=s.extend(!0,f,e),"GET"===e.method&&!e.cache){var l=-1!==e.url.indexOf("?");e.url+=(l?"&":"?")+"_nonce="+s.uuid(16)}var d,h;h=e.xhr?new e.xhr:new XMLHttpRequest,h.open(e.method,e.url),h.withCredentials=!0,e.json&&(e.headers.Accept="application/json",e.headers["Content-Type"]=e.headers["Content-Type"]||"application/json",e.body&&e.processData&&"string"!=typeof e.body&&(e.body=JSON.stringify(e.body))),e.binary&&(h.responseType="arraybuffer");var p=function(e,t,r){var n="";if(r){var o=new Date;o.setTime(o.getTime()+24*r*60*60*1e3),n="; expires="+o.toGMTString()}document.cookie=e+"="+t+n+"; path=/"};for(var v in e.headers)if("Cookie"===v){var y=e.headers[v].split("=");p(y[0],y[1],10)}else h.setRequestHeader(v,e.headers[v]);"body"in e||(e.body=null);var g=function(){u||(h.abort(),a(h,c))};return h.onreadystatechange=function(){if(4===h.readyState&&!u)if(clearTimeout(d),h.status>=200&&h.status<300){var t;t=e.binary?o([h.response||""],{type:h.getResponseHeader("Content-Type")}):h.responseText,r(t,h,c)}else a(h,c)},e.timeout>0&&(d=setTimeout(g,e.timeout),h.onprogress=function(){clearTimeout(d),d=setTimeout(g,e.timeout)},"undefined"==typeof n&&(n=-1!==Object.keys(h).indexOf("upload")),n&&(h.upload.onprogress=h.onprogress)),e.body&&e.body instanceof Blob?s.readAsBinaryString(e.body,function(e){h.send(s.fixBinary(e))}):h.send(e.body),{abort:g}}var n,o=e("./blob.js"),i=e("./errors"),s=e("../utils");t.exports=r},{"../utils":13,"./blob.js":3,"./errors":5}],3:[function(e,t){(function(e){"use strict";function r(t,r){t=t||[],r=r||{};try{return new Blob(t,r)}catch(n){if("TypeError"!==n.name)throw n;for(var o=e.BlobBuilder||e.MSBlobBuilder||e.MozBlobBuilder||e.WebKitBlobBuilder,i=new o,s=0;s<t.length;s+=1)i.append(t[s]);return i.getBlob(r.type)}}t.exports=r}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],4:[function(e,t,r){"use strict";function n(){this.store={}}function o(e){if(this.store=new n,e&&Array.isArray(e))for(var t=0,r=e.length;r>t;t++)this.add(e[t])}r.Map=n,r.Set=o,n.prototype.mangle=function(e){if("string"!=typeof e)throw new TypeError("key must be a string but Got "+e);return"$"+e},n.prototype.unmangle=function(e){return e.substring(1)},n.prototype.get=function(e){var t=this.mangle(e);return t in this.store?this.store[t]:void 0},n.prototype.set=function(e,t){var r=this.mangle(e);return this.store[r]=t,!0},n.prototype.has=function(e){var t=this.mangle(e);return t in this.store},n.prototype["delete"]=function(e){var t=this.mangle(e);return t in this.store?(delete this.store[t],!0):!1},n.prototype.forEach=function(e){var t=this,r=Object.keys(t.store);r.forEach(function(r){var n=t.store[r];r=t.unmangle(r),e(n,r)})},o.prototype.add=function(e){return this.store.set(e,!0)},o.prototype.has=function(e){return this.store.has(e)},o.prototype["delete"]=function(e){return this.store["delete"](e)}},{}],5:[function(e,t,r){"use strict";function n(e){this.status=e.status,this.name=e.error,this.message=e.reason,this.error=!0}n.prototype__proto__=Error.prototype,n.prototype.toString=function(){return JSON.stringify({status:this.status,name:this.name,message:this.message})},r.UNAUTHORIZED=new n({status:401,error:"unauthorized",reason:"Name or password is incorrect."}),r.MISSING_BULK_DOCS=new n({status:400,error:"bad_request",reason:"Missing JSON list of 'docs'"}),r.MISSING_DOC=new n({status:404,error:"not_found",reason:"missing"}),r.REV_CONFLICT=new n({status:409,error:"conflict",reason:"Document update conflict"}),r.INVALID_ID=new n({status:400,error:"invalid_id",reason:"_id field must contain a string"}),r.MISSING_ID=new n({status:412,error:"missing_id",reason:"_id is required for puts"}),r.RESERVED_ID=new n({status:400,error:"bad_request",reason:"Only reserved document ids may start with underscore."}),r.NOT_OPEN=new n({status:412,error:"precondition_failed",reason:"Database not open"}),r.UNKNOWN_ERROR=new n({status:500,error:"unknown_error",reason:"Database encountered an unknown error"}),r.BAD_ARG=new n({status:500,error:"badarg",reason:"Some query argument is invalid"}),r.INVALID_REQUEST=new n({status:400,error:"invalid_request",reason:"Request was invalid"}),r.QUERY_PARSE_ERROR=new n({status:400,error:"query_parse_error",reason:"Some query parameter is invalid"}),r.DOC_VALIDATION=new n({status:500,error:"doc_validation",reason:"Bad special document member"}),r.BAD_REQUEST=new n({status:400,error:"bad_request",reason:"Something wrong with the request"}),r.NOT_AN_OBJECT=new n({status:400,error:"bad_request",reason:"Document must be a JSON object"}),r.DB_MISSING=new n({status:404,error:"not_found",reason:"Database not found"}),r.IDB_ERROR=new n({status:500,error:"indexed_db_went_bad",reason:"unknown"}),r.WSQ_ERROR=new n({status:500,error:"web_sql_went_bad",reason:"unknown"}),r.LDB_ERROR=new n({status:500,error:"levelDB_went_went_bad",reason:"unknown"}),r.FORBIDDEN=new n({status:403,error:"forbidden",reason:"Forbidden by design doc validate_doc_update function"}),r.error=function(e,t,r){function n(){this.message=t,r&&(this.name=r)}return n.prototype=e,new n(t)}},{}],6:[function(e,t){(function(r,n){"use strict";function o(e,t,r){if("function"==typeof e.slice)return t?r?e.slice(t,r):e.slice(t):e.slice();t=Math.floor(t||0),r=Math.floor(r||0);var n=e.byteLength;if(t=0>t?Math.max(t+n,0):Math.min(n,t),r=0>r?Math.max(r+n,0):Math.min(n,r),0>=r-t)return new ArrayBuffer(0);var o=new ArrayBuffer(r-t),i=new Uint8Array(o),s=new Uint8Array(e,t,r-t);return i.set(s),o}function i(e){var t=[255&e,e>>>8&255,e>>>16&255,e>>>24&255];return t.map(function(e){return String.fromCharCode(e)}).join("")}function s(e){for(var t="",r=0;r<e.length;r++)t+=i(e[r]);return n.btoa(t)}var a=e("crypto"),u=e("spark-md5"),c=n.setImmediate||n.setTimeout,f=32768;t.exports=function(e,t){function n(e,t,r,n){d?e.appendBinary(t.substring(r,n)):e.append(o(t,r,n))}function i(){var r=y*p,o=r+p;if(r+p>=e.size&&(o=e.size),y++,v>y)n(g,e,r,o),c(i);else{n(g,e,r,o);var a=g.end(!0),u=s(a);t(null,u),g.destroy()}}if(!r.browser){var l=a.createHash("md5").update(e).digest("base64");return void t(null,l)}var d="string"==typeof e,h=d?e.length:e.byteLength,p=Math.min(f,h),v=Math.ceil(h/p),y=0,g=d?new u:new u.ArrayBuffer;i()}}).call(this,e("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{_process:24,crypto:16,"spark-md5":117}],7:[function(e,t,r){"use strict";function n(e){return("0000000000000000"+e).slice(-16)}var o=e("fs"),i=e("path"),s=e("../utils"),a=e("../merge"),u=e("levelup"),c=e("through2").obj,f=e("leveldown"),l=["document-store","by-sequence","attach-store","attach-binary-store"],d="_local_last_update_seq",h="_local_doc_count",p="_local_uuid";r.toSublevel=function(e,t,r){function n(e,r,n){var o,a=i.join(s,e);o=3===r?{valueEncoding:"binary"}:{valueEncoding:"json"};var c=t.sublevel(e,o),f=u(a,o),l=f.createReadStream(),d=c.createWriteStream();l.on("end",function(){f.close(function(e){n(e,a)})}),l.pipe(d)}var s=i.resolve(e);o.unlink(s+".uuid",function(e){if(e)return r();var t=4,i=[];l.forEach(function(e,a){n(e,a,function(e,n){return e?r(e):(i.push(n),void(--t||i.forEach(function(e){f.destroy(e,function(){++t===i.length&&o.rmdir(s,r)})})))})})})},r.localAndMetaStores=function(e,t,r){var o=[];t.bySeqStore.get(p,function(i,u){return i?r():(o.push({key:p,value:u,prefix:t.metaStore,type:"put",valueEncoding:"json"}),o.push({key:p,prefix:t.bySeqStore,type:"del"}),void t.bySeqStore.get(h,function(i,u){u&&(o.push({key:h,value:u,prefix:t.metaStore,type:"put",valueEncoding:"json"}),o.push({key:h,prefix:t.bySeqStore,type:"del"})),t.bySeqStore.get(d,function(i,u){u&&(o.push({key:d,value:u,prefix:t.metaStore,type:"put",valueEncoding:"json"}),o.push({key:d,prefix:t.bySeqStore,type:"del"}));var f={};t.docStore.createReadStream({startKey:"_",endKey:"_ÿ"}).pipe(c(function(e,r,i){if(!s.isLocalId(e.key))return i();o.push({key:e.key,prefix:t.docStore,type:"del"});var u=a.winningRev(e.value);Object.keys(e.value.rev_map).forEach(function(t){"winner"!==t&&this.push(n(e.value.rev_map[t]))},this);var c=e.value.rev_map[u];t.bySeqStore.get(n(c),function(r,n){r||o.push({key:e.key,value:n,prefix:t.localStore,type:"put",valueEncoding:"json"}),i()})})).pipe(c(function(e,r,n){return f[e]?n():(f[e]=!0,void t.bySeqStore.get(e,function(r,i){return r||!s.isLocalId(i._id)?n():(o.push({key:e,prefix:t.bySeqStore,type:"del"}),void n())}))},function(){e.batch(o,r)}))})}))})}},{"../merge":10,"../utils":13,fs:15,leveldown:"leveldown",levelup:75,path:23,through2:132}],8:[function(e,t){"use strict";function r(e){for(var t=n,r=t.parser[t.strictMode?"strict":"loose"].exec(e),o={},i=14;i--;){var s=t.key[i],a=r[i]||"",u=-1!==["user","password"].indexOf(s);o[s]=u?decodeURIComponent(a):a}return o[t.q.name]={},o[t.key[12]].replace(t.q.parser,function(e,r,n){r&&(o[t.q.name][r]=n)}),o}var n={strictMode:!1,key:["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],q:{name:"queryKey",parser:/(?:^|&)([^&=]*)=?([^&]*)/g},parser:{strict:/^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,loose:/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/}};t.exports=r},{}],9:[function(e,t){"use strict";function r(e){return 0|Math.random()*e}function n(e,t){t=t||o.length;var n="",i=-1;if(e){for(;++i<e;)n+=o[r(t)];return n}for(;++i<36;)switch(i){case 8:case 13:case 18:case 23:n+="-";break;case 19:n+=o[3&r(16)|8];break;default:n+=o[r(16)]}return n}var o="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split("");t.exports=n},{}],10:[function(e,t){"use strict";function r(e){for(var t,r=e.shift(),n=[r.id,r.opts,[]],o=n;e.length;)r=e.shift(),t=[r.id,r.opts,[]],o[2].push(t),o=t;return n}function n(e,t){for(var r=[{tree1:e,tree2:t}],n=!1;r.length>0;){var o=r.pop(),i=o.tree1,s=o.tree2;(i[1].status||s[1].status)&&(i[1].status="available"===i[1].status||"available"===s[1].status?"available":"missing");for(var a=0;a<s[2].length;a++)if(i[2][0]){for(var u=!1,c=0;c<i[2].length;c++)i[2][c][0]===s[2][a][0]&&(r.push({tree1:i[2][c],tree2:s[2][a]}),u=!0);u||(n="new_branch",i[2].push(s[2][a]),i[2].sort())}else n="new_leaf",i[2][0]=s[2][a]}return{conflicts:n,tree:e}}function o(e,t,r){var o,i=[],s=!1,a=!1;return e.length?(e.forEach(function(e){if(e.pos===t.pos&&e.ids[0]===t.ids[0])o=n(e.ids,t.ids),i.push({pos:e.pos,ids:o.tree}),s=s||o.conflicts,a=!0;else if(r!==!0){var u=e.pos<t.pos?e:t,c=e.pos<t.pos?t:e,f=c.pos-u.pos,l=[],d=[];for(d.push({ids:u.ids,diff:f,parent:null,parentIdx:null});d.length>0;){var h=d.pop();0!==h.diff?h.ids&&h.ids[2].forEach(function(e,t){d.push({ids:e,diff:h.diff-1,parent:h.ids,parentIdx:t})}):h.ids[0]===c.ids[0]&&l.push(h)}var p=l[0];p?(o=n(p.ids,c.ids),p.parent[2][p.parentIdx]=o.tree,i.push({pos:u.pos,ids:u.ids}),s=s||o.conflicts,a=!0):i.push(e)}else i.push(e)}),a||i.push(t),i.sort(function(e,t){return e.pos-t.pos}),{tree:i,conflicts:s||"internal_node"}):{tree:[t],conflicts:"new_leaf"}}function i(e,t){var n=a.rootToLeaf(e).map(function(e){var n=e.ids.slice(-t);return{pos:e.pos+(e.ids.length-n.length),ids:r(n)}});return n.reduce(function(e,t){return o(e,t,!0).tree},[n.shift()])}var s=e("pouchdb-extend"),a={};a.merge=function(e,t,r){e=s(!0,[],e),t=s(!0,{},t);var n=o(e,t);return{tree:i(n.tree,r),conflicts:n.conflicts}},a.winningRev=function(e){var t=[];return a.traverseRevTree(e.rev_tree,function(e,r,n,o,i){e&&t.push({pos:r,id:n,deleted:!!i.deleted})}),t.sort(function(e,t){return e.deleted!==t.deleted?e.deleted>t.deleted?1:-1:e.pos!==t.pos?t.pos-e.pos:e.id<t.id?1:-1}),t[0].pos+"-"+t[0].id},a.traverseRevTree=function(e,t){for(var r,n=e.slice();r=n.pop();)for(var o=r.pos,i=r.ids,s=i[2],a=t(0===s.length,o,i[0],r.ctx,i[1]),u=0,c=s.length;c>u;u++)n.push({pos:o+1,ids:s[u],ctx:a})},a.collectLeaves=function(e){var t=[];return a.traverseRevTree(e,function(e,r,n,o,i){e&&t.unshift({rev:r+"-"+n,pos:r,opts:i})}),t.sort(function(e,t){return t.pos-e.pos}),t.map(function(e){delete e.pos}),t},a.collectConflicts=function(e){var t=a.winningRev(e),r=a.collectLeaves(e.rev_tree),n=[];return r.forEach(function(e){e.rev===t||e.opts.deleted||n.push(e.rev)}),n},a.rootToLeaf=function(e){var t=[];return a.traverseRevTree(e,function(e,r,n,o,i){if(o=o?o.slice(0):[],o.push({id:n,opts:i}),e){var s=r+1-o.length;t.unshift({pos:s,ids:o})}return o}),t},t.exports=a},{"pouchdb-extend":116}],11:[function(e){(function(t){"use strict";var r=e("adapter-config"),n=r.name,o=e("./levelalt")(r),i=t.PouchDB||e("pouchdb");i.adapter(n,o),i.preferredAdapters.push(n)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./levelalt":12,"adapter-config":"adapter-config",pouchdb:"pouchdb"}],12:[function(e,t){"use strict";function r(e){function t(e,t){var r=i.extend({db:o},e);n.call(this,r,t)}return t.valid=function(){return e.valid()},t.use_prefix=e.use_prefix,t.destroy=i.toPromise(function(e,t,r){"function"==typeof t&&(r=t,t={});var s=i.extend({db:o},t);return n.destroy(e,s,r)}),t}var n=e("../adapters/leveldb"),o=e("leveldown"),i=e("../utils");t.exports=r},{"../adapters/leveldb":1,"../utils":13,leveldown:"leveldown"}],13:[function(e,t,r){(function(t,n){function o(e){var t={};return e.forEach(function(e){t[e]=!0}),t}function i(){return"undefined"!=typeof chrome&&"undefined"!=typeof chrome.storage&&"undefined"!=typeof chrome.storage.local}function s(){if(!(this instanceof s))return new s;var e=this;f.call(this),this.isChrome=i(),this.listeners={},this.hasLocal=!1,this.isChrome||(this.hasLocal=r.hasLocalStorage()),this.isChrome?chrome.storage.onChanged.addListener(function(t){null!=t.db_name&&e.emit(t.dbName.newValue)}):this.hasLocal&&(n.addEventListener?n.addEventListener("storage",function(t){e.emit(t.key)}):n.attachEvent("storage",function(t){e.emit(t.key)}))}var a=e("./merge");r.extend=e("pouchdb-extend"),r.ajax=e("./deps/ajax"),r.createBlob=e("./deps/blob"),r.uuid=e("./deps/uuid"),r.getArguments=e("argsarray");var u=e("./deps/buffer"),c=e("./deps/errors"),f=e("events").EventEmitter,l=e("./deps/collections");r.Map=l.Map,r.Set=l.Set,r.Promise="function"==typeof n.Promise?n.Promise:e("bluebird");var d=r.Promise,h=o(["_id","_rev","_attachments","_deleted","_revisions","_revs_info","_conflicts","_deleted_conflicts","_local_seq","_rev_tree","_replication_id","_replication_state","_replication_state_time","_replication_state_reason","_replication_stats"]),p=o(["_attachments","_replication_id","_replication_state","_replication_state_time","_replication_state_reason","_replication_stats"]);r.lastIndexOf=function(e,t){for(var r=e.length-1;r>=0;r--)if(e.charAt(r)===t)return r;return-1},r.clone=function(e){return r.extend(!0,{},e)},r.pick=function(e,t){for(var r={},n=0,o=t.length;o>n;n++){var i=t[n];r[i]=e[i]}return r},r.inherits=e("inherits"),r.invalidIdError=function(e){var t;if(e?"string"!=typeof e?(t=new TypeError(c.INVALID_ID.message),t.status=400):/^_/.test(e)&&!/^_(design|local)/.test(e)&&(t=new TypeError(c.RESERVED_ID.message),t.status=400):(t=new TypeError(c.MISSING_ID.message),t.status=412),t)throw t},r.call=r.getArguments(function(e){if(e.length){var t=e.shift();"function"==typeof t&&t.apply(this,e)}}),r.isLocalId=function(e){return/^_local/.test(e)},r.isDeleted=function(e,t){t||(t=a.winningRev(e)); +var r=t.indexOf("-");-1!==r&&(t=t.substring(r+1));var n=!1;return a.traverseRevTree(e.rev_tree,function(e,r,o,i,s){o===t&&(n=!!s.deleted)}),n},r.revExists=function(e,t){var r=!1;return a.traverseRevTree(e.rev_tree,function(e,n,o){n+"-"+o===t&&(r=!0)}),r},r.filterChange=function(e){var t={},r=e.filter&&"function"==typeof e.filter;return t.query=e.query_params,function(n){if(e.filter&&r&&!e.filter.call(this,n.doc,t))return!1;if(e.include_docs){if(!e.attachments)for(var o in n.doc._attachments)n.doc._attachments.hasOwnProperty(o)&&(n.doc._attachments[o].stub=!0)}else delete n.doc;return!0}},r.parseDoc=function(e,t){var n,o,i,s,a={status:"available"};if(e._deleted&&(a.deleted=!0),t)if(e._id||(e._id=r.uuid()),o=r.uuid(32,16).toLowerCase(),e._rev){if(i=/^(\d+)-(.+)$/.exec(e._rev),!i)return s=new Error("bad_request"),s.message="Invalid rev format",s.error=!0,s;e._rev_tree=[{pos:parseInt(i[1],10),ids:[i[2],{status:"missing"},[[o,a,[]]]]}],n=parseInt(i[1],10)+1}else e._rev_tree=[{pos:1,ids:[o,a,[]]}],n=1;else if(e._revisions&&(e._rev_tree=[{pos:e._revisions.start-e._revisions.ids.length+1,ids:e._revisions.ids.reduce(function(e,t){return null===e?[t,a,[]]:[t,{status:"missing"},[e]]},null)}],n=e._revisions.start,o=e._revisions.ids[0]),!e._rev_tree){if(i=/^(\d+)-(.+)$/.exec(e._rev),!i)return s=new Error("bad_request"),s.message="Invalid rev format",s.error=!0,s;n=parseInt(i[1],10),o=i[2],e._rev_tree=[{pos:parseInt(i[1],10),ids:[i[2],a,[]]}]}r.invalidIdError(e._id),e._rev=[n,o].join("-");var u={metadata:{},data:{}};for(var f in e)if(e.hasOwnProperty(f)){var l="_"===f[0];if(l&&!h[f])throw s=new Error(c.DOC_VALIDATION.message+": "+f),s.status=c.DOC_VALIDATION.status,s;l&&!p[f]?u.metadata[f.slice(1)]=e[f]:u.data[f]=e[f]}return u},r.isCordova=function(){return"undefined"!=typeof cordova||"undefined"!=typeof PhoneGap||"undefined"!=typeof phonegap},r.hasLocalStorage=function(){if(i())return!1;try{return n.localStorage}catch(e){return!1}},r.Changes=s,r.inherits(s,f),s.prototype.addListener=function(e,t,n,o){function i(){n.changes({include_docs:o.include_docs,attachments:o.attachments,conflicts:o.conflicts,continuous:!1,descending:!1,filter:o.filter,doc_ids:o.doc_ids,view:o.view,since:o.since,query_params:o.query_params,onChange:function(e){e.seq>o.since&&!o.cancelled&&(o.since=e.seq,r.call(o.onChange,e))}})}this.listeners[t]||(this.listeners[t]=i,this.on(e,i))},s.prototype.removeListener=function(e,t){t in this.listeners&&f.prototype.removeListener.call(this,e,this.listeners[t])},s.prototype.notifyLocalWindows=function(e){this.isChrome?chrome.storage.local.set({dbName:e}):this.hasLocal&&(localStorage[e]="a"===localStorage[e]?"b":"a")},s.prototype.notify=function(e){this.emit(e),this.notifyLocalWindows(e)},r.atob=t.browser&&"atob"in n?function(e){return atob(e)}:function(e){var t=new u(e,"base64");if(t.toString("base64")!==e)throw"Cannot base64 encode full string";return t.toString("binary")},r.btoa=t.browser&&"btoa"in n?function(e){return btoa(e)}:function(e){return new u(e,"binary").toString("base64")},r.fixBinary=function(e){if(!t.browser)return e;for(var r=e.length,n=new ArrayBuffer(r),o=new Uint8Array(n),i=0;r>i;i++)o[i]=e.charCodeAt(i);return n},r.readAsBinaryString=function(e,t){var n=new FileReader,o="function"==typeof n.readAsBinaryString;n.onloadend=function(e){var n=e.target.result||"";return o?t(n):void t(r.arrayBufferToBinaryString(n))},o?n.readAsBinaryString(e):n.readAsArrayBuffer(e)},r.once=function(e){var t=!1;return r.getArguments(function(r){if(t)throw new Error("once called more than once");t=!0,e.apply(this,r)})},r.toPromise=function(e){return r.getArguments(function(n){var o,i=this,s="function"==typeof n[n.length-1]?n.pop():!1;s&&(o=function(e,r){t.nextTick(function(){s(e,r)})});var a=new d(function(t,o){var s;try{var a=r.once(function(e,r){e?o(e):t(r)});n.push(a),s=e.apply(i,n),s&&"function"==typeof s.then&&t(s)}catch(u){o(u)}});return o&&a.then(function(e){o(null,e)},o),a.cancel=function(){return this},a})},r.adapterFun=function(t,n){function o(e,t,r){if(i.enabled){for(var n=[e._db_name,t],o=0;o<r.length-1;o++)n.push(r[o]);i.apply(null,n);var s=r[r.length-1];r[r.length-1]=function(r,n){var o=[e._db_name,t];o=o.concat(r?["error",r]:["success",n]),i.apply(null,o),s(r,n)}}}var i=e("debug")("pouchdb:api");return r.toPromise(r.getArguments(function(e){if(this._closed)return d.reject(new Error("database is closed"));var i=this;return o(i,t,e),this.taskqueue.isReady?n.apply(this,e):new r.Promise(function(r,n){i.taskqueue.addTask(function(o){o?n(o):r(i[t].apply(i,e))})})}))},r.arrayBufferToBinaryString=function(e){for(var t="",r=new Uint8Array(e),n=r.byteLength,o=0;n>o;o++)t+=String.fromCharCode(r[o]);return t},r.cancellableFun=function(e,t,n){n=n?r.clone(!0,{},n):{};var o=new f,i=n.complete||function(){},s=n.complete=r.once(function(e,t){e?i(e):(o.emit("end",t),i(null,t)),o.removeAllListeners()}),a=n.onChange||function(){},u=0;t.on("destroyed",function(){o.removeAllListeners()}),n.onChange=function(e){a(e),e.seq<=u||(u=e.seq,o.emit("change",e),e.deleted?o.emit("delete",e):1===e.changes.length&&"1-"===e.changes[0].rev.slice(0,1)?o.emit("create",e):o.emit("update",e))};var c=new d(function(e,t){n.complete=function(r,n){r?t(r):e(n)}});return c.then(function(e){s(null,e)},s),c.cancel=function(){c.isCancelled=!0,t.taskqueue.isReady&&n.complete(null,{status:"cancelled"})},t.taskqueue.isReady?e(t,n,c):t.taskqueue.addTask(function(){c.isCancelled?n.complete(null,{status:"cancelled"}):e(t,n,c)}),c.on=o.on.bind(o),c.once=o.once.bind(o),c.addListener=o.addListener.bind(o),c.removeListener=o.removeListener.bind(o),c.removeAllListeners=o.removeAllListeners.bind(o),c.setMaxListeners=o.setMaxListeners.bind(o),c.listeners=o.listeners.bind(o),c.emit=o.emit.bind(o),c},r.MD5=r.toPromise(e("./deps/md5")),r.explain404=function(e){t.browser&&"console"in n&&"info"in console&&console.info("The above 404 is totally normal. "+e)},r.parseUri=e("./deps/parse-uri"),r.compare=function(e,t){return t>e?-1:e>t?1:0},r.updateDoc=function(e,t,n,o,i,s,u){if(r.revExists(e,t.metadata.rev))return n[o]=t,i();var f=r.isDeleted(e),l=r.isDeleted(t.metadata),d=/^1-/.test(t.metadata.rev);if(f&&!l&&u&&d){var h=t.data;h._rev=a.winningRev(e),h._id=t.metadata.id,t=r.parseDoc(h,u)}var p=a.merge(e.rev_tree,t.metadata.rev_tree[0],1e3),v=u&&(f&&l||!f&&"new_leaf"!==p.conflicts||f&&!l&&"new_branch"===p.conflicts);if(v){var y=c.REV_CONFLICT;return n[o]=y,i()}t.metadata.rev_tree=p.tree;var g=a.winningRev(t.metadata);l=r.isDeleted(t.metadata,g),s(t,g,l,i,!0,o)},r.processDocs=function(e,t,n,o,i,s,u){function f(e,t,n){var o=a.winningRev(e.metadata),f=r.isDeleted(e.metadata,o);return"was_delete"in u&&f?(i[t]=c.MISSING_DOC,n()):void s(e,o,f,n,!1,t)}if(e.length){var l=u.new_edits,d=new r.Map;e.forEach(function(e,n){if(e._id&&r.isLocalId(e._id))return void t[e._deleted?"_removeLocal":"_putLocal"](e,{ctx:o},function(e){i[n]=e?e:{}});var s=e.metadata.id;d.has(s)?d.get(s).push([e,n]):d.set(s,[[e,n]])}),d.forEach(function(e,t){function o(){++u<e.length&&a()}function a(){var a=e[u],c=a[0],d=a[1];n.has(t)?r.updateDoc(n.get(t),c,i,d,o,s,l):f(c,d,o)}var u=0;a()})}},r.preprocessAttachments=function(e,t,n){function o(e){try{return r.atob(e)}catch(t){var n=c.error(c.BAD_ARG,"Attachments need to be base64 encoded");return{error:n}}}function i(e,n){if(e.stub)return n();if("string"==typeof e.data){var i=o(e.data);if(i.error)return n(i.error);e.length=i.length,e.data="blob"===t?r.createBlob([r.fixBinary(i)],{type:e.content_type}):"base64"===t?r.btoa(i):i,r.MD5(i).then(function(t){e.digest="md5-"+t,n()})}else r.readAsBinaryString(e.data,function(o){"binary"===t?e.data=o:"base64"===t&&(e.data=r.btoa(o)),r.MD5(o).then(function(t){e.digest="md5-"+t,e.length=o.length,n()})})}function s(){u++,e.length===u&&(a?n(a):n())}if(!e.length)return n();var a,u=0;e.forEach(function(e){function t(e){a=e,n++,n===r.length&&s()}var r=e.data&&e.data._attachments?Object.keys(e.data._attachments):[],n=0;if(!r.length)return s();for(var o in e.data._attachments)e.data._attachments.hasOwnProperty(o)&&i(e.data._attachments[o],t)})}}).call(this,e("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./deps/ajax":2,"./deps/blob":3,"./deps/buffer":16,"./deps/collections":4,"./deps/errors":5,"./deps/md5":6,"./deps/parse-uri":8,"./deps/uuid":9,"./merge":10,_process:24,argsarray:14,bluebird:101,debug:40,events:21,inherits:44,"pouchdb-extend":116}],14:[function(e,t){"use strict";function r(e){return function(){var t=arguments.length;if(t){for(var r=[],n=-1;++n<t;)r[n]=arguments[n];return e.call(this,r)}return e.call(this,[])}}t.exports=r},{}],15:[function(){},{}],16:[function(e,t){t.exports=e(15)},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/lib/_empty.js":15}],17:[function(e,t,r){function n(e,t,r){if(!(this instanceof n))return new n(e,t,r);var o,i=typeof e;if("number"===i)o=e>0?e>>>0:0;else if("string"===i)"base64"===t&&(e=x(e)),o=n.byteLength(e,t);else{if("object"!==i||null===e)throw new TypeError("must start with number, buffer, array or string");"Buffer"===e.type&&B(e.data)&&(e=e.data),o=+e.length>0?Math.floor(+e.length):0}if(this.length>C)throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+C.toString(16)+" bytes");var s;n.TYPED_ARRAY_SUPPORT?s=n._augment(new Uint8Array(o)):(s=this,s.length=o,s._isBuffer=!0);var a;if(n.TYPED_ARRAY_SUPPORT&&"number"==typeof e.byteLength)s._set(e);else if(S(e))if(n.isBuffer(e))for(a=0;o>a;a++)s[a]=e.readUInt8(a);else for(a=0;o>a;a++)s[a]=(e[a]%256+256)%256;else if("string"===i)s.write(e,0,t);else if("number"===i&&!n.TYPED_ARRAY_SUPPORT&&!r)for(a=0;o>a;a++)s[a]=0;return s}function o(e,t,r,n){r=Number(r)||0;var o=e.length-r;n?(n=Number(n),n>o&&(n=o)):n=o;var i=t.length;if(i%2!==0)throw new Error("Invalid hex string");n>i/2&&(n=i/2);for(var s=0;n>s;s++){var a=parseInt(t.substr(2*s,2),16);if(isNaN(a))throw new Error("Invalid hex string");e[r+s]=a}return s}function i(e,t,r,n){var o=N(j(t),e,r,n);return o}function s(e,t,r,n){var o=N(O(t),e,r,n);return o}function a(e,t,r,n){return s(e,t,r,n)}function u(e,t,r,n){var o=N(I(t),e,r,n);return o}function c(e,t,r,n){var o=N(R(t),e,r,n);return o}function f(e,t,r){return L.fromByteArray(0===t&&r===e.length?e:e.slice(t,r))}function l(e,t,r){var n="",o="";r=Math.min(e.length,r);for(var i=t;r>i;i++)e[i]<=127?(n+=T(o)+String.fromCharCode(e[i]),o=""):o+="%"+e[i].toString(16);return n+T(o)}function d(e,t,r){var n="";r=Math.min(e.length,r);for(var o=t;r>o;o++)n+=String.fromCharCode(e[o]);return n}function h(e,t,r){return d(e,t,r)}function p(e,t,r){var n=e.length;(!t||0>t)&&(t=0),(!r||0>r||r>n)&&(r=n);for(var o="",i=t;r>i;i++)o+=A(e[i]);return o}function v(e,t,r){for(var n=e.slice(t,r),o="",i=0;i<n.length;i+=2)o+=String.fromCharCode(n[i]+256*n[i+1]);return o}function y(e,t,r){if(e%1!==0||0>e)throw new RangeError("offset is not uint");if(e+t>r)throw new RangeError("Trying to access beyond buffer length")}function g(e,t,r,o,i,s){if(!n.isBuffer(e))throw new TypeError("buffer must be a Buffer instance");if(t>i||s>t)throw new TypeError("value is out of bounds");if(r+o>e.length)throw new TypeError("index out of range")}function m(e,t,r,n){0>t&&(t=65535+t+1);for(var o=0,i=Math.min(e.length-r,2);i>o;o++)e[r+o]=(t&255<<8*(n?o:1-o))>>>8*(n?o:1-o)}function b(e,t,r,n){0>t&&(t=4294967295+t+1);for(var o=0,i=Math.min(e.length-r,4);i>o;o++)e[r+o]=t>>>8*(n?o:3-o)&255}function _(e,t,r,n,o,i){if(t>o||i>t)throw new TypeError("value is out of bounds");if(r+n>e.length)throw new TypeError("index out of range")}function w(e,t,r,n,o){return o||_(e,t,r,4,3.4028234663852886e38,-3.4028234663852886e38),D.write(e,t,r,n,23,4),r+4}function E(e,t,r,n,o){return o||_(e,t,r,8,1.7976931348623157e308,-1.7976931348623157e308),D.write(e,t,r,n,52,8),r+8}function x(e){for(e=k(e).replace(U,"");e.length%4!==0;)e+="=";return e}function k(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}function S(e){return B(e)||n.isBuffer(e)||e&&"object"==typeof e&&"number"==typeof e.length}function A(e){return 16>e?"0"+e.toString(16):e.toString(16)}function j(e){for(var t=[],r=0;r<e.length;r++){var n=e.charCodeAt(r);if(127>=n)t.push(n);else{var o=r;n>=55296&&57343>=n&&r++;for(var i=encodeURIComponent(e.slice(o,r+1)).substr(1).split("%"),s=0;s<i.length;s++)t.push(parseInt(i[s],16))}}return t}function O(e){for(var t=[],r=0;r<e.length;r++)t.push(255&e.charCodeAt(r));return t}function R(e){for(var t,r,n,o=[],i=0;i<e.length;i++)t=e.charCodeAt(i),r=t>>8,n=t%256,o.push(n),o.push(r);return o}function I(e){return L.toByteArray(e)}function N(e,t,r,n){for(var o=0;n>o&&!(o+r>=t.length||o>=e.length);o++)t[o+r]=e[o];return o}function T(e){try{return decodeURIComponent(e)}catch(t){return String.fromCharCode(65533)}}var L=e("base64-js"),D=e("ieee754"),B=e("is-array");r.Buffer=n,r.SlowBuffer=n,r.INSPECT_MAX_BYTES=50,n.poolSize=8192;var C=1073741823;n.TYPED_ARRAY_SUPPORT=function(){try{var e=new ArrayBuffer(0),t=new Uint8Array(e);return t.foo=function(){return 42},42===t.foo()&&"function"==typeof t.subarray&&0===new Uint8Array(1).subarray(1,1).byteLength}catch(r){return!1}}(),n.isBuffer=function(e){return!(null==e||!e._isBuffer)},n.compare=function(e,t){if(!n.isBuffer(e)||!n.isBuffer(t))throw new TypeError("Arguments must be Buffers");for(var r=e.length,o=t.length,i=0,s=Math.min(r,o);s>i&&e[i]===t[i];i++);return i!==s&&(r=e[i],o=t[i]),o>r?-1:r>o?1:0},n.isEncoding=function(e){switch(String(e).toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"raw":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return!0;default:return!1}},n.concat=function(e,t){if(!B(e))throw new TypeError("Usage: Buffer.concat(list[, length])");if(0===e.length)return new n(0);if(1===e.length)return e[0];var r;if(void 0===t)for(t=0,r=0;r<e.length;r++)t+=e[r].length;var o=new n(t),i=0;for(r=0;r<e.length;r++){var s=e[r];s.copy(o,i),i+=s.length}return o},n.byteLength=function(e,t){var r;switch(e+="",t||"utf8"){case"ascii":case"binary":case"raw":r=e.length;break;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":r=2*e.length;break;case"hex":r=e.length>>>1;break;case"utf8":case"utf-8":r=j(e).length;break;case"base64":r=I(e).length;break;default:r=e.length}return r},n.prototype.length=void 0,n.prototype.parent=void 0,n.prototype.toString=function(e,t,r){var n=!1;if(t>>>=0,r=void 0===r||1/0===r?this.length:r>>>0,e||(e="utf8"),0>t&&(t=0),r>this.length&&(r=this.length),t>=r)return"";for(;;)switch(e){case"hex":return p(this,t,r);case"utf8":case"utf-8":return l(this,t,r);case"ascii":return d(this,t,r);case"binary":return h(this,t,r);case"base64":return f(this,t,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return v(this,t,r);default:if(n)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),n=!0}},n.prototype.equals=function(e){if(!n.isBuffer(e))throw new TypeError("Argument must be a Buffer");return 0===n.compare(this,e)},n.prototype.inspect=function(){var e="",t=r.INSPECT_MAX_BYTES;return this.length>0&&(e=this.toString("hex",0,t).match(/.{2}/g).join(" "),this.length>t&&(e+=" ... ")),"<Buffer "+e+">"},n.prototype.compare=function(e){if(!n.isBuffer(e))throw new TypeError("Argument must be a Buffer");return n.compare(this,e)},n.prototype.get=function(e){return console.log(".get() is deprecated. Access using array indexes instead."),this.readUInt8(e)},n.prototype.set=function(e,t){return console.log(".set() is deprecated. Access using array indexes instead."),this.writeUInt8(e,t)},n.prototype.write=function(e,t,r,n){if(isFinite(t))isFinite(r)||(n=r,r=void 0);else{var f=n;n=t,t=r,r=f}t=Number(t)||0;var l=this.length-t;r?(r=Number(r),r>l&&(r=l)):r=l,n=String(n||"utf8").toLowerCase();var d;switch(n){case"hex":d=o(this,e,t,r);break;case"utf8":case"utf-8":d=i(this,e,t,r);break;case"ascii":d=s(this,e,t,r);break;case"binary":d=a(this,e,t,r);break;case"base64":d=u(this,e,t,r);break;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":d=c(this,e,t,r);break;default:throw new TypeError("Unknown encoding: "+n)}return d},n.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}},n.prototype.slice=function(e,t){var r=this.length;if(e=~~e,t=void 0===t?r:~~t,0>e?(e+=r,0>e&&(e=0)):e>r&&(e=r),0>t?(t+=r,0>t&&(t=0)):t>r&&(t=r),e>t&&(t=e),n.TYPED_ARRAY_SUPPORT)return n._augment(this.subarray(e,t));for(var o=t-e,i=new n(o,void 0,!0),s=0;o>s;s++)i[s]=this[s+e];return i},n.prototype.readUInt8=function(e,t){return t||y(e,1,this.length),this[e]},n.prototype.readUInt16LE=function(e,t){return t||y(e,2,this.length),this[e]|this[e+1]<<8},n.prototype.readUInt16BE=function(e,t){return t||y(e,2,this.length),this[e]<<8|this[e+1]},n.prototype.readUInt32LE=function(e,t){return t||y(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},n.prototype.readUInt32BE=function(e,t){return t||y(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},n.prototype.readInt8=function(e,t){return t||y(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},n.prototype.readInt16LE=function(e,t){t||y(e,2,this.length);var r=this[e]|this[e+1]<<8;return 32768&r?4294901760|r:r},n.prototype.readInt16BE=function(e,t){t||y(e,2,this.length);var r=this[e+1]|this[e]<<8;return 32768&r?4294901760|r:r},n.prototype.readInt32LE=function(e,t){return t||y(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},n.prototype.readInt32BE=function(e,t){return t||y(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},n.prototype.readFloatLE=function(e,t){return t||y(e,4,this.length),D.read(this,e,!0,23,4)},n.prototype.readFloatBE=function(e,t){return t||y(e,4,this.length),D.read(this,e,!1,23,4)},n.prototype.readDoubleLE=function(e,t){return t||y(e,8,this.length),D.read(this,e,!0,52,8)},n.prototype.readDoubleBE=function(e,t){return t||y(e,8,this.length),D.read(this,e,!1,52,8)},n.prototype.writeUInt8=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,1,255,0),n.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=e,t+1},n.prototype.writeUInt16LE=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,2,65535,0),n.TYPED_ARRAY_SUPPORT?(this[t]=e,this[t+1]=e>>>8):m(this,e,t,!0),t+2},n.prototype.writeUInt16BE=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,2,65535,0),n.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=e):m(this,e,t,!1),t+2},n.prototype.writeUInt32LE=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,4,4294967295,0),n.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=e):b(this,e,t,!0),t+4},n.prototype.writeUInt32BE=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,4,4294967295,0),n.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=e):b(this,e,t,!1),t+4},n.prototype.writeInt8=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,1,127,-128),n.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),0>e&&(e=255+e+1),this[t]=e,t+1},n.prototype.writeInt16LE=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,2,32767,-32768),n.TYPED_ARRAY_SUPPORT?(this[t]=e,this[t+1]=e>>>8):m(this,e,t,!0),t+2},n.prototype.writeInt16BE=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,2,32767,-32768),n.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=e):m(this,e,t,!1),t+2},n.prototype.writeInt32LE=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,4,2147483647,-2147483648),n.TYPED_ARRAY_SUPPORT?(this[t]=e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):b(this,e,t,!0),t+4},n.prototype.writeInt32BE=function(e,t,r){return e=+e,t>>>=0,r||g(this,e,t,4,2147483647,-2147483648),0>e&&(e=4294967295+e+1),n.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=e):b(this,e,t,!1),t+4},n.prototype.writeFloatLE=function(e,t,r){return w(this,e,t,!0,r)},n.prototype.writeFloatBE=function(e,t,r){return w(this,e,t,!1,r)},n.prototype.writeDoubleLE=function(e,t,r){return E(this,e,t,!0,r)},n.prototype.writeDoubleBE=function(e,t,r){return E(this,e,t,!1,r)},n.prototype.copy=function(e,t,r,o){var i=this;if(r||(r=0),o||0===o||(o=this.length),t||(t=0),o!==r&&0!==e.length&&0!==i.length){if(r>o)throw new TypeError("sourceEnd < sourceStart");if(0>t||t>=e.length)throw new TypeError("targetStart out of bounds");if(0>r||r>=i.length)throw new TypeError("sourceStart out of bounds");if(0>o||o>i.length)throw new TypeError("sourceEnd out of bounds");o>this.length&&(o=this.length),e.length-t<o-r&&(o=e.length-t+r);var s=o-r;if(1e3>s||!n.TYPED_ARRAY_SUPPORT)for(var a=0;s>a;a++)e[a+t]=this[a+r];else e._set(this.subarray(r,r+s),t)}},n.prototype.fill=function(e,t,r){if(e||(e=0),t||(t=0),r||(r=this.length),t>r)throw new TypeError("end < start");if(r!==t&&0!==this.length){if(0>t||t>=this.length)throw new TypeError("start out of bounds");if(0>r||r>this.length)throw new TypeError("end out of bounds");var n;if("number"==typeof e)for(n=t;r>n;n++)this[n]=e;else{var o=j(e.toString()),i=o.length;for(n=t;r>n;n++)this[n]=o[n%i]}return this}},n.prototype.toArrayBuffer=function(){if("undefined"!=typeof Uint8Array){if(n.TYPED_ARRAY_SUPPORT)return new n(this).buffer;for(var e=new Uint8Array(this.length),t=0,r=e.length;r>t;t+=1)e[t]=this[t];return e.buffer}throw new TypeError("Buffer.toArrayBuffer not supported in this browser")};var P=n.prototype;n._augment=function(e){return e.constructor=n,e._isBuffer=!0,e._get=e.get,e._set=e.set,e.get=P.get,e.set=P.set,e.write=P.write,e.toString=P.toString,e.toLocaleString=P.toString,e.toJSON=P.toJSON,e.equals=P.equals,e.compare=P.compare,e.copy=P.copy,e.slice=P.slice,e.readUInt8=P.readUInt8,e.readUInt16LE=P.readUInt16LE,e.readUInt16BE=P.readUInt16BE,e.readUInt32LE=P.readUInt32LE,e.readUInt32BE=P.readUInt32BE,e.readInt8=P.readInt8,e.readInt16LE=P.readInt16LE,e.readInt16BE=P.readInt16BE,e.readInt32LE=P.readInt32LE,e.readInt32BE=P.readInt32BE,e.readFloatLE=P.readFloatLE,e.readFloatBE=P.readFloatBE,e.readDoubleLE=P.readDoubleLE,e.readDoubleBE=P.readDoubleBE,e.writeUInt8=P.writeUInt8,e.writeUInt16LE=P.writeUInt16LE,e.writeUInt16BE=P.writeUInt16BE,e.writeUInt32LE=P.writeUInt32LE,e.writeUInt32BE=P.writeUInt32BE,e.writeInt8=P.writeInt8,e.writeInt16LE=P.writeInt16LE,e.writeInt16BE=P.writeInt16BE,e.writeInt32LE=P.writeInt32LE,e.writeInt32BE=P.writeInt32BE,e.writeFloatLE=P.writeFloatLE,e.writeFloatBE=P.writeFloatBE,e.writeDoubleLE=P.writeDoubleLE,e.writeDoubleBE=P.writeDoubleBE,e.fill=P.fill,e.inspect=P.inspect,e.toArrayBuffer=P.toArrayBuffer,e};var U=/[^+\/0-9A-z]/g},{"base64-js":18,ieee754:19,"is-array":20}],18:[function(e,t,r){var n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";!function(e){"use strict";function t(e){var t=e.charCodeAt(0);return t===s?62:t===a?63:u>t?-1:u+10>t?t-u+26+26:f+26>t?t-f:c+26>t?t-c+26:void 0}function r(e){function r(e){c[l++]=e}var n,o,s,a,u,c;if(e.length%4>0)throw new Error("Invalid string. Length must be a multiple of 4");var f=e.length;u="="===e.charAt(f-2)?2:"="===e.charAt(f-1)?1:0,c=new i(3*e.length/4-u),s=u>0?e.length-4:e.length;var l=0;for(n=0,o=0;s>n;n+=4,o+=3)a=t(e.charAt(n))<<18|t(e.charAt(n+1))<<12|t(e.charAt(n+2))<<6|t(e.charAt(n+3)),r((16711680&a)>>16),r((65280&a)>>8),r(255&a);return 2===u?(a=t(e.charAt(n))<<2|t(e.charAt(n+1))>>4,r(255&a)):1===u&&(a=t(e.charAt(n))<<10|t(e.charAt(n+1))<<4|t(e.charAt(n+2))>>2,r(a>>8&255),r(255&a)),c}function o(e){function t(e){return n.charAt(e)}function r(e){return t(e>>18&63)+t(e>>12&63)+t(e>>6&63)+t(63&e)}var o,i,s,a=e.length%3,u="";for(o=0,s=e.length-a;s>o;o+=3)i=(e[o]<<16)+(e[o+1]<<8)+e[o+2],u+=r(i);switch(a){case 1:i=e[e.length-1],u+=t(i>>2),u+=t(i<<4&63),u+="==";break;case 2:i=(e[e.length-2]<<8)+e[e.length-1],u+=t(i>>10),u+=t(i>>4&63),u+=t(i<<2&63),u+="="}return u}var i="undefined"!=typeof Uint8Array?Uint8Array:Array,s="+".charCodeAt(0),a="/".charCodeAt(0),u="0".charCodeAt(0),c="a".charCodeAt(0),f="A".charCodeAt(0);e.toByteArray=r,e.fromByteArray=o}("undefined"==typeof r?this.base64js={}:r)},{}],19:[function(e,t,r){r.read=function(e,t,r,n,o){var i,s,a=8*o-n-1,u=(1<<a)-1,c=u>>1,f=-7,l=r?o-1:0,d=r?-1:1,h=e[t+l];for(l+=d,i=h&(1<<-f)-1,h>>=-f,f+=a;f>0;i=256*i+e[t+l],l+=d,f-=8);for(s=i&(1<<-f)-1,i>>=-f,f+=n;f>0;s=256*s+e[t+l],l+=d,f-=8);if(0===i)i=1-c;else{if(i===u)return s?0/0:1/0*(h?-1:1);s+=Math.pow(2,n),i-=c}return(h?-1:1)*s*Math.pow(2,i-n)},r.write=function(e,t,r,n,o,i){var s,a,u,c=8*i-o-1,f=(1<<c)-1,l=f>>1,d=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,h=n?0:i-1,p=n?1:-1,v=0>t||0===t&&0>1/t?1:0;for(t=Math.abs(t),isNaN(t)||1/0===t?(a=isNaN(t)?1:0,s=f):(s=Math.floor(Math.log(t)/Math.LN2),t*(u=Math.pow(2,-s))<1&&(s--,u*=2),t+=s+l>=1?d/u:d*Math.pow(2,1-l),t*u>=2&&(s++,u/=2),s+l>=f?(a=0,s=f):s+l>=1?(a=(t*u-1)*Math.pow(2,o),s+=l):(a=t*Math.pow(2,l-1)*Math.pow(2,o),s=0));o>=8;e[r+h]=255&a,h+=p,a/=256,o-=8);for(s=s<<o|a,c+=o;c>0;e[r+h]=255&s,h+=p,s/=256,c-=8);e[r+h-p]|=128*v}},{}],20:[function(e,t){var r=Array.isArray,n=Object.prototype.toString;t.exports=r||function(e){return!!e&&"[object Array]"==n.call(e)}},{}],21:[function(e,t){function r(){this._events=this._events||{},this._maxListeners=this._maxListeners||void 0}function n(e){return"function"==typeof e}function o(e){return"number"==typeof e}function i(e){return"object"==typeof e&&null!==e}function s(e){return void 0===e}t.exports=r,r.EventEmitter=r,r.prototype._events=void 0,r.prototype._maxListeners=void 0,r.defaultMaxListeners=10,r.prototype.setMaxListeners=function(e){if(!o(e)||0>e||isNaN(e))throw TypeError("n must be a positive number");return this._maxListeners=e,this},r.prototype.emit=function(e){var t,r,o,a,u,c;if(this._events||(this._events={}),"error"===e&&(!this._events.error||i(this._events.error)&&!this._events.error.length)){if(t=arguments[1],t instanceof Error)throw t;throw TypeError('Uncaught, unspecified "error" event.')}if(r=this._events[e],s(r))return!1;if(n(r))switch(arguments.length){case 1:r.call(this);break;case 2:r.call(this,arguments[1]);break;case 3:r.call(this,arguments[1],arguments[2]);break;default:for(o=arguments.length,a=new Array(o-1),u=1;o>u;u++)a[u-1]=arguments[u];r.apply(this,a)}else if(i(r)){for(o=arguments.length,a=new Array(o-1),u=1;o>u;u++)a[u-1]=arguments[u];for(c=r.slice(),o=c.length,u=0;o>u;u++)c[u].apply(this,a)}return!0},r.prototype.addListener=function(e,t){var o;if(!n(t))throw TypeError("listener must be a function");if(this._events||(this._events={}),this._events.newListener&&this.emit("newListener",e,n(t.listener)?t.listener:t),this._events[e]?i(this._events[e])?this._events[e].push(t):this._events[e]=[this._events[e],t]:this._events[e]=t,i(this._events[e])&&!this._events[e].warned){var o;o=s(this._maxListeners)?r.defaultMaxListeners:this._maxListeners,o&&o>0&&this._events[e].length>o&&(this._events[e].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[e].length),"function"==typeof console.trace&&console.trace())}return this},r.prototype.on=r.prototype.addListener,r.prototype.once=function(e,t){function r(){this.removeListener(e,r),o||(o=!0,t.apply(this,arguments))}if(!n(t))throw TypeError("listener must be a function");var o=!1;return r.listener=t,this.on(e,r),this},r.prototype.removeListener=function(e,t){var r,o,s,a;if(!n(t))throw TypeError("listener must be a function");if(!this._events||!this._events[e])return this;if(r=this._events[e],s=r.length,o=-1,r===t||n(r.listener)&&r.listener===t)delete this._events[e],this._events.removeListener&&this.emit("removeListener",e,t);else if(i(r)){for(a=s;a-->0;)if(r[a]===t||r[a].listener&&r[a].listener===t){o=a;break}if(0>o)return this;1===r.length?(r.length=0,delete this._events[e]):r.splice(o,1),this._events.removeListener&&this.emit("removeListener",e,t)}return this},r.prototype.removeAllListeners=function(e){var t,r;if(!this._events)return this;if(!this._events.removeListener)return 0===arguments.length?this._events={}:this._events[e]&&delete this._events[e],this;if(0===arguments.length){for(t in this._events)"removeListener"!==t&&this.removeAllListeners(t);return this.removeAllListeners("removeListener"),this._events={},this}if(r=this._events[e],n(r))this.removeListener(e,r);else for(;r.length;)this.removeListener(e,r[r.length-1]);return delete this._events[e],this},r.prototype.listeners=function(e){var t;return t=this._events&&this._events[e]?n(this._events[e])?[this._events[e]]:this._events[e].slice():[]},r.listenerCount=function(e,t){var r;return r=e._events&&e._events[t]?n(e._events[t])?1:e._events[t].length:0}},{}],22:[function(e,t){t.exports=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)}},{}],23:[function(e,t,r){(function(e){function t(e,t){for(var r=0,n=e.length-1;n>=0;n--){var o=e[n];"."===o?e.splice(n,1):".."===o?(e.splice(n,1),r++):r&&(e.splice(n,1),r--)}if(t)for(;r--;r)e.unshift("..");return e}function n(e,t){if(e.filter)return e.filter(t);for(var r=[],n=0;n<e.length;n++)t(e[n],n,e)&&r.push(e[n]);return r}var o=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/,i=function(e){return o.exec(e).slice(1)};r.resolve=function(){for(var r="",o=!1,i=arguments.length-1;i>=-1&&!o;i--){var s=i>=0?arguments[i]:e.cwd();if("string"!=typeof s)throw new TypeError("Arguments to path.resolve must be strings");s&&(r=s+"/"+r,o="/"===s.charAt(0))}return r=t(n(r.split("/"),function(e){return!!e}),!o).join("/"),(o?"/":"")+r||"."},r.normalize=function(e){var o=r.isAbsolute(e),i="/"===s(e,-1);return e=t(n(e.split("/"),function(e){return!!e}),!o).join("/"),e||o||(e="."),e&&i&&(e+="/"),(o?"/":"")+e},r.isAbsolute=function(e){return"/"===e.charAt(0)},r.join=function(){var e=Array.prototype.slice.call(arguments,0);return r.normalize(n(e,function(e){if("string"!=typeof e)throw new TypeError("Arguments to path.join must be strings");return e}).join("/"))},r.relative=function(e,t){function n(e){for(var t=0;t<e.length&&""===e[t];t++);for(var r=e.length-1;r>=0&&""===e[r];r--);return t>r?[]:e.slice(t,r-t+1)}e=r.resolve(e).substr(1),t=r.resolve(t).substr(1);for(var o=n(e.split("/")),i=n(t.split("/")),s=Math.min(o.length,i.length),a=s,u=0;s>u;u++)if(o[u]!==i[u]){a=u;break}for(var c=[],u=a;u<o.length;u++)c.push("..");return c=c.concat(i.slice(a)),c.join("/")},r.sep="/",r.delimiter=":",r.dirname=function(e){var t=i(e),r=t[0],n=t[1];return r||n?(n&&(n=n.substr(0,n.length-1)),r+n):"."},r.basename=function(e,t){var r=i(e)[2];return t&&r.substr(-1*t.length)===t&&(r=r.substr(0,r.length-t.length)),r},r.extname=function(e){return i(e)[3]};var s="b"==="ab".substr(-1)?function(e,t,r){return e.substr(t,r)}:function(e,t,r){return 0>t&&(t=e.length+t),e.substr(t,r)}}).call(this,e("_process"))},{_process:24}],24:[function(e,t){function r(){}var n=t.exports={};n.nextTick=function(){var e="undefined"!=typeof window&&window.setImmediate,t="undefined"!=typeof window&&window.MutationObserver,r="undefined"!=typeof window&&window.postMessage&&window.addEventListener;if(e)return function(e){return window.setImmediate(e)};var n=[];if(t){var o=document.createElement("div"),i=new MutationObserver(function(){var e=n.slice();n.length=0,e.forEach(function(e){e()})});return i.observe(o,{attributes:!0}),function(e){n.length||o.setAttribute("yes","no"),n.push(e)}}return r?(window.addEventListener("message",function(e){var t=e.source;if((t===window||null===t)&&"process-tick"===e.data&&(e.stopPropagation(),n.length>0)){var r=n.shift();r()}},!0),function(e){n.push(e),window.postMessage("process-tick","*")}):function(e){setTimeout(e,0)}}(),n.title="browser",n.browser=!0,n.env={},n.argv=[],n.on=r,n.addListener=r,n.once=r,n.off=r,n.removeListener=r,n.removeAllListeners=r,n.emit=r,n.binding=function(){throw new Error("process.binding is not supported")},n.cwd=function(){return"/"},n.chdir=function(){throw new Error("process.chdir is not supported")}},{}],25:[function(e,t){t.exports=e("./lib/_stream_duplex.js")},{"./lib/_stream_duplex.js":26}],26:[function(e,t){(function(r){function n(e){return this instanceof n?(u.call(this,e),c.call(this,e),e&&e.readable===!1&&(this.readable=!1),e&&e.writable===!1&&(this.writable=!1),this.allowHalfOpen=!0,e&&e.allowHalfOpen===!1&&(this.allowHalfOpen=!1),void this.once("end",o)):new n(e)}function o(){this.allowHalfOpen||this._writableState.ended||r.nextTick(this.end.bind(this)) +}function i(e,t){for(var r=0,n=e.length;n>r;r++)t(e[r],r)}t.exports=n;var s=Object.keys||function(e){var t=[];for(var r in e)t.push(r);return t},a=e("core-util-is");a.inherits=e("inherits");var u=e("./_stream_readable"),c=e("./_stream_writable");a.inherits(n,u),i(s(c.prototype),function(e){n.prototype[e]||(n.prototype[e]=c.prototype[e])})}).call(this,e("_process"))},{"./_stream_readable":28,"./_stream_writable":30,_process:24,"core-util-is":31,inherits:44}],27:[function(e,t){function r(e){return this instanceof r?void n.call(this,e):new r(e)}t.exports=r;var n=e("./_stream_transform"),o=e("core-util-is");o.inherits=e("inherits"),o.inherits(r,n),r.prototype._transform=function(e,t,r){r(null,e)}},{"./_stream_transform":29,"core-util-is":31,inherits:44}],28:[function(e,t){(function(r){function n(t){t=t||{};var r=t.highWaterMark;this.highWaterMark=r||0===r?r:16384,this.highWaterMark=~~this.highWaterMark,this.buffer=[],this.length=0,this.pipes=null,this.pipesCount=0,this.flowing=!1,this.ended=!1,this.endEmitted=!1,this.reading=!1,this.calledRead=!1,this.sync=!0,this.needReadable=!1,this.emittedReadable=!1,this.readableListening=!1,this.objectMode=!!t.objectMode,this.defaultEncoding=t.defaultEncoding||"utf8",this.ranOut=!1,this.awaitDrain=0,this.readingMore=!1,this.decoder=null,this.encoding=null,t.encoding&&(O||(O=e("string_decoder/").StringDecoder),this.decoder=new O(t.encoding),this.encoding=t.encoding)}function o(e){return this instanceof o?(this._readableState=new n(e,this),this.readable=!0,void A.call(this)):new o(e)}function i(e,t,r,n,o){var i=c(t,r);if(i)e.emit("error",i);else if(null===r||void 0===r)t.reading=!1,t.ended||f(e,t);else if(t.objectMode||r&&r.length>0)if(t.ended&&!o){var a=new Error("stream.push() after EOF");e.emit("error",a)}else if(t.endEmitted&&o){var a=new Error("stream.unshift() after end event");e.emit("error",a)}else!t.decoder||o||n||(r=t.decoder.write(r)),t.length+=t.objectMode?1:r.length,o?t.buffer.unshift(r):(t.reading=!1,t.buffer.push(r)),t.needReadable&&l(e),h(e,t);else o||(t.reading=!1);return s(t)}function s(e){return!e.ended&&(e.needReadable||e.length<e.highWaterMark||0===e.length)}function a(e){if(e>=R)e=R;else{e--;for(var t=1;32>t;t<<=1)e|=e>>t;e++}return e}function u(e,t){return 0===t.length&&t.ended?0:t.objectMode?0===e?0:1:null===e||isNaN(e)?t.flowing&&t.buffer.length?t.buffer[0].length:t.length:0>=e?0:(e>t.highWaterMark&&(t.highWaterMark=a(e)),e>t.length?t.ended?t.length:(t.needReadable=!0,0):e)}function c(e,t){var r=null;return k.isBuffer(t)||"string"==typeof t||null===t||void 0===t||e.objectMode||(r=new TypeError("Invalid non-string/buffer chunk")),r}function f(e,t){if(t.decoder&&!t.ended){var r=t.decoder.end();r&&r.length&&(t.buffer.push(r),t.length+=t.objectMode?1:r.length)}t.ended=!0,t.length>0?l(e):_(e)}function l(e){var t=e._readableState;t.needReadable=!1,t.emittedReadable||(t.emittedReadable=!0,t.sync?r.nextTick(function(){d(e)}):d(e))}function d(e){e.emit("readable")}function h(e,t){t.readingMore||(t.readingMore=!0,r.nextTick(function(){p(e,t)}))}function p(e,t){for(var r=t.length;!t.reading&&!t.flowing&&!t.ended&&t.length<t.highWaterMark&&(e.read(0),r!==t.length);)r=t.length;t.readingMore=!1}function v(e){return function(){var t=e._readableState;t.awaitDrain--,0===t.awaitDrain&&y(e)}}function y(e){function t(e){var t=e.write(r);!1===t&&n.awaitDrain++}var r,n=e._readableState;for(n.awaitDrain=0;n.pipesCount&&null!==(r=e.read());)if(1===n.pipesCount?t(n.pipes,0,null):w(n.pipes,t),e.emit("data",r),n.awaitDrain>0)return;return 0===n.pipesCount?(n.flowing=!1,void(S.listenerCount(e,"data")>0&&m(e))):void(n.ranOut=!0)}function g(){this._readableState.ranOut&&(this._readableState.ranOut=!1,y(this))}function m(e,t){var n=e._readableState;if(n.flowing)throw new Error("Cannot switch to old mode now.");var o=t||!1,i=!1;e.readable=!0,e.pipe=A.prototype.pipe,e.on=e.addListener=A.prototype.on,e.on("readable",function(){i=!0;for(var t;!o&&null!==(t=e.read());)e.emit("data",t);null===t&&(i=!1,e._readableState.needReadable=!0)}),e.pause=function(){o=!0,this.emit("pause")},e.resume=function(){o=!1,i?r.nextTick(function(){e.emit("readable")}):this.read(0),this.emit("resume")},e.emit("readable")}function b(e,t){var r,n=t.buffer,o=t.length,i=!!t.decoder,s=!!t.objectMode;if(0===n.length)return null;if(0===o)r=null;else if(s)r=n.shift();else if(!e||e>=o)r=i?n.join(""):k.concat(n,o),n.length=0;else if(e<n[0].length){var a=n[0];r=a.slice(0,e),n[0]=a.slice(e)}else if(e===n[0].length)r=n.shift();else{r=i?"":new k(e);for(var u=0,c=0,f=n.length;f>c&&e>u;c++){var a=n[0],l=Math.min(e-u,a.length);i?r+=a.slice(0,l):a.copy(r,u,0,l),l<a.length?n[0]=a.slice(l):n.shift(),u+=l}}return r}function _(e){var t=e._readableState;if(t.length>0)throw new Error("endReadable called on non-empty stream");!t.endEmitted&&t.calledRead&&(t.ended=!0,r.nextTick(function(){t.endEmitted||0!==t.length||(t.endEmitted=!0,e.readable=!1,e.emit("end"))}))}function w(e,t){for(var r=0,n=e.length;n>r;r++)t(e[r],r)}function E(e,t){for(var r=0,n=e.length;n>r;r++)if(e[r]===t)return r;return-1}t.exports=o;var x=e("isarray"),k=e("buffer").Buffer;o.ReadableState=n;var S=e("events").EventEmitter;S.listenerCount||(S.listenerCount=function(e,t){return e.listeners(t).length});var A=e("stream"),j=e("core-util-is");j.inherits=e("inherits");var O;j.inherits(o,A),o.prototype.push=function(e,t){var r=this._readableState;return"string"!=typeof e||r.objectMode||(t=t||r.defaultEncoding,t!==r.encoding&&(e=new k(e,t),t="")),i(this,r,e,t,!1)},o.prototype.unshift=function(e){var t=this._readableState;return i(this,t,e,"",!0)},o.prototype.setEncoding=function(t){O||(O=e("string_decoder/").StringDecoder),this._readableState.decoder=new O(t),this._readableState.encoding=t};var R=8388608;o.prototype.read=function(e){var t=this._readableState;t.calledRead=!0;var r,n=e;if(("number"!=typeof e||e>0)&&(t.emittedReadable=!1),0===e&&t.needReadable&&(t.length>=t.highWaterMark||t.ended))return l(this),null;if(e=u(e,t),0===e&&t.ended)return r=null,t.length>0&&t.decoder&&(r=b(e,t),t.length-=r.length),0===t.length&&_(this),r;var o=t.needReadable;return t.length-e<=t.highWaterMark&&(o=!0),(t.ended||t.reading)&&(o=!1),o&&(t.reading=!0,t.sync=!0,0===t.length&&(t.needReadable=!0),this._read(t.highWaterMark),t.sync=!1),o&&!t.reading&&(e=u(n,t)),r=e>0?b(e,t):null,null===r&&(t.needReadable=!0,e=0),t.length-=e,0!==t.length||t.ended||(t.needReadable=!0),t.ended&&!t.endEmitted&&0===t.length&&_(this),r},o.prototype._read=function(){this.emit("error",new Error("not implemented"))},o.prototype.pipe=function(e,t){function n(e){e===f&&i()}function o(){e.end()}function i(){e.removeListener("close",a),e.removeListener("finish",u),e.removeListener("drain",p),e.removeListener("error",s),e.removeListener("unpipe",n),f.removeListener("end",o),f.removeListener("end",i),(!e._writableState||e._writableState.needDrain)&&p()}function s(t){c(),e.removeListener("error",s),0===S.listenerCount(e,"error")&&e.emit("error",t)}function a(){e.removeListener("finish",u),c()}function u(){e.removeListener("close",a),c()}function c(){f.unpipe(e)}var f=this,l=this._readableState;switch(l.pipesCount){case 0:l.pipes=e;break;case 1:l.pipes=[l.pipes,e];break;default:l.pipes.push(e)}l.pipesCount+=1;var d=(!t||t.end!==!1)&&e!==r.stdout&&e!==r.stderr,h=d?o:i;l.endEmitted?r.nextTick(h):f.once("end",h),e.on("unpipe",n);var p=v(f);return e.on("drain",p),e._events&&e._events.error?x(e._events.error)?e._events.error.unshift(s):e._events.error=[s,e._events.error]:e.on("error",s),e.once("close",a),e.once("finish",u),e.emit("pipe",f),l.flowing||(this.on("readable",g),l.flowing=!0,r.nextTick(function(){y(f)})),e},o.prototype.unpipe=function(e){var t=this._readableState;if(0===t.pipesCount)return this;if(1===t.pipesCount)return e&&e!==t.pipes?this:(e||(e=t.pipes),t.pipes=null,t.pipesCount=0,this.removeListener("readable",g),t.flowing=!1,e&&e.emit("unpipe",this),this);if(!e){var r=t.pipes,n=t.pipesCount;t.pipes=null,t.pipesCount=0,this.removeListener("readable",g),t.flowing=!1;for(var o=0;n>o;o++)r[o].emit("unpipe",this);return this}var o=E(t.pipes,e);return-1===o?this:(t.pipes.splice(o,1),t.pipesCount-=1,1===t.pipesCount&&(t.pipes=t.pipes[0]),e.emit("unpipe",this),this)},o.prototype.on=function(e,t){var r=A.prototype.on.call(this,e,t);if("data"!==e||this._readableState.flowing||m(this),"readable"===e&&this.readable){var n=this._readableState;n.readableListening||(n.readableListening=!0,n.emittedReadable=!1,n.needReadable=!0,n.reading?n.length&&l(this,n):this.read(0))}return r},o.prototype.addListener=o.prototype.on,o.prototype.resume=function(){m(this),this.read(0),this.emit("resume")},o.prototype.pause=function(){m(this,!0),this.emit("pause")},o.prototype.wrap=function(e){var t=this._readableState,r=!1,n=this;e.on("end",function(){if(t.decoder&&!t.ended){var e=t.decoder.end();e&&e.length&&n.push(e)}n.push(null)}),e.on("data",function(o){if(t.decoder&&(o=t.decoder.write(o)),(!t.objectMode||null!==o&&void 0!==o)&&(t.objectMode||o&&o.length)){var i=n.push(o);i||(r=!0,e.pause())}});for(var o in e)"function"==typeof e[o]&&"undefined"==typeof this[o]&&(this[o]=function(t){return function(){return e[t].apply(e,arguments)}}(o));var i=["error","close","destroy","pause","resume"];return w(i,function(t){e.on(t,n.emit.bind(n,t))}),n._read=function(){r&&(r=!1,e.resume())},n},o._fromList=b}).call(this,e("_process"))},{_process:24,buffer:17,"core-util-is":31,events:21,inherits:44,isarray:22,stream:36,"string_decoder/":37}],29:[function(e,t){function r(e,t){this.afterTransform=function(e,r){return n(t,e,r)},this.needTransform=!1,this.transforming=!1,this.writecb=null,this.writechunk=null}function n(e,t,r){var n=e._transformState;n.transforming=!1;var o=n.writecb;if(!o)return e.emit("error",new Error("no writecb in Transform class"));n.writechunk=null,n.writecb=null,null!==r&&void 0!==r&&e.push(r),o&&o(t);var i=e._readableState;i.reading=!1,(i.needReadable||i.length<i.highWaterMark)&&e._read(i.highWaterMark)}function o(e){if(!(this instanceof o))return new o(e);s.call(this,e);var t=(this._transformState=new r(e,this),this);this._readableState.needReadable=!0,this._readableState.sync=!1,this.once("finish",function(){"function"==typeof this._flush?this._flush(function(e){i(t,e)}):i(t)})}function i(e,t){if(t)return e.emit("error",t);var r=e._writableState,n=(e._readableState,e._transformState);if(r.length)throw new Error("calling transform done when ws.length != 0");if(n.transforming)throw new Error("calling transform done when still transforming");return e.push(null)}t.exports=o;var s=e("./_stream_duplex"),a=e("core-util-is");a.inherits=e("inherits"),a.inherits(o,s),o.prototype.push=function(e,t){return this._transformState.needTransform=!1,s.prototype.push.call(this,e,t)},o.prototype._transform=function(){throw new Error("not implemented")},o.prototype._write=function(e,t,r){var n=this._transformState;if(n.writecb=r,n.writechunk=e,n.writeencoding=t,!n.transforming){var o=this._readableState;(n.needTransform||o.needReadable||o.length<o.highWaterMark)&&this._read(o.highWaterMark)}},o.prototype._read=function(){var e=this._transformState;null!==e.writechunk&&e.writecb&&!e.transforming?(e.transforming=!0,this._transform(e.writechunk,e.writeencoding,e.afterTransform)):e.needTransform=!0}},{"./_stream_duplex":26,"core-util-is":31,inherits:44}],30:[function(e,t){(function(r){function n(e,t,r){this.chunk=e,this.encoding=t,this.callback=r}function o(e,t){e=e||{};var r=e.highWaterMark;this.highWaterMark=r||0===r?r:16384,this.objectMode=!!e.objectMode,this.highWaterMark=~~this.highWaterMark,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1;var n=e.decodeStrings===!1;this.decodeStrings=!n,this.defaultEncoding=e.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(e){h(t,e)},this.writecb=null,this.writelen=0,this.buffer=[],this.errorEmitted=!1}function i(t){var r=e("./_stream_duplex");return this instanceof i||this instanceof r?(this._writableState=new o(t,this),this.writable=!0,void E.call(this)):new i(t)}function s(e,t,n){var o=new Error("write after end");e.emit("error",o),r.nextTick(function(){n(o)})}function a(e,t,n,o){var i=!0;if(!_.isBuffer(n)&&"string"!=typeof n&&null!==n&&void 0!==n&&!t.objectMode){var s=new TypeError("Invalid non-string/buffer chunk");e.emit("error",s),r.nextTick(function(){o(s)}),i=!1}return i}function u(e,t,r){return e.objectMode||e.decodeStrings===!1||"string"!=typeof t||(t=new _(t,r)),t}function c(e,t,r,o,i){r=u(t,r,o),_.isBuffer(r)&&(o="buffer");var s=t.objectMode?1:r.length;t.length+=s;var a=t.length<t.highWaterMark;return a||(t.needDrain=!0),t.writing?t.buffer.push(new n(r,o,i)):f(e,t,s,r,o,i),a}function f(e,t,r,n,o,i){t.writelen=r,t.writecb=i,t.writing=!0,t.sync=!0,e._write(n,o,t.onwrite),t.sync=!1}function l(e,t,n,o,i){n?r.nextTick(function(){i(o)}):i(o),e._writableState.errorEmitted=!0,e.emit("error",o)}function d(e){e.writing=!1,e.writecb=null,e.length-=e.writelen,e.writelen=0}function h(e,t){var n=e._writableState,o=n.sync,i=n.writecb;if(d(n),t)l(e,n,o,t,i);else{var s=g(e,n);s||n.bufferProcessing||!n.buffer.length||y(e,n),o?r.nextTick(function(){p(e,n,s,i)}):p(e,n,s,i)}}function p(e,t,r,n){r||v(e,t),n(),r&&m(e,t)}function v(e,t){0===t.length&&t.needDrain&&(t.needDrain=!1,e.emit("drain"))}function y(e,t){t.bufferProcessing=!0;for(var r=0;r<t.buffer.length;r++){var n=t.buffer[r],o=n.chunk,i=n.encoding,s=n.callback,a=t.objectMode?1:o.length;if(f(e,t,a,o,i,s),t.writing){r++;break}}t.bufferProcessing=!1,r<t.buffer.length?t.buffer=t.buffer.slice(r):t.buffer.length=0}function g(e,t){return t.ending&&0===t.length&&!t.finished&&!t.writing}function m(e,t){var r=g(e,t);return r&&(t.finished=!0,e.emit("finish")),r}function b(e,t,n){t.ending=!0,m(e,t),n&&(t.finished?r.nextTick(n):e.once("finish",n)),t.ended=!0}t.exports=i;var _=e("buffer").Buffer;i.WritableState=o;var w=e("core-util-is");w.inherits=e("inherits");var E=e("stream");w.inherits(i,E),i.prototype.pipe=function(){this.emit("error",new Error("Cannot pipe. Not readable."))},i.prototype.write=function(e,t,r){var n=this._writableState,o=!1;return"function"==typeof t&&(r=t,t=null),_.isBuffer(e)?t="buffer":t||(t=n.defaultEncoding),"function"!=typeof r&&(r=function(){}),n.ended?s(this,n,r):a(this,n,e,r)&&(o=c(this,n,e,t,r)),o},i.prototype._write=function(e,t,r){r(new Error("not implemented"))},i.prototype.end=function(e,t,r){var n=this._writableState;"function"==typeof e?(r=e,e=null,t=null):"function"==typeof t&&(r=t,t=null),"undefined"!=typeof e&&null!==e&&this.write(e,t),n.ending||n.finished||b(this,n,r)}}).call(this,e("_process"))},{"./_stream_duplex":26,_process:24,buffer:17,"core-util-is":31,inherits:44,stream:36}],31:[function(e,t,r){(function(e){function t(e){return Array.isArray(e)}function n(e){return"boolean"==typeof e}function o(e){return null===e}function i(e){return null==e}function s(e){return"number"==typeof e}function a(e){return"string"==typeof e}function u(e){return"symbol"==typeof e}function c(e){return void 0===e}function f(e){return l(e)&&"[object RegExp]"===g(e)}function l(e){return"object"==typeof e&&null!==e}function d(e){return l(e)&&"[object Date]"===g(e)}function h(e){return l(e)&&("[object Error]"===g(e)||e instanceof Error)}function p(e){return"function"==typeof e}function v(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||"undefined"==typeof e}function y(t){return e.isBuffer(t)}function g(e){return Object.prototype.toString.call(e)}r.isArray=t,r.isBoolean=n,r.isNull=o,r.isNullOrUndefined=i,r.isNumber=s,r.isString=a,r.isSymbol=u,r.isUndefined=c,r.isRegExp=f,r.isObject=l,r.isDate=d,r.isError=h,r.isFunction=p,r.isPrimitive=v,r.isBuffer=y}).call(this,e("buffer").Buffer)},{buffer:17}],32:[function(e,t){t.exports=e("./lib/_stream_passthrough.js")},{"./lib/_stream_passthrough.js":27}],33:[function(e,t,r){var n=e("stream");r=t.exports=e("./lib/_stream_readable.js"),r.Stream=n,r.Readable=r,r.Writable=e("./lib/_stream_writable.js"),r.Duplex=e("./lib/_stream_duplex.js"),r.Transform=e("./lib/_stream_transform.js"),r.PassThrough=e("./lib/_stream_passthrough.js")},{"./lib/_stream_duplex.js":26,"./lib/_stream_passthrough.js":27,"./lib/_stream_readable.js":28,"./lib/_stream_transform.js":29,"./lib/_stream_writable.js":30,stream:36}],34:[function(e,t){t.exports=e("./lib/_stream_transform.js")},{"./lib/_stream_transform.js":29}],35:[function(e,t){t.exports=e("./lib/_stream_writable.js")},{"./lib/_stream_writable.js":30}],36:[function(e,t){function r(){n.call(this)}t.exports=r;var n=e("events").EventEmitter,o=e("inherits");o(r,n),r.Readable=e("readable-stream/readable.js"),r.Writable=e("readable-stream/writable.js"),r.Duplex=e("readable-stream/duplex.js"),r.Transform=e("readable-stream/transform.js"),r.PassThrough=e("readable-stream/passthrough.js"),r.Stream=r,r.prototype.pipe=function(e,t){function r(t){e.writable&&!1===e.write(t)&&c.pause&&c.pause()}function o(){c.readable&&c.resume&&c.resume()}function i(){f||(f=!0,e.end())}function s(){f||(f=!0,"function"==typeof e.destroy&&e.destroy())}function a(e){if(u(),0===n.listenerCount(this,"error"))throw e}function u(){c.removeListener("data",r),e.removeListener("drain",o),c.removeListener("end",i),c.removeListener("close",s),c.removeListener("error",a),e.removeListener("error",a),c.removeListener("end",u),c.removeListener("close",u),e.removeListener("close",u)}var c=this;c.on("data",r),e.on("drain",o),e._isStdio||t&&t.end===!1||(c.on("end",i),c.on("close",s));var f=!1;return c.on("error",a),e.on("error",a),c.on("end",u),c.on("close",u),e.on("close",u),e.emit("pipe",c),e}},{events:21,inherits:44,"readable-stream/duplex.js":25,"readable-stream/passthrough.js":32,"readable-stream/readable.js":33,"readable-stream/transform.js":34,"readable-stream/writable.js":35}],37:[function(e,t,r){function n(e){if(e&&!u(e))throw new Error("Unknown encoding: "+e)}function o(e){return e.toString(this.encoding)}function i(e){this.charReceived=e.length%2,this.charLength=this.charReceived?2:0}function s(e){this.charReceived=e.length%3,this.charLength=this.charReceived?3:0}var a=e("buffer").Buffer,u=a.isEncoding||function(e){switch(e&&e.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}},c=r.StringDecoder=function(e){switch(this.encoding=(e||"utf8").toLowerCase().replace(/[-_]/,""),n(e),this.encoding){case"utf8":this.surrogateSize=3;break;case"ucs2":case"utf16le":this.surrogateSize=2,this.detectIncompleteChar=i;break;case"base64":this.surrogateSize=3,this.detectIncompleteChar=s;break;default:return void(this.write=o)}this.charBuffer=new a(6),this.charReceived=0,this.charLength=0};c.prototype.write=function(e){for(var t="";this.charLength;){var r=e.length>=this.charLength-this.charReceived?this.charLength-this.charReceived:e.length;if(e.copy(this.charBuffer,this.charReceived,0,r),this.charReceived+=r,this.charReceived<this.charLength)return"";e=e.slice(r,e.length),t=this.charBuffer.slice(0,this.charLength).toString(this.encoding);var n=t.charCodeAt(t.length-1);if(!(n>=55296&&56319>=n)){if(this.charReceived=this.charLength=0,0===e.length)return t;break}this.charLength+=this.surrogateSize,t=""}this.detectIncompleteChar(e);var o=e.length;this.charLength&&(e.copy(this.charBuffer,0,e.length-this.charReceived,o),o-=this.charReceived),t+=e.toString(this.encoding,0,o);var o=t.length-1,n=t.charCodeAt(o);if(n>=55296&&56319>=n){var i=this.surrogateSize;return this.charLength+=i,this.charReceived+=i,this.charBuffer.copy(this.charBuffer,i,0,i),e.copy(this.charBuffer,0,0,i),t.substring(0,o)}return t},c.prototype.detectIncompleteChar=function(e){for(var t=e.length>=3?3:e.length;t>0;t--){var r=e[e.length-t];if(1==t&&r>>5==6){this.charLength=2;break}if(2>=t&&r>>4==14){this.charLength=3;break}if(3>=t&&r>>3==30){this.charLength=4;break}}this.charReceived=t},c.prototype.end=function(e){var t="";if(e&&e.length&&(t=this.write(e)),this.charReceived){var r=this.charReceived,n=this.charBuffer,o=this.encoding;t+=n.slice(0,r).toString(o)}return t}},{buffer:17}],38:[function(e,t){t.exports=function(e){return e&&"object"==typeof e&&"function"==typeof e.copy&&"function"==typeof e.fill&&"function"==typeof e.readUInt8}},{}],39:[function(e,t,r){(function(t,n){function o(e,t){var n={seen:[],stylize:s};return arguments.length>=3&&(n.depth=arguments[2]),arguments.length>=4&&(n.colors=arguments[3]),v(t)?n.showHidden=t:t&&r._extend(n,t),w(n.showHidden)&&(n.showHidden=!1),w(n.depth)&&(n.depth=2),w(n.colors)&&(n.colors=!1),w(n.customInspect)&&(n.customInspect=!0),n.colors&&(n.stylize=i),u(n,e,n.depth)}function i(e,t){var r=o.styles[t];return r?"["+o.colors[r][0]+"m"+e+"["+o.colors[r][1]+"m":e}function s(e){return e}function a(e){var t={};return e.forEach(function(e){t[e]=!0}),t}function u(e,t,n){if(e.customInspect&&t&&A(t.inspect)&&t.inspect!==r.inspect&&(!t.constructor||t.constructor.prototype!==t)){var o=t.inspect(n,e);return b(o)||(o=u(e,o,n)),o}var i=c(e,t);if(i)return i;var s=Object.keys(t),v=a(s);if(e.showHidden&&(s=Object.getOwnPropertyNames(t)),S(t)&&(s.indexOf("message")>=0||s.indexOf("description")>=0))return f(t);if(0===s.length){if(A(t)){var y=t.name?": "+t.name:"";return e.stylize("[Function"+y+"]","special")}if(E(t))return e.stylize(RegExp.prototype.toString.call(t),"regexp");if(k(t))return e.stylize(Date.prototype.toString.call(t),"date");if(S(t))return f(t)}var g="",m=!1,_=["{","}"];if(p(t)&&(m=!0,_=["[","]"]),A(t)){var w=t.name?": "+t.name:"";g=" [Function"+w+"]"}if(E(t)&&(g=" "+RegExp.prototype.toString.call(t)),k(t)&&(g=" "+Date.prototype.toUTCString.call(t)),S(t)&&(g=" "+f(t)),0===s.length&&(!m||0==t.length))return _[0]+g+_[1];if(0>n)return E(t)?e.stylize(RegExp.prototype.toString.call(t),"regexp"):e.stylize("[Object]","special");e.seen.push(t);var x;return x=m?l(e,t,n,v,s):s.map(function(r){return d(e,t,n,v,r,m)}),e.seen.pop(),h(x,g,_)}function c(e,t){if(w(t))return e.stylize("undefined","undefined");if(b(t)){var r="'"+JSON.stringify(t).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return e.stylize(r,"string")}return m(t)?e.stylize(""+t,"number"):v(t)?e.stylize(""+t,"boolean"):y(t)?e.stylize("null","null"):void 0}function f(e){return"["+Error.prototype.toString.call(e)+"]"}function l(e,t,r,n,o){for(var i=[],s=0,a=t.length;a>s;++s)i.push(N(t,String(s))?d(e,t,r,n,String(s),!0):"");return o.forEach(function(o){o.match(/^\d+$/)||i.push(d(e,t,r,n,o,!0))}),i}function d(e,t,r,n,o,i){var s,a,c;if(c=Object.getOwnPropertyDescriptor(t,o)||{value:t[o]},c.get?a=c.set?e.stylize("[Getter/Setter]","special"):e.stylize("[Getter]","special"):c.set&&(a=e.stylize("[Setter]","special")),N(n,o)||(s="["+o+"]"),a||(e.seen.indexOf(c.value)<0?(a=y(r)?u(e,c.value,null):u(e,c.value,r-1),a.indexOf("\n")>-1&&(a=i?a.split("\n").map(function(e){return" "+e}).join("\n").substr(2):"\n"+a.split("\n").map(function(e){return" "+e}).join("\n"))):a=e.stylize("[Circular]","special")),w(s)){if(i&&o.match(/^\d+$/))return a;s=JSON.stringify(""+o),s.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(s=s.substr(1,s.length-2),s=e.stylize(s,"name")):(s=s.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),s=e.stylize(s,"string"))}return s+": "+a}function h(e,t,r){var n=0,o=e.reduce(function(e,t){return n++,t.indexOf("\n")>=0&&n++,e+t.replace(/\u001b\[\d\d?m/g,"").length+1},0);return o>60?r[0]+(""===t?"":t+"\n ")+" "+e.join(",\n ")+" "+r[1]:r[0]+t+" "+e.join(", ")+" "+r[1]}function p(e){return Array.isArray(e)}function v(e){return"boolean"==typeof e}function y(e){return null===e}function g(e){return null==e}function m(e){return"number"==typeof e}function b(e){return"string"==typeof e}function _(e){return"symbol"==typeof e}function w(e){return void 0===e}function E(e){return x(e)&&"[object RegExp]"===O(e)}function x(e){return"object"==typeof e&&null!==e}function k(e){return x(e)&&"[object Date]"===O(e)}function S(e){return x(e)&&("[object Error]"===O(e)||e instanceof Error)}function A(e){return"function"==typeof e}function j(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||"undefined"==typeof e}function O(e){return Object.prototype.toString.call(e)}function R(e){return 10>e?"0"+e.toString(10):e.toString(10)}function I(){var e=new Date,t=[R(e.getHours()),R(e.getMinutes()),R(e.getSeconds())].join(":");return[e.getDate(),B[e.getMonth()],t].join(" ")}function N(e,t){return Object.prototype.hasOwnProperty.call(e,t)}var T=/%[sdj%]/g;r.format=function(e){if(!b(e)){for(var t=[],r=0;r<arguments.length;r++)t.push(o(arguments[r]));return t.join(" ")}for(var r=1,n=arguments,i=n.length,s=String(e).replace(T,function(e){if("%"===e)return"%";if(r>=i)return e;switch(e){case"%s":return String(n[r++]);case"%d":return Number(n[r++]);case"%j":try{return JSON.stringify(n[r++])}catch(t){return"[Circular]"}default:return e}}),a=n[r];i>r;a=n[++r])s+=y(a)||!x(a)?" "+a:" "+o(a);return s},r.deprecate=function(e,o){function i(){if(!s){if(t.throwDeprecation)throw new Error(o);t.traceDeprecation?console.trace(o):console.error(o),s=!0}return e.apply(this,arguments)}if(w(n.process))return function(){return r.deprecate(e,o).apply(this,arguments)};if(t.noDeprecation===!0)return e;var s=!1;return i};var L,D={};r.debuglog=function(e){if(w(L)&&(L=t.env.NODE_DEBUG||""),e=e.toUpperCase(),!D[e])if(new RegExp("\\b"+e+"\\b","i").test(L)){var n=t.pid;D[e]=function(){var t=r.format.apply(r,arguments);console.error("%s %d: %s",e,n,t)}}else D[e]=function(){};return D[e]},r.inspect=o,o.colors={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},o.styles={special:"cyan",number:"yellow","boolean":"yellow",undefined:"grey","null":"bold",string:"green",date:"magenta",regexp:"red"},r.isArray=p,r.isBoolean=v,r.isNull=y,r.isNullOrUndefined=g,r.isNumber=m,r.isString=b,r.isSymbol=_,r.isUndefined=w,r.isRegExp=E,r.isObject=x,r.isDate=k,r.isError=S,r.isFunction=A,r.isPrimitive=j,r.isBuffer=e("./support/isBuffer");var B=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];r.log=function(){console.log("%s - %s",I(),r.format.apply(r,arguments))},r.inherits=e("inherits"),r._extend=function(e,t){if(!t||!x(t))return e;for(var r=Object.keys(t),n=r.length;n--;)e[r[n]]=t[r[n]];return e}}).call(this,e("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./support/isBuffer":38,_process:24,inherits:44}],40:[function(e,t,r){function n(){return"WebkitAppearance"in document.documentElement.style||window.console&&(console.firebug||console.exception&&console.table)||navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)&&parseInt(RegExp.$1,10)>=31}function o(){var e=arguments,t=this.useColors;if(e[0]=(t?"%c":"")+this.namespace+(t?" %c":" ")+e[0]+(t?"%c ":" ")+"+"+r.humanize(this.diff),!t)return e;var n="color: "+this.color;e=[e[0],n,"color: inherit"].concat(Array.prototype.slice.call(e,1));var o=0,i=0;return e[0].replace(/%[a-z%]/g,function(e){"%"!==e&&(o++,"%c"===e&&(i=o))}),e.splice(i,0,n),e}function i(){return"object"==typeof console&&"function"==typeof console.log&&Function.prototype.apply.call(console.log,console,arguments)}function s(e){try{null==e?localStorage.removeItem("debug"):localStorage.debug=e}catch(t){}}function a(){var e;try{e=localStorage.debug}catch(t){}return e}r=t.exports=e("./debug"),r.log=i,r.formatArgs=o,r.save=s,r.load=a,r.useColors=n,r.colors=["lightseagreen","forestgreen","goldenrod","dodgerblue","darkorchid","crimson"],r.formatters.j=function(e){return JSON.stringify(e)},r.enable(a())},{"./debug":41}],41:[function(e,t,r){function n(){return r.colors[f++%r.colors.length]}function o(e){function t(){}function o(){var e=o,t=+new Date,i=t-(c||t);e.diff=i,e.prev=c,e.curr=t,c=t,null==e.useColors&&(e.useColors=r.useColors()),null==e.color&&e.useColors&&(e.color=n());var s=Array.prototype.slice.call(arguments);s[0]=r.coerce(s[0]),"string"!=typeof s[0]&&(s=["%o"].concat(s));var a=0;s[0]=s[0].replace(/%([a-z%])/g,function(t,n){if("%"===t)return t;a++;var o=r.formatters[n];if("function"==typeof o){var i=s[a];t=o.call(e,i),s.splice(a,1),a--}return t}),"function"==typeof r.formatArgs&&(s=r.formatArgs.apply(e,s));var u=o.log||r.log||console.log.bind(console);u.apply(e,s)}t.enabled=!1,o.enabled=!0;var i=r.enabled(e)?o:t;return i.namespace=e,i}function i(e){r.save(e);for(var t=(e||"").split(/[\s,]+/),n=t.length,o=0;n>o;o++)t[o]&&(e=t[o].replace(/\*/g,".*?"),"-"===e[0]?r.skips.push(new RegExp("^"+e.substr(1)+"$")):r.names.push(new RegExp("^"+e+"$")))}function s(){r.enable("")}function a(e){var t,n;for(t=0,n=r.skips.length;n>t;t++)if(r.skips[t].test(e))return!1;for(t=0,n=r.names.length;n>t;t++)if(r.names[t].test(e))return!0;return!1}function u(e){return e instanceof Error?e.stack||e.message:e}r=t.exports=o,r.coerce=u,r.disable=s,r.enable=i,r.enabled=a,r.humanize=e("ms"),r.names=[],r.skips=[],r.formatters={};var c,f=0},{ms:42}],42:[function(e,t){function r(e){var t=/^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(e);if(t){var r=parseFloat(t[1]),n=(t[2]||"ms").toLowerCase();switch(n){case"years":case"year":case"y":return r*f;case"days":case"day":case"d":return r*c;case"hours":case"hour":case"h":return r*u;case"minutes":case"minute":case"m":return r*a;case"seconds":case"second":case"s":return r*s;case"ms":return r}}}function n(e){return e>=c?Math.round(e/c)+"d":e>=u?Math.round(e/u)+"h":e>=a?Math.round(e/a)+"m":e>=s?Math.round(e/s)+"s":e+"ms"}function o(e){return i(e,c,"day")||i(e,u,"hour")||i(e,a,"minute")||i(e,s,"second")||e+" ms"}function i(e,t,r){return t>e?void 0:1.5*t>e?Math.floor(e/t)+" "+r:Math.ceil(e/t)+" "+r+"s"}var s=1e3,a=60*s,u=60*a,c=24*u,f=365.25*c;t.exports=function(e,t){return t=t||{},"string"==typeof e?r(e):t.long?o(e):n(e)}},{}],43:[function(e,t){"use strict";function r(e){if(this._capacity=i(e),this._length=0,this._front=0,this._makeCapacity(),s(e)){for(var t=e.length,r=0;t>r;++r)this[r]=e[r];this._length=t}}function n(e,t,r,n,o){for(var i=0;o>i;++i)r[i+n]=e[i+t]}function o(e){return e>>>=0,e-=1,e|=e>>1,e|=e>>2,e|=e>>4,e|=e>>8,e|=e>>16,e+1}function i(e){if("number"!=typeof e){if(!s(e))return 16;e=e.length}return o(Math.min(Math.max(16,e),1073741824))}r.prototype.toArray=function(){for(var e=this._length,t=new Array(e),r=this._front,n=this._capacity,o=0;e>o;++o)t[o]=this[r+o&n-1];return t},r.prototype.push=function(e){var t=arguments.length,r=this._length;if(t>1){var n=this._capacity;if(r+t>n){for(var o=0;t>o;++o){this._checkCapacity(r+1);var i=this._front+r&this._capacity-1;this[i]=arguments[o],r++,this._length=r}return r}for(var i=this._front,o=0;t>o;++o)this[i+r&n-1]=arguments[o],i++;return this._length=r+t,r+t}if(0===t)return r;this._checkCapacity(r+1);var o=this._front+r&this._capacity-1;return this[o]=e,this._length=r+1,r+1},r.prototype.pop=function(){var e=this._length;if(0===e)return void 0;var t=this._front+e-1&this._capacity-1,r=this[t];return this[t]=void 0,this._length=e-1,r},r.prototype.shift=function(){var e=this._length;if(0===e)return void 0;var t=this._front,r=this[t];return this[t]=void 0,this._front=t+1&this._capacity-1,this._length=e-1,r},r.prototype.unshift=function(e){var t=this._length,r=arguments.length;if(r>1){var n=this._capacity;if(t+r>n){for(var o=r-1;o>=0;o--){this._checkCapacity(t+1);var n=this._capacity,i=(this._front-1&n-1^n)-n;this[i]=arguments[o],t++,this._length=t,this._front=i}return t}for(var s=this._front,o=r-1;o>=0;o--){var i=(s-1&n-1^n)-n;this[i]=arguments[o],s=i}return this._front=s,this._length=t+r,t+r}if(0===r)return t;this._checkCapacity(t+1);var n=this._capacity,o=(this._front-1&n-1^n)-n;return this[o]=e,this._length=t+1,this._front=o,t+1},r.prototype.peekBack=function(){var e=this._length;if(0===e)return void 0;var t=this._front+e-1&this._capacity-1;return this[t]},r.prototype.peekFront=function(){return 0===this._length?void 0:this[this._front] +},r.prototype.get=function(e){var t=e;if(t!==(0|t))return void 0;var r=this._length;return 0>t&&(t+=r),0>t||t>=r?void 0:this[this._front+t&this._capacity-1]},r.prototype.isEmpty=function(){return 0===this._length},r.prototype.clear=function(){this._length=0,this._front=0,this._makeCapacity()},r.prototype.toString=function(){return this.toArray().toString()},r.prototype.valueOf=r.prototype.toString,r.prototype.removeFront=r.prototype.shift,r.prototype.removeBack=r.prototype.pop,r.prototype.insertFront=r.prototype.unshift,r.prototype.insertBack=r.prototype.push,r.prototype.enqueue=r.prototype.push,r.prototype.dequeue=r.prototype.shift,r.prototype.toJSON=r.prototype.toArray,Object.defineProperty(r.prototype,"length",{get:function(){return this._length},set:function(){throw new RangeError("")}}),r.prototype._makeCapacity=function(){for(var e=this._capacity,t=0;e>t;++t)this[t]=void 0},r.prototype._checkCapacity=function(e){this._capacity<e&&this._resizeTo(i(1.5*this._capacity+16))},r.prototype._resizeTo=function(e){var t=this._front,r=this._capacity,o=new Array(r),i=this._length;if(n(this,0,o,0,r),this._capacity=e,this._makeCapacity(),this._front=0,r>=t+i)n(o,t,this,0,i);else{var s=i-(t+i&r-1);n(o,t,this,0,s),n(o,0,this,s,i-s)}};var s=Array.isArray;t.exports=r},{}],44:[function(e,t){t.exports="function"==typeof Object.create?function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:function(e,t){e.super_=t;var r=function(){};r.prototype=t.prototype,e.prototype=new r,e.prototype.constructor=e}},{}],45:[function(e,t){function r(e,t){t||(t={}),this.options=t,o.call(this,e),this._order=t.reverse?"DESC":"ASC",this._limit=t.limit,this._count=0,this._done=!1;var r=i.lowerBound(t),n=i.upperBound(t);this._keyRange=r||n?this.db.makeKeyRange({lower:r,upper:n,excludeLower:i.lowerBoundExclusive(t),excludeUpper:i.upperBoundExclusive(t)}):null,this.callback=null}var n=e("util"),o=e("abstract-leveldown").AbstractIterator,i=e("ltgt");t.exports=r,n.inherits(r,o),r.prototype.createIterator=function(){var e=this;e.iterator=e.db.iterate(function(){e.onItem.apply(e,arguments)},{keyRange:e._keyRange,autoContinue:!1,order:e._order,onError:function(e){console.log("horrible error",e)}})},r.prototype.onItem=function(e,t){if(!t&&this.callback)return this.callback(),void(this.callback=!1);var r=!0;this._limit&&this._limit>0&&this._count++>=this._limit&&(r=!1),r&&this.callback(!1,t.key,t.value),t&&t["continue"]()},r.prototype._next=function(e){return e?(this._started||(this.createIterator(),this._started=!0),void(this.callback=e)):new Error("next() requires a callback argument")}},{"abstract-leveldown":48,ltgt:52,util:39}],46:[function(e,t){(function(e){function r(e){this._db=e,this._operations=[],this._written=!1}r.prototype._checkWritten=function(){if(this._written)throw new Error("write() already called on this batch")},r.prototype.put=function(e,t){this._checkWritten();var r=this._db._checkKeyValue(e,"key",this._db._isBuffer);if(r)throw r;if(r=this._db._checkKeyValue(t,"value",this._db._isBuffer))throw r;return this._db._isBuffer(e)||(e=String(e)),this._db._isBuffer(t)||(t=String(t)),"function"==typeof this._put?this._put(e,t):this._operations.push({type:"put",key:e,value:t}),this},r.prototype.del=function(e){this._checkWritten();var t=this._db._checkKeyValue(e,"key",this._db._isBuffer);if(t)throw t;return this._db._isBuffer(e)||(e=String(e)),"function"==typeof this._del?this._del(e):this._operations.push({type:"del",key:e}),this},r.prototype.clear=function(){return this._checkWritten(),this._operations=[],"function"==typeof this._clear&&this._clear(),this},r.prototype.write=function(t,r){if(this._checkWritten(),"function"==typeof t&&(r=t),"function"!=typeof r)throw new Error("write() requires a callback argument");return"object"!=typeof t&&(t={}),this._written=!0,"function"==typeof this._write?this._write(r):"function"==typeof this._db._batch?this._db._batch(this._operations,t,r):void e.nextTick(r)},t.exports=r}).call(this,e("_process"))},{_process:24}],47:[function(e,t){(function(e){function r(e){this.db=e,this._ended=!1,this._nexting=!1}r.prototype.next=function(t){var r=this;if("function"!=typeof t)throw new Error("next() requires a callback argument");return r._ended?t(new Error("cannot call next() after end()")):r._nexting?t(new Error("cannot call next() before previous next() has completed")):(r._nexting=!0,"function"==typeof r._next?r._next(function(){r._nexting=!1,t.apply(null,arguments)}):void e.nextTick(function(){r._nexting=!1,t()}))},r.prototype.end=function(t){if("function"!=typeof t)throw new Error("end() requires a callback argument");return this._ended?t(new Error("end() already called on iterator")):(this._ended=!0,"function"==typeof this._end?this._end(t):void e.nextTick(t))},t.exports=r}).call(this,e("_process"))},{_process:24}],48:[function(e,t){(function(r,n){function o(e){if(!arguments.length||void 0===e)throw new Error("constructor requires at least a location argument");if("string"!=typeof e)throw new Error("constructor requires a location string argument");this.location=e}var i=e("xtend"),s=e("./abstract-iterator"),a=e("./abstract-chained-batch");o.prototype.open=function(e,t){if("function"==typeof e&&(t=e),"function"!=typeof t)throw new Error("open() requires a callback argument");return"object"!=typeof e&&(e={}),"function"==typeof this._open?this._open(e,t):void r.nextTick(t)},o.prototype.close=function(e){if("function"!=typeof e)throw new Error("close() requires a callback argument");return"function"==typeof this._close?this._close(e):void r.nextTick(e)},o.prototype.get=function(e,t,n){var o;if("function"==typeof t&&(n=t),"function"!=typeof n)throw new Error("get() requires a callback argument");return(o=this._checkKeyValue(e,"key",this._isBuffer))?n(o):(this._isBuffer(e)||(e=String(e)),"object"!=typeof t&&(t={}),"function"==typeof this._get?this._get(e,t,n):void r.nextTick(function(){n(new Error("NotFound"))}))},o.prototype.put=function(e,t,n,o){var i;if("function"==typeof n&&(o=n),"function"!=typeof o)throw new Error("put() requires a callback argument");return(i=this._checkKeyValue(e,"key",this._isBuffer))?o(i):(i=this._checkKeyValue(t,"value",this._isBuffer))?o(i):(this._isBuffer(e)||(e=String(e)),this._isBuffer(t)||r.browser||(t=String(t)),"object"!=typeof n&&(n={}),"function"==typeof this._put?this._put(e,t,n,o):void r.nextTick(o))},o.prototype.del=function(e,t,n){var o;if("function"==typeof t&&(n=t),"function"!=typeof n)throw new Error("del() requires a callback argument");return(o=this._checkKeyValue(e,"key",this._isBuffer))?n(o):(this._isBuffer(e)||(e=String(e)),"object"!=typeof t&&(t={}),"function"==typeof this._del?this._del(e,t,n):void r.nextTick(n))},o.prototype.batch=function(e,t,n){if(!arguments.length)return this._chainedBatch();if("function"==typeof t&&(n=t),"function"!=typeof n)throw new Error("batch(array) requires a callback argument");if(!Array.isArray(e))return n(new Error("batch(array) requires an array argument"));"object"!=typeof t&&(t={});for(var o,i,s=0,a=e.length;a>s;s++)if(o=e[s],"object"==typeof o){if(i=this._checkKeyValue(o.type,"type",this._isBuffer))return n(i);if(i=this._checkKeyValue(o.key,"key",this._isBuffer))return n(i);if("put"==o.type&&(i=this._checkKeyValue(o.value,"value",this._isBuffer)))return n(i)}return"function"==typeof this._batch?this._batch(e,t,n):void r.nextTick(n)},o.prototype.approximateSize=function(e,t,n){if(null==e||null==t||"function"==typeof e||"function"==typeof t)throw new Error("approximateSize() requires valid `start`, `end` and `callback` arguments");if("function"!=typeof n)throw new Error("approximateSize() requires a callback argument");return this._isBuffer(e)||(e=String(e)),this._isBuffer(t)||(t=String(t)),"function"==typeof this._approximateSize?this._approximateSize(e,t,n):void r.nextTick(function(){n(null,0)})},o.prototype._setupIteratorOptions=function(e){var t=this;return e=i(e),["start","end","gt","gte","lt","lte"].forEach(function(r){e[r]&&t._isBuffer(e[r])&&0===e[r].length&&delete e[r]}),e.reverse=!!e.reverse,e.reverse&&e.lt&&(e.start=e.lt),e.reverse&&e.lte&&(e.start=e.lte),!e.reverse&&e.gt&&(e.start=e.gt),!e.reverse&&e.gte&&(e.start=e.gte),(e.reverse&&e.lt&&!e.lte||!e.reverse&&e.gt&&!e.gte)&&(e.exclusiveStart=!0),e},o.prototype.iterator=function(e){return"object"!=typeof e&&(e={}),e=this._setupIteratorOptions(e),"function"==typeof this._iterator?this._iterator(e):new s(this)},o.prototype._chainedBatch=function(){return new a(this)},o.prototype._isBuffer=function(e){return n.isBuffer(e)},o.prototype._checkKeyValue=function(e,t){if(null===e||void 0===e)return new Error(t+" cannot be `null` or `undefined`");if(this._isBuffer(e)){if(0===e.length)return new Error(t+" cannot be an empty Buffer")}else if(""===String(e))return new Error(t+" cannot be an empty String")},t.exports.AbstractLevelDOWN=o,t.exports.AbstractIterator=s,t.exports.AbstractChainedBatch=a}).call(this,e("_process"),e("buffer").Buffer)},{"./abstract-chained-batch":46,"./abstract-iterator":47,_process:24,buffer:17,xtend:49}],49:[function(e,t){function r(){for(var e={},t=0;t<arguments.length;t++){var r=arguments[t];for(var n in r)r.hasOwnProperty(n)&&(e[n]=r[n])}return e}t.exports=r},{}],50:[function(e,t){!function(e,r,n){"function"==typeof define?define(r):"undefined"!=typeof t&&t.exports?t.exports=r():n[e]=r()}("IDBStore",function(){"use strict";var e=function(e){throw e},t={storeName:"Store",storePrefix:"IDBWrapper-",dbVersion:1,keyPath:"id",autoIncrement:!0,onStoreReady:function(){},onError:e,indexes:[]},r=function(e,r){"undefined"==typeof r&&"function"==typeof e&&(r=e),"[object Object]"!=Object.prototype.toString.call(e)&&(e={});for(var n in t)this[n]="undefined"!=typeof e[n]?e[n]:t[n];this.dbName=this.storePrefix+this.storeName,this.dbVersion=parseInt(this.dbVersion,10)||1,r&&(this.onStoreReady=r);var o="object"==typeof window?window:self;this.idb=o.indexedDB||o.webkitIndexedDB||o.mozIndexedDB,this.keyRange=o.IDBKeyRange||o.webkitIDBKeyRange||o.mozIDBKeyRange,this.features={hasAutoIncrement:!o.mozIndexedDB},this.consts={READ_ONLY:"readonly",READ_WRITE:"readwrite",VERSION_CHANGE:"versionchange",NEXT:"next",NEXT_NO_DUPLICATE:"nextunique",PREV:"prev",PREV_NO_DUPLICATE:"prevunique"},this.openDB()};r.prototype={constructor:r,version:"1.4.1",db:null,dbName:null,dbVersion:null,store:null,storeName:null,keyPath:null,autoIncrement:null,indexes:null,features:null,onStoreReady:null,onError:null,_insertIdCount:0,openDB:function(){var e=this.idb.open(this.dbName,this.dbVersion),t=!1;e.onerror=function(e){var t=!1;"error"in e.target?t="VersionError"==e.target.error.name:"errorCode"in e.target&&(t=12==e.target.errorCode),this.onError(t?new Error("The version number provided is lower than the existing one."):e)}.bind(this),e.onsuccess=function(e){if(!t){if(this.db)return void this.onStoreReady();if(this.db=e.target.result,"string"==typeof this.db.version)return void this.onError(new Error("The IndexedDB implementation in this browser is outdated. Please upgrade your browser."));if(!this.db.objectStoreNames.contains(this.storeName))return void this.onError(new Error("Something is wrong with the IndexedDB implementation in this browser. Please upgrade your browser."));var r=this.db.transaction([this.storeName],this.consts.READ_ONLY);this.store=r.objectStore(this.storeName);var n=Array.prototype.slice.call(this.getIndexList());this.indexes.forEach(function(e){var r=e.name;if(!r)return t=!0,void this.onError(new Error("Cannot create index: No index name given."));if(this.normalizeIndexData(e),this.hasIndex(r)){var o=this.store.index(r),i=this.indexComplies(o,e);i||(t=!0,this.onError(new Error('Cannot modify index "'+r+'" for current version. Please bump version number to '+(this.dbVersion+1)+"."))),n.splice(n.indexOf(r),1)}else t=!0,this.onError(new Error('Cannot create new index "'+r+'" for current version. Please bump version number to '+(this.dbVersion+1)+"."))},this),n.length&&(t=!0,this.onError(new Error('Cannot delete index(es) "'+n.toString()+'" for current version. Please bump version number to '+(this.dbVersion+1)+"."))),t||this.onStoreReady()}}.bind(this),e.onupgradeneeded=function(e){if(this.db=e.target.result,this.db.objectStoreNames.contains(this.storeName))this.store=e.target.transaction.objectStore(this.storeName);else{var r={autoIncrement:this.autoIncrement};null!==this.keyPath&&(r.keyPath=this.keyPath),this.store=this.db.createObjectStore(this.storeName,r)}var n=Array.prototype.slice.call(this.getIndexList());this.indexes.forEach(function(e){var r=e.name;if(r||(t=!0,this.onError(new Error("Cannot create index: No index name given."))),this.normalizeIndexData(e),this.hasIndex(r)){var o=this.store.index(r),i=this.indexComplies(o,e);i||(this.store.deleteIndex(r),this.store.createIndex(r,e.keyPath,{unique:e.unique,multiEntry:e.multiEntry})),n.splice(n.indexOf(r),1)}else this.store.createIndex(r,e.keyPath,{unique:e.unique,multiEntry:e.multiEntry})},this),n.length&&n.forEach(function(e){this.store.deleteIndex(e)},this)}.bind(this)},deleteDatabase:function(){this.idb.deleteDatabase&&this.idb.deleteDatabase(this.dbName)},put:function(t,r,o,i){null!==this.keyPath&&(i=o,o=r,r=t),i||(i=e),o||(o=n);var s,a=!1,u=null,c=this.db.transaction([this.storeName],this.consts.READ_WRITE);return c.oncomplete=function(){var e=a?o:i;e(u)},c.onabort=i,c.onerror=i,null!==this.keyPath?(this._addIdPropertyIfNeeded(r),s=c.objectStore(this.storeName).put(r)):s=c.objectStore(this.storeName).put(r,t),s.onsuccess=function(e){a=!0,u=e.target.result},s.onerror=i,c},get:function(t,r,o){o||(o=e),r||(r=n);var i=!1,s=null,a=this.db.transaction([this.storeName],this.consts.READ_ONLY);a.oncomplete=function(){var e=i?r:o;e(s)},a.onabort=o,a.onerror=o;var u=a.objectStore(this.storeName).get(t);return u.onsuccess=function(e){i=!0,s=e.target.result},u.onerror=o,a},remove:function(t,r,o){o||(o=e),r||(r=n);var i=!1,s=null,a=this.db.transaction([this.storeName],this.consts.READ_WRITE);a.oncomplete=function(){var e=i?r:o;e(s)},a.onabort=o,a.onerror=o;var u=a.objectStore(this.storeName)["delete"](t);return u.onsuccess=function(e){i=!0,s=e.target.result},u.onerror=o,a},batch:function(t,r,o){o||(o=e),r||(r=n),"[object Array]"!=Object.prototype.toString.call(t)&&o(new Error("dataArray argument must be of type Array."));var i=this.db.transaction([this.storeName],this.consts.READ_WRITE);i.oncomplete=function(){var e=u?r:o;e(u)},i.onabort=o,i.onerror=o;var s=t.length,a=!1,u=!1,c=function(){s--,0!==s||a||(a=!0,u=!0)};return t.forEach(function(e){var t=e.type,r=e.key,n=e.value,s=function(e){i.abort(),a||(a=!0,o(e,t,r))};if("remove"==t){var u=i.objectStore(this.storeName)["delete"](r);u.onsuccess=c,u.onerror=s}else if("put"==t){var f;null!==this.keyPath?(this._addIdPropertyIfNeeded(n),f=i.objectStore(this.storeName).put(n)):f=i.objectStore(this.storeName).put(n,r),f.onsuccess=c,f.onerror=s}},this),i},putBatch:function(e,t,r){var n=e.map(function(e){return{type:"put",value:e}});return this.batch(n,t,r)},removeBatch:function(e,t,r){var n=e.map(function(e){return{type:"remove",key:e}});return this.batch(n,t,r)},getBatch:function(t,r,o,i){o||(o=e),r||(r=n),i||(i="sparse"),"[object Array]"!=Object.prototype.toString.call(t)&&o(new Error("keyArray argument must be of type Array."));var s=this.db.transaction([this.storeName],this.consts.READ_ONLY);s.oncomplete=function(){var e=f?r:o;e(l)},s.onabort=o,s.onerror=o;var a=[],u=t.length,c=!1,f=!1,l=null,d=function(e){e.target.result||"dense"==i?a.push(e.target.result):"sparse"==i&&a.length++,u--,0===u&&(c=!0,f=!0,l=a)};return t.forEach(function(e){var t=function(e){c=!0,l=e,o(e),s.abort()},r=s.objectStore(this.storeName).get(e);r.onsuccess=d,r.onerror=t},this),s},getAll:function(t,r){r||(r=e),t||(t=n);var o=this.db.transaction([this.storeName],this.consts.READ_ONLY),i=o.objectStore(this.storeName);return i.getAll?this._getAllNative(o,i,t,r):this._getAllCursor(o,i,t,r),o},_getAllNative:function(e,t,r,n){var o=!1,i=null;e.oncomplete=function(){var e=o?r:n;e(i)},e.onabort=n,e.onerror=n;var s=t.getAll();s.onsuccess=function(e){o=!0,i=e.target.result},s.onerror=n},_getAllCursor:function(e,t,r,n){var o=[],i=!1,s=null;e.oncomplete=function(){var e=i?r:n;e(s)},e.onabort=n,e.onerror=n;var a=t.openCursor();a.onsuccess=function(e){var t=e.target.result;t?(o.push(t.value),t["continue"]()):(i=!0,s=o)},a.onError=n},clear:function(t,r){r||(r=e),t||(t=n);var o=!1,i=null,s=this.db.transaction([this.storeName],this.consts.READ_WRITE);s.oncomplete=function(){var e=o?t:r;e(i)},s.onabort=r,s.onerror=r;var a=s.objectStore(this.storeName).clear();return a.onsuccess=function(e){o=!0,i=e.target.result},a.onerror=r,s},_addIdPropertyIfNeeded:function(e){this.features.hasAutoIncrement||"undefined"!=typeof e[this.keyPath]||(e[this.keyPath]=this._insertIdCount++ +Date.now())},getIndexList:function(){return this.store.indexNames},hasIndex:function(e){return this.store.indexNames.contains(e)},normalizeIndexData:function(e){e.keyPath=e.keyPath||e.name,e.unique=!!e.unique,e.multiEntry=!!e.multiEntry},indexComplies:function(e,t){var r=["keyPath","unique","multiEntry"].every(function(r){if("multiEntry"==r&&void 0===e[r]&&t[r]===!1)return!0;if("keyPath"==r&&"[object Array]"==Object.prototype.toString.call(t[r])){var n=t.keyPath,o=e.keyPath;if("string"==typeof o)return n.toString()==o;if("function"!=typeof o.contains&&"function"!=typeof o.indexOf)return!1;if(o.length!==n.length)return!1;for(var i=0,s=n.length;s>i;i++)if(!(o.contains&&o.contains(n[i])||o.indexOf(-1!==n[i])))return!1;return!0}return t[r]==e[r]});return r},iterate:function(t,r){r=i({index:null,order:"ASC",autoContinue:!0,filterDuplicates:!1,keyRange:null,writeAccess:!1,onEnd:null,onError:e},r||{});var n="desc"==r.order.toLowerCase()?"PREV":"NEXT";r.filterDuplicates&&(n+="_NO_DUPLICATE");var o=!1,s=this.db.transaction([this.storeName],this.consts[r.writeAccess?"READ_WRITE":"READ_ONLY"]),a=s.objectStore(this.storeName);r.index&&(a=a.index(r.index)),s.oncomplete=function(){return o?void(r.onEnd?r.onEnd():t(null)):void r.onError(null)},s.onabort=r.onError,s.onerror=r.onError;var u=a.openCursor(r.keyRange,this.consts[n]);return u.onerror=r.onError,u.onsuccess=function(e){var n=e.target.result;n?(t(n.value,n,s),r.autoContinue&&n["continue"]()):o=!0},s},query:function(e,t){var r=[];return t=t||{},t.onEnd=function(){e(r)},this.iterate(function(e){r.push(e)},t)},count:function(t,r){r=i({index:null,keyRange:null},r||{});var n=r.onError||e,o=!1,s=null,a=this.db.transaction([this.storeName],this.consts.READ_ONLY);a.oncomplete=function(){var e=o?t:n;e(s)},a.onabort=n,a.onerror=n;var u=a.objectStore(this.storeName);r.index&&(u=u.index(r.index));var c=u.count(r.keyRange);return c.onsuccess=function(e){o=!0,s=e.target.result},c.onError=n,a},makeKeyRange:function(e){var t,r="undefined"!=typeof e.lower,n="undefined"!=typeof e.upper,o="undefined"!=typeof e.only;switch(!0){case o:t=this.keyRange.only(e.only);break;case r&&n:t=this.keyRange.bound(e.lower,e.upper,e.excludeLower,e.excludeUpper);break;case r:t=this.keyRange.lowerBound(e.lower,e.excludeLower);break;case n:t=this.keyRange.upperBound(e.upper,e.excludeUpper);break;default:throw new Error('Cannot create KeyRange. Provide one or both of "lower" or "upper" value, or an "only" value.')}return t}};var n=function(){},o={},i=function(e,t){var r,n;for(r in t)n=t[r],n!==o[r]&&n!==e[r]&&(e[r]=n);return e};return r.version=r.prototype.version,r},this)},{}],51:[function(e,t){function r(e){return n.isBuffer(e)||/\[object (.+Array|Array.+)\]/.test(Object.prototype.toString.call(e))}var n=e("buffer").Buffer;t.exports=r},{buffer:17}],52:[function(e,t,r){(function(e){function t(e,t){return Object.hasOwnProperty.call(e,t)}function n(e){return void 0!==e&&""!==e}function t(e,t){return Object.hasOwnProperty.call(e,t)}function o(e,t){return Object.hasOwnProperty.call(e,t)&&t}function i(e){return e}r.compare=function(t,r){if(e.isBuffer(t)){for(var n=Math.min(t.length,r.length),o=0;n>o;o++){var i=t[o]-r[o];if(i)return i}return t.length-r.length}return r>t?-1:t>r?1:0};var s=r.lowerBoundKey=function(e){return o(e,"gt")||o(e,"gte")||o(e,"min")||(e.reverse?o(e,"end"):o(e,"start"))||void 0},a=r.lowerBound=function(e){var t=s(e);return t&&e[t]};r.lowerBoundInclusive=function(e){return t(e,"gt")?!1:!0},r.upperBoundInclusive=function(e){return t(e,"lt")||!e.minEx?!1:!0};var u=r.lowerBoundExclusive=function(e){return t(e,"gt")||e.minEx?!0:!1},c=r.upperBoundExclusive=function(e){return t(e,"lt")?!0:!1},f=r.upperBoundKey=function(e){return o(e,"lt")||o(e,"lte")||o(e,"max")||(e.reverse?o(e,"start"):o(e,"end"))||void 0},l=r.upperBound=function(e){var t=f(e);return t&&e[t]};r.toLtgt=function(e,t,n,o,s){t=t||{},n=n||i;var a=arguments.length>3,u=r.lowerBoundKey(e),c=r.upperBoundKey(e);return u?"gt"===u?t.gt=n(e.gt):t.gte=n(e[u]):a&&(t.gte=o),c?"lt"===c?t.lt=n(e.lt):t.lte=n(e[c]):a&&(t.lte=s),t.reverse=!!e.reverse,t},r.contains=function(e,t,o){o=o||r.compare;var i=a(e);if(n(i)){var s=o(t,i);if(0>s||0===s&&u(e))return!1}var f=l(e);if(n(f)){var s=o(t,f);if(s>0||0===s&&c(e))return!1}return!0},r.filter=function(e,t){return function(n){return r.contains(e,n,t)}}}).call(this,e("buffer").Buffer)},{buffer:17}],53:[function(e,t){(function(e){t.exports=function(t){return"function"==typeof e._augment&&e.TYPED_ARRAY_SUPPORT?e._augment(t):new e(t)}}).call(this,e("buffer").Buffer)},{buffer:17}],54:[function(e,t){function r(e){return null!==e&&("object"==typeof e||"function"==typeof e)}t.exports=r},{}],55:[function(e,t){function r(){for(var e={},t=0;t<arguments.length;t++){var r=arguments[t];if(o(r))for(var i=n(r),s=0;s<i.length;s++){var a=i[s];e[a]=r[a]}}return e}var n=e("object-keys"),o=e("./has-keys");t.exports=r},{"./has-keys":54,"object-keys":57}],56:[function(e,t){var r=Object.prototype.hasOwnProperty,n=Object.prototype.toString,o=function(e){var t="function"==typeof e&&!(e instanceof RegExp)||"[object Function]"===n.call(e);return t||"undefined"==typeof window||(t=e===window.setTimeout||e===window.alert||e===window.confirm||e===window.prompt),t};t.exports=function(e,t){if(!o(t))throw new TypeError("iterator must be a function");var n,i,s="string"==typeof e,a=e.length,u=arguments.length>2?arguments[2]:null;if(a===+a)for(n=0;a>n;n++)null===u?t(s?e.charAt(n):e[n],n,e):t.call(u,s?e.charAt(n):e[n],n,e);else for(i in e)r.call(e,i)&&(null===u?t(e[i],i,e):t.call(u,e[i],i,e))}},{}],57:[function(e,t){t.exports=Object.keys||e("./shim")},{"./shim":59}],58:[function(e,t){var r=Object.prototype.toString;t.exports=function n(e){var t=r.call(e),n="[object Arguments]"===t;return n||(n="[object Array]"!==t&&null!==e&&"object"==typeof e&&"number"==typeof e.length&&e.length>=0&&"[object Function]"===r.call(e.callee)),n}},{}],59:[function(e,t){!function(){"use strict";var r,n=Object.prototype.hasOwnProperty,o=Object.prototype.toString,i=e("./foreach"),s=e("./isArguments"),a=!{toString:null}.propertyIsEnumerable("toString"),u=function(){}.propertyIsEnumerable("prototype"),c=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"];r=function(e){var t=null!==e&&"object"==typeof e,r="[object Function]"===o.call(e),f=s(e),l=[];if(!t&&!r&&!f)throw new TypeError("Object.keys called on a non-object");if(f)i(e,function(e){l.push(e)});else{var d,h=u&&r;for(d in e)h&&"prototype"===d||!n.call(e,d)||l.push(d)}if(a){var p=e.constructor,v=p&&p.prototype===e;i(c,function(t){v&&"constructor"===t||!n.call(e,t)||l.push(t)})}return l},t.exports=r}()},{"./foreach":56,"./isArguments":58}],60:[function(e,t){function r(e,t,r,n){var o={type:e,key:t,value:r,options:n};return n&&n.prefix&&(o.prefix=n.prefix,delete n.prefix),this._operations.push(o),this}function n(e){this._operations=[],this._sdb=e,this.put=r.bind(this,"put"),this.del=r.bind(this,"del")}var o=n.prototype;o.clear=function(){this._operations=[]},o.write=function(e){this._sdb.batch(this._operations,e)},t.exports=n},{}],61:[function(e,t){(function(r){var n=(e("events").EventEmitter,r.nextTick,e("./sub")),o=e("./batch"),i=e("level-fix-range"),s=e("level-hooks");t.exports=function(e,t){function r(){}function a(e){return function(t){return t=t||{},t=i(t),t.reverse?t.start=t.start||c:t.end=t.end||c,e.call(u,t)}}r.prototype=e;var u=new r;if(u.sublevel)return u;t=t||{};var c=t.sep=t.sep||"ÿ";u._options=t,s(u),u.sublevels={},u.sublevel=function(e,t){return u.sublevels[e]?u.sublevels[e]:new n(u,e,t||this._options)},u.methods={},u.prefix=function(e){return""+(e||"")},u.pre=function(e,t){return t||(t=e,e={max:c}),u.hooks.pre(e,t)},u.post=function(e,t){return t||(t=e,e={max:c}),u.hooks.post(e,t)},u.readStream=u.createReadStream=a(u.createReadStream),u.keyStream=u.createKeyStream=a(u.createKeyStream),u.valuesStream=u.createValueStream=a(u.createValueStream);var f=u.batch;return u.batch=function(e,t,r){return Array.isArray(e)?(e.forEach(function(e){e.prefix&&("function"==typeof e.prefix.prefix?e.key=e.prefix.prefix(e.key):"string"==typeof e.prefix&&(e.key=e.prefix+e.key))}),void f.call(u,e,t,r)):new o(u)},u}}).call(this,e("_process"))},{"./batch":60,"./sub":72,_process:24,events:21,"level-fix-range":62,"level-hooks":64}],62:[function(e,t){var r=e("clone");t.exports=function(e){e=r(e);var t=e.reverse,n=e.max||e.end,o=e.min||e.start,i=[o,n];return null!=o&&null!=n&&i.sort(),t&&(i=i.reverse()),e.start=i[0],e.end=i[1],delete e.min,delete e.max,e}},{clone:63}],63:[function(e,t){(function(e){"use strict";function r(e){return Object.prototype.toString.call(e)}function n(t,r,n,i){function s(t,n){if(null===t)return null;if(0==n)return t;var f,l;if("object"!=typeof t)return t;if(o.isArray(t))f=[];else if(o.isRegExp(t))f=new RegExp(t.source,o.getRegExpFlags(t)),t.lastIndex&&(f.lastIndex=t.lastIndex);else if(o.isDate(t))f=new Date(t.getTime());else{if(c&&e.isBuffer(t))return f=new e(t.length),t.copy(f),f;"undefined"==typeof i?(l=Object.getPrototypeOf(t),f=Object.create(l)):(f=Object.create(i),l=i)}if(r){var d=a.indexOf(t);if(-1!=d)return u[d];a.push(t),u.push(f)}for(var h in t){var p;l&&(p=Object.getOwnPropertyDescriptor(l,h)),p&&null==p.set||(f[h]=s(t[h],n-1))}return f}var a=[],u=[],c="undefined"!=typeof e;return"undefined"==typeof r&&(r=!0),"undefined"==typeof n&&(n=1/0),s(t,n)}var o={isArray:function(e){return Array.isArray(e)||"object"==typeof e&&"[object Array]"===r(e)},isDate:function(e){return"object"==typeof e&&"[object Date]"===r(e)},isRegExp:function(e){return"object"==typeof e&&"[object RegExp]"===r(e)},getRegExpFlags:function(e){var t="";return e.global&&(t+="g"),e.ignoreCase&&(t+="i"),e.multiline&&(t+="m"),t}};"object"==typeof t&&(t.exports=n),n.clonePrototype=function(e){if(null===e)return null;var t=function(){};return t.prototype=e,new t}}).call(this,e("buffer").Buffer)},{buffer:17}],64:[function(e,t){var r=e("string-range");t.exports=function(e){function t(e){return e&&("string"==typeof e?e:"string"==typeof e.prefix?e.prefix:"function"==typeof e.prefix?e.prefix():"")}function n(e){return e&&e._getKeyEncoding?e._getKeyEncoding(e):void 0}function o(e){return e&&e._getValueEncoding?e._getValueEncoding(e):void 0}function i(e,t){return function(){var r=e.indexOf(t);return~r?(e.splice(r,1),!0):!1}}function s(e){e&&e.type&&u.forEach(function(t){t.test(e.key)&&t.hook(e)})}function a(r,i,s,a){try{i.forEach(function p(e,r){c.forEach(function(s){if(s.test(String(e.key))){var a={add:function(e,a){if("undefined"==typeof e)return this;if(e===!1)return delete i[r];var u=t(e.prefix)||t(a)||s.prefix||"";if(u&&(e.prefix=u),e.key=u+e.key,s.safe&&s.test(String(e.key)))throw new Error("prehook cannot insert into own range");var c=e.keyEncoding||n(e.prefix),f=e.valueEncoding||o(e.prefix);return c&&(e.keyEncoding=c),f&&(e.valueEncoding=f),i.push(e),p(e,i.length-1),this},put:function(e,t){return"object"==typeof e&&(e.type="put"),this.add(e,t)},del:function(e,t){return"object"==typeof e&&(e.type="del"),this.add(e,t)},veto:function(){return this.add(!1)}};s.hook.call(a,e,a.add,i)}})})}catch(u){return(a||s)(u)}if(i=i.filter(function(e){return e&&e.type}),1==i.length&&!r){var h=i[0];return"put"==h.type?f.call(e,h.key,h.value,s,a):l.call(e,h.key,s,a)}return d.call(e,i,s,a)}if(!e.hooks){var u=[],c=[];e.hooks={post:function(e,t){t||(t=e,e="");var n={test:r.checker(e),hook:t};return u.push(n),i(u,n)},pre:function(e,t){t||(t=e,e="");var n={test:r.checker(e),hook:t,safe:!1!==e.safe};return c.push(n),i(c,n)},posthooks:u,prehooks:c},e.on("put",function(e,t){s({type:"put",key:e,value:t})}),e.on("del",function(e,t){s({type:"del",key:e,value:t})}),e.on("batch",function(e){e.forEach(s)});var f=e.put,l=e.del,d=e.batch;e.put=function(e,t,r,n){var o=[{key:e,value:t,type:"put"}];return a(!1,o,r,n)},e.del=function(e,t,r){var n=[{key:e,type:"del"}];return a(!1,n,t,r)},e.batch=function(e,t,r){return a(!0,e,t,r)}}}},{"string-range":65}],65:[function(e,t,r){{var n=r.range=function(e){return null==e?{}:"string"==typeof n?{min:n,max:n+"ÿ"}:e},o=(r.prefix=function(e,t,n){e=r.range(e);var o={};return n=n||"ÿ",e instanceof RegExp||"function"==typeof e?(o.min=t,o.max=t+n,o.inner=function(r){var n=r.substring(t.length);return e.test?e.test(n):e(n)}):"object"==typeof e&&(o.min=t+(e.min||e.start||""),o.max=t+(e.max||e.end||n||"~"),o.reverse=!!e.reverse),o},r.checker=function(e){return e||(e={}),"string"==typeof e?function(t){return 0==t.indexOf(e)}:e instanceof RegExp?function(t){return e.test(t)}:"object"==typeof e?function(t){var r=e.min||e.start,n=e.max||e.end;return t=String(t),(!r||t>=r)&&(!n||n>=t)&&(!e.inner||(e.inner.test?e.inner.test(t):e.inner(t)))}:"function"==typeof e?e:void 0});r.satisfies=function(e,t){return o(t)(e)}}},{}],66:[function(e,t){t.exports=e(54)},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/has-keys.js":54}],67:[function(e,t,r){arguments[4][55][0].apply(r,arguments)},{"./has-keys":66,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/index.js":55,"object-keys":68}],68:[function(e,t,r){arguments[4][57][0].apply(r,arguments)},{"./shim":71,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/index.js":57}],69:[function(e,t){var r=Object.prototype.hasOwnProperty,n=Object.prototype.toString;t.exports=function(e,t,o){if("[object Function]"!==n.call(t))throw new TypeError("iterator must be a function");var i=e.length;if(i===+i)for(var s=0;i>s;s++)t.call(o,e[s],s,e);else for(var a in e)r.call(e,a)&&t.call(o,e[a],a,e)}},{}],70:[function(e,t){var r=Object.prototype,n=r.hasOwnProperty,o=r.toString,i=function(e){return e!==e},s={"boolean":1,number:1,string:1,undefined:1},a=t.exports={};a.a=a.type=function(e,t){return typeof e===t},a.defined=function(e){return void 0!==e},a.empty=function(e){var t,r=o.call(e);if("[object Array]"===r||"[object Arguments]"===r)return 0===e.length;if("[object Object]"===r){for(t in e)if(n.call(e,t))return!1;return!0}return"[object String]"===r?""===e:!1},a.equal=function(e,t){var r,n=o.call(e);if(n!==o.call(t))return!1;if("[object Object]"===n){for(r in e)if(!a.equal(e[r],t[r]))return!1;return!0}if("[object Array]"===n){if(r=e.length,r!==t.length)return!1;for(;--r;)if(!a.equal(e[r],t[r]))return!1;return!0}return"[object Function]"===n?e.prototype===t.prototype:"[object Date]"===n?e.getTime()===t.getTime():e===t},a.hosted=function(e,t){var r=typeof t[e];return"object"===r?!!t[e]:!s[r]},a.instance=a["instanceof"]=function(e,t){return e instanceof t},a["null"]=function(e){return null===e},a.undefined=function(e){return void 0===e},a.arguments=function(e){var t="[object Arguments]"===o.call(e),r=!a.array(e)&&a.arraylike(e)&&a.object(e)&&a.fn(e.callee);return t||r},a.array=function(e){return"[object Array]"===o.call(e)},a.arguments.empty=function(e){return a.arguments(e)&&0===e.length},a.array.empty=function(e){return a.array(e)&&0===e.length},a.arraylike=function(e){return!!e&&!a.boolean(e)&&n.call(e,"length")&&isFinite(e.length)&&a.number(e.length)&&e.length>=0},a.boolean=function(e){return"[object Boolean]"===o.call(e)},a["false"]=function(e){return a.boolean(e)&&(e===!1||e.valueOf()===!1) +},a["true"]=function(e){return a.boolean(e)&&(e===!0||e.valueOf()===!0)},a.date=function(e){return"[object Date]"===o.call(e)},a.element=function(e){return void 0!==e&&"undefined"!=typeof HTMLElement&&e instanceof HTMLElement&&1===e.nodeType},a.error=function(e){return"[object Error]"===o.call(e)},a.fn=a["function"]=function(e){var t="undefined"!=typeof window&&e===window.alert;return t||"[object Function]"===o.call(e)},a.number=function(e){return"[object Number]"===o.call(e)},a.infinite=function(e){return 1/0===e||e===-1/0},a.decimal=function(e){return a.number(e)&&!i(e)&&!a.infinite(e)&&e%1!==0},a.divisibleBy=function(e,t){var r=a.infinite(e),n=a.infinite(t),o=a.number(e)&&!i(e)&&a.number(t)&&!i(t)&&0!==t;return r||n||o&&e%t===0},a.int=function(e){return a.number(e)&&!i(e)&&e%1===0},a.maximum=function(e,t){if(i(e))throw new TypeError("NaN is not a valid value");if(!a.arraylike(t))throw new TypeError("second argument must be array-like");for(var r=t.length;--r>=0;)if(e<t[r])return!1;return!0},a.minimum=function(e,t){if(i(e))throw new TypeError("NaN is not a valid value");if(!a.arraylike(t))throw new TypeError("second argument must be array-like");for(var r=t.length;--r>=0;)if(e>t[r])return!1;return!0},a.nan=function(e){return!a.number(e)||e!==e},a.even=function(e){return a.infinite(e)||a.number(e)&&e===e&&e%2===0},a.odd=function(e){return a.infinite(e)||a.number(e)&&e===e&&e%2!==0},a.ge=function(e,t){if(i(e)||i(t))throw new TypeError("NaN is not a valid value");return!a.infinite(e)&&!a.infinite(t)&&e>=t},a.gt=function(e,t){if(i(e)||i(t))throw new TypeError("NaN is not a valid value");return!a.infinite(e)&&!a.infinite(t)&&e>t},a.le=function(e,t){if(i(e)||i(t))throw new TypeError("NaN is not a valid value");return!a.infinite(e)&&!a.infinite(t)&&t>=e},a.lt=function(e,t){if(i(e)||i(t))throw new TypeError("NaN is not a valid value");return!a.infinite(e)&&!a.infinite(t)&&t>e},a.within=function(e,t,r){if(i(e)||i(t)||i(r))throw new TypeError("NaN is not a valid value");if(!a.number(e)||!a.number(t)||!a.number(r))throw new TypeError("all arguments must be numbers");var n=a.infinite(e)||a.infinite(t)||a.infinite(r);return n||e>=t&&r>=e},a.object=function(e){return e&&"[object Object]"===o.call(e)},a.hash=function(e){return a.object(e)&&e.constructor===Object&&!e.nodeType&&!e.setInterval},a.regexp=function(e){return"[object RegExp]"===o.call(e)},a.string=function(e){return"[object String]"===o.call(e)}},{}],71:[function(e,t){!function(){"use strict";var r,n=Object.prototype.hasOwnProperty,o=e("is"),i=e("foreach"),s=!{toString:null}.propertyIsEnumerable("toString"),a=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"];r=function(e){if(!o.object(e)&&!o.array(e))throw new TypeError("Object.keys called on a non-object");var t,r=[];for(t in e)n.call(e,t)&&r.push(t);return s&&i(a,function(t){n.call(e,t)&&r.push(t)}),r},t.exports=r}()},{foreach:69,is:70}],72:[function(e,t){function r(e,t,n){if("string"==typeof n&&(console.error("db.sublevel(name, seperator<string>) is depreciated"),console.error("use db.sublevel(name, {sep: separator})) if you must"),n={sep:n}),!(this instanceof r))return new r(e,t,n);if(!e)throw new Error("must provide db");if(!t)throw new Error("must provide prefix");n=n||{},n.sep=n.sep||"ÿ",this._parent=e,this._options=n,this.options=n,this._prefix=t,this._root=o(this),e.sublevels[t]=this,this.sublevels={},this.methods={};var i=this;this.hooks={pre:function(){return i.pre.apply(i,arguments)},post:function(){return i.post.apply(i,arguments)}}}function n(e,t){["valueEncoding","encoding","keyEncoding","reverse","values","keys","limit","fillCache"].forEach(function(r){t.hasOwnProperty(r)&&(e[r]=t[r])})}function o(e){return e._parent?o(e._parent):e}var i=e("events").EventEmitter,s=e("util").inherits,a=e("string-range"),u=e("level-fix-range"),c=e("xtend"),f=e("./batch");s(r,i);var l=r.prototype;l._key=function(e){var t=this._options.sep;return t+this._prefix+t+e},l._getOptsAndCb=function(e,t){return"function"==typeof e&&(t=e,e={}),{opts:c(e,this._options),cb:t}},l.sublevel=function(e,t){return this.sublevels[e]?this.sublevels[e]:new r(this,e,t||this._options)},l.put=function(e,t,r,n){var o=this._getOptsAndCb(r,n);this._root.put(this.prefix(e),t,o.opts,o.cb)},l.get=function(e,t,r){var n=this._getOptsAndCb(t,r);this._root.get(this.prefix(e),n.opts,n.cb)},l.del=function(e,t,r){var n=this._getOptsAndCb(t,r);this._root.del(this.prefix(e),n.opts,n.cb)},l.batch=function(e,t,r){if(!Array.isArray(e))return new f(this);var n=this,o=this._getOptsAndCb(t,r);e.forEach(function(e){e.key="string"==typeof e.prefix?e.prefix+e.key:(e.prefix||n).prefix(e.key),e.prefix&&(e.prefix=null)}),this._root.batch(e,o.opts,o.cb)},l._getKeyEncoding=function(){return this.options.keyEncoding?this.options.keyEncoding:this._parent&&this._parent._getKeyEncoding?this._parent._getKeyEncoding():void 0},l._getValueEncoding=function(){return this.options.valueEncoding?this.options.valueEncoding:this._parent&&this._parent._getValueEncoding?this._parent._getValueEncoding():void 0},l.prefix=function(e){var t=this._options.sep;return this._parent.prefix()+t+this._prefix+t+(e||"")},l.keyStream=l.createKeyStream=function(e){return e=e||{},e.keys=!0,e.values=!1,this.createReadStream(e)},l.valueStream=l.createValueStream=function(e){return e=e||{},e.keys=!1,e.values=!0,e.keys=!1,this.createReadStream(e)},l.readStream=l.createReadStream=function(e){e=e||{};var t=o(this),r=this.prefix(),i=a.prefix(e,r);n(i,c(e,this._options));var s=t.createReadStream(i);if(i.values===!1){var u=s.read;if(u)s.read=function(e){var t=u.call(this,e);return t&&(t=t.substring(r.length)),t};else{var f=s.emit;s.emit=function(e,t){"data"===e?f.call(this,"data",t.substring(r.length)):f.call(this,e,t)}}return s}if(i.keys===!1)return s;var u=s.read;return u?s.read=function(e){var t=u.call(this,e);return t&&(t.key=t.key.substring(r.length)),t}:s.on("data",function(e){e.key=e.key.substring(r.length)}),s},l.writeStream=l.createWriteStream=function(){var e=o(this),t=this.prefix(),r=e.createWriteStream.apply(e,arguments),n=r.write,i=this._options.encoding,s=this._options.valueEncoding,a=this._options.keyEncoding,u=!i&&!s&&!a;return r.write=u?function(e){return e.key=t+e.key,n.call(r,e)}:function(e){return e.key=t+e.key,i&&"undefined"==typeof e.encoding&&(e.encoding=i),s&&"undefined"==typeof e.valueEncoding&&(e.valueEncoding=s),a&&"undefined"==typeof e.keyEncoding&&(e.keyEncoding=a),n.call(r,e)},r},l.approximateSize=function(){var e=o(db);return e.approximateSize.apply(e,arguments)},l.pre=function(e,t){t||(t=e,e=null),e=a.prefix(e,this.prefix(),this._options.sep);var r=o(this._parent),n=this.prefix();return r.hooks.pre(u(e),function(e,r,o){t({key:e.key.substring(n.length),value:e.value,type:e.type},function(e,t){r(e,e.prefix?t:t||n)},o)})},l.post=function(e,t){t||(t=e,e=null);var r=o(this._parent),n=this.prefix();return e=a.prefix(e,n,this._options.sep),r.hooks.post(u(e),function(e){t({key:e.key.substring(n.length),value:e.value,type:e.type})})};t.exports=r},{"./batch":60,events:21,"level-fix-range":62,"string-range":65,util:39,xtend:67}],73:[function(e,t){function r(e){this._levelup=e,this.batch=e.db.batch(),this.ops=[]}var n=e("./util"),o=e("./errors").WriteError,i=n.getOptions,s=n.dispatchError;r.prototype.put=function(e,t,r){r=i(this._levelup,r);var s=n.encodeKey(e,r),a=n.encodeValue(t,r);try{this.batch.put(s,a)}catch(u){throw new o(u)}return this.ops.push({type:"put",key:s,value:a}),this},r.prototype.del=function(e,t){t=i(this._levelup,t);var r=n.encodeKey(e,t);try{this.batch.del(r)}catch(s){throw new o(s)}return this.ops.push({type:"del",key:r}),this},r.prototype.clear=function(){try{this.batch.clear()}catch(e){throw new o(e)}return this.ops=[],this},r.prototype.write=function(e){var t=this._levelup,r=this.ops;try{this.batch.write(function(n){return n?s(t,new o(n),e):(t.emit("batch",r),void(e&&e()))})}catch(n){throw new o(n)}},t.exports=r},{"./errors":74,"./util":77}],74:[function(e,t){var r=e("errno").create,n=r("LevelUPError"),o=r("NotFoundError",n);o.prototype.notFound=!0,o.prototype.status=404,t.exports={LevelUPError:n,InitializationError:r("InitializationError",n),OpenError:r("OpenError",n),ReadError:r("ReadError",n),WriteError:r("WriteError",n),NotFoundError:o,EncodingError:r("EncodingError",n)}},{errno:85}],75:[function(e,t){(function(r){function n(e,t){return"function"==typeof e?e:t}function o(e,t,n){if(!(this instanceof o))return new o(e,t,n);var i;if(s.call(this),this.setMaxListeners(1/0),"function"==typeof e?(t="object"==typeof t?t:{},t.db=e,e=null):"object"==typeof e&&"function"==typeof e.db&&(t=e,e=null),"function"==typeof t&&(n=t,t={}),(!t||"function"!=typeof t.db)&&"string"!=typeof e){if(i=new y("Must provide a location for the database"),n)return r.nextTick(function(){n(i)});throw i}t=w(this,t),this.options=u(E,t),this._status="new",c(this,"location",e,"e"),this.open(n)}function i(e){return function(t,r){x()[e](t,r||function(){})}}var s=e("events").EventEmitter,a=e("util").inherits,u=e("xtend"),c=e("prr"),f=e("deferred-leveldown"),l=e("./errors").WriteError,d=e("./errors").ReadError,h=e("./errors").NotFoundError,p=e("./errors").OpenError,v=e("./errors").EncodingError,y=e("./errors").InitializationError,g=e("./read-stream"),m=e("./write-stream"),b=e("./util"),_=e("./batch"),w=b.getOptions,E=b.defaultOptions,x=b.getLevelDOWN,k=b.dispatchError;a(o,s),o.prototype.open=function(e){var t,n,o=this;return this.isOpen()?(e&&r.nextTick(function(){e(null,o)}),this):this._isOpening()?e&&this.once("open",function(){e(null,o)}):(this.emit("opening"),this._status="opening",this.db=new f(this.location),t=this.options.db||x(),n=t(this.location),void n.open(this.options,function(t){return t?k(o,new p(t),e):(o.db.setDb(n),o.db=n,o._status="open",e&&e(null,o),o.emit("open"),o.emit("ready"),void 0)}))},o.prototype.close=function(e){var t=this;if(this.isOpen())this._status="closing",this.db.close(function(){t._status="closed",t.emit("closed"),e&&e.apply(null,arguments)}),this.emit("closing"),this.db=null;else{if("closed"==this._status&&e)return r.nextTick(e);"closing"==this._status&&e?this.once("closed",e):this._isOpening()&&this.once("open",function(){t.close(e)})}},o.prototype.isOpen=function(){return"open"==this._status},o.prototype._isOpening=function(){return"opening"==this._status},o.prototype.isClosed=function(){return/^clos/.test(this._status)},o.prototype.get=function(e,t,r){var o,i=this;return r=n(t,r),"function"!=typeof r?k(this,new d("get() requires key and callback arguments")):this._isOpening()||this.isOpen()?(t=b.getOptions(this,t),o=b.encodeKey(e,t),t.asBuffer=b.isValueAsBuffer(t),void this.db.get(o,t,function(n,o){if(n)return n=/notfound/i.test(n)?new h("Key not found in database ["+e+"]",n):new d(n),k(i,n,r);if(r){try{o=b.decodeValue(o,t)}catch(s){return r(new v(s))}r(null,o)}})):k(this,new d("Database is not open"),r)},o.prototype.put=function(e,t,r,o){var i,s,a=this;return o=n(r,o),null===e||void 0===e||null===t||void 0===t?k(this,new l("put() requires key and value arguments"),o):this._isOpening()||this.isOpen()?(r=w(this,r),i=b.encodeKey(e,r),s=b.encodeValue(t,r),void this.db.put(i,s,r,function(r){return r?k(a,new l(r),o):(a.emit("put",e,t),void(o&&o()))})):k(this,new l("Database is not open"),o)},o.prototype.del=function(e,t,r){var o,i=this;return r=n(t,r),null===e||void 0===e?k(this,new l("del() requires a key argument"),r):this._isOpening()||this.isOpen()?(t=w(this,t),o=b.encodeKey(e,t),void this.db.del(o,t,function(t){return t?k(i,new l(t),r):(i.emit("del",e),void(r&&r()))})):k(this,new l("Database is not open"),r)},o.prototype.batch=function(e,t,r){var o,i,s,a=this;return arguments.length?(r=n(t,r),Array.isArray(e)?this._isOpening()||this.isOpen()?(t=w(this,t),o=t.keyEncoding,i=t.valueEncoding,s=e.map(function(e){if(void 0===e.type||void 0===e.key)return{};var r,n=e.keyEncoding||o,s=e.valueEncoding||e.encoding||i;return"utf8"!=n&&"binary"!=n||"utf8"!=s&&"binary"!=s?(r={type:e.type,key:b.encodeKey(e.key,t,e)},void 0!==e.value&&(r.value=b.encodeValue(e.value,t,e)),r):e}),void this.db.batch(s,t,function(t){return t?k(a,new l(t),r):(a.emit("batch",e),void(r&&r()))})):k(this,new l("Database is not open"),r):k(this,new l("batch() requires an array argument"),r)):new _(this)},o.prototype.approximateSize=function(e,t,r){var n,o,i=this;return null===e||void 0===e||null===t||void 0===t||"function"!=typeof r?k(this,new d("approximateSize() requires start, end and callback arguments"),r):(n=b.encodeKey(e,this.options),o=b.encodeKey(t,this.options),this._isOpening()||this.isOpen()?void this.db.approximateSize(n,o,function(e,t){return e?k(i,new p(e),r):void(r&&r(null,t))}):k(this,new l("Database is not open"),r))},o.prototype.readStream=o.prototype.createReadStream=function(e){var t=this;return e=u(this.options,e),new g(e,this,function(e){return t.db.iterator(e)})},o.prototype.keyStream=o.prototype.createKeyStream=function(e){return this.createReadStream(u(e,{keys:!0,values:!1}))},o.prototype.valueStream=o.prototype.createValueStream=function(e){return this.createReadStream(u(e,{keys:!1,values:!0}))},o.prototype.writeStream=o.prototype.createWriteStream=function(e){return new m(u(e),this)},o.prototype.toString=function(){return"LevelUP"},t.exports=o,t.exports.copy=b.copy,t.exports.destroy=i("destroy"),t.exports.repair=i("repair")}).call(this,e("_process"))},{"./batch":73,"./errors":74,"./read-stream":76,"./util":77,"./write-stream":78,_process:24,"deferred-leveldown":80,events:21,prr:86,util:39,xtend:96}],76:[function(e,t){function r(e,t,o){if(!(this instanceof r))return new r(e,t,o);n.call(this,{objectMode:!0,highWaterMark:e.highWaterMark}),this._db=t,e=this._options=i(u,e),this._keyEncoding=e.keyEncoding||e.encoding,this._valueEncoding=e.valueEncoding||e.encoding,"undefined"!=typeof this._options.start&&(this._options.start=a.encodeKey(this._options.start,this._options)),"undefined"!=typeof this._options.end&&(this._options.end=a.encodeKey(this._options.end,this._options)),"number"!=typeof this._options.limit&&(this._options.limit=-1),this._options.keyAsBuffer=a.isKeyAsBuffer(this._options),this._options.valueAsBuffer=a.isValueAsBuffer(this._options),this._makeData=this._options.keys&&this._options.values?c:this._options.keys?f:this._options.values?l:d;var s=this;this._db.isOpen()?this._iterator=o(this._options):this._db.once("ready",function(){s._destroyed||(s._iterator=o(s._options))})}var n=e("readable-stream").Readable,o=e("util").inherits,i=e("xtend"),s=e("./errors").EncodingError,a=e("./util"),u={keys:!0,values:!0},c=function(e,t){return{key:a.decodeKey(e,this._options),value:a.decodeValue(t,this._options)}},f=function(e){return a.decodeKey(e,this._options)},l=function(e,t){return a.decodeValue(t,this._options)},d=function(){return null};o(r,n),r.prototype._read=function h(){var e=this;return e._db.isOpen()?void(e._destroyed||e._iterator.next(function(t,r,n){if(t||void 0===r&&void 0===n)return t||e._destroyed||e.push(null),e._cleanup(t);try{n=e._makeData(r,n)}catch(o){return e._cleanup(new s(o))}e._destroyed||e.push(n)})):e._db.once("ready",function(){h.call(e)})},r.prototype._cleanup=function(e){if(!this._destroyed){this._destroyed=!0;var t=this;e&&t.emit("error",e),t._iterator?t._iterator.end(function(){t._iterator=null,t.emit("close")}):t.emit("close")}},r.prototype.destroy=function(){this._cleanup()},r.prototype.toString=function(){return"LevelUP.ReadStream"},t.exports=r},{"./errors":74,"./util":77,"readable-stream":95,util:39,xtend:96}],77:[function(e,t){(function(r,n){function o(e,t,r){e.readStream().pipe(t.writeStream()).on("close",r?r:function(){}).on("error",r?r:function(e){throw e})}function i(e,t){var r="string"==typeof t;return!r&&t&&t.encoding&&!t.valueEncoding&&(t.valueEncoding=t.encoding),g(e&&e.options||{},r?E[t]||E[_.valueEncoding]:t)}function s(){if(y)return y;var t,r=e("../package.json").devDependencies.leveldown,n="Could not locate LevelDOWN, try `npm install leveldown`";try{t=e("leveldown/package").version}catch(o){throw new m(n)}if(!e("semver").satisfies(t,r))throw new m("Installed version of LevelDOWN ("+t+") does not match required version ("+r+")");try{return y=e("leveldown")}catch(o){throw new m(n)}}function a(e,t,r){return"function"==typeof r?r(t):e.emit("error",t)}function u(e,t){var r=t&&t.keyEncoding||e.keyEncoding||"utf8";return w[r]||r}function c(e,t){var r=t&&(t.valueEncoding||t.encoding)||e.valueEncoding||e.encoding||"utf8";return w[r]||r}function f(e,t,r){return u(t,r).encode(e)}function l(e,t,r){return c(t,r).encode(e)}function d(e,t){return u(t).decode(e)}function h(e,t){return c(t).decode(e)}function p(e,t){return c(e,t).buffer}function v(e,t){return u(e,t).buffer}var y,g=e("xtend"),m=e("./errors").LevelUPError,b=["hex","utf8","utf-8","ascii","binary","base64","ucs2","ucs-2","utf16le","utf-16le"],_={createIfMissing:!0,errorIfExists:!1,keyEncoding:"utf8",valueEncoding:"utf8",compression:!0},w=function(){function e(e){return void 0===e||null===e||n.isBuffer(e)}var t={};return t.utf8=t["utf-8"]={encode:function(t){return e(t)?t:String(t)},decode:function(e){return e},buffer:!1,type:"utf8"},t.json={encode:JSON.stringify,decode:JSON.parse,buffer:!1,type:"json"},b.forEach(function(o){t[o]||(t[o]={encode:function(t){return e(t)?t:new n(t,o)},decode:function(e){return r.browser?e.toString(o):e},buffer:!0,type:o})}),t}(),E=function(){var e={};return b.forEach(function(t){e[t]={valueEncoding:t}}),e}();t.exports={defaultOptions:_,copy:o,getOptions:i,getLevelDOWN:s,dispatchError:a,encodeKey:f,encodeValue:l,isValueAsBuffer:p,isKeyAsBuffer:v,decodeValue:h,decodeKey:d}}).call(this,e("_process"),e("buffer").Buffer)},{"../package.json":97,"./errors":74,_process:24,buffer:17,leveldown:"leveldown","leveldown/package":16,semver:16,xtend:96}],78:[function(e,t){(function(r,n){function o(e,t){if(!(this instanceof o))return new o(e,t);i.call(this),this._options=a(l,f(t,e)),this._db=t,this._buffer=[],this._status="init",this._end=!1,this.writable=!0,this.readable=!1;var r=this,n=function(){r.writable&&(r._status="ready",r.emit("ready"),r._process())};t.isOpen()?c(n):t.once("ready",n)}var i=e("stream").Stream,s=e("util").inherits,a=e("xtend"),u=e("bl"),c=n.setImmediate||r.nextTick,f=e("./util").getOptions,l={type:"put"};s(o,i),o.prototype.write=function(e){return this.writable?(this._buffer.push(e),"init"!=this._status&&this._processDelayed(),this._options.maxBufferLength&&this._buffer.length>this._options.maxBufferLength?(this._writeBlock=!0,!1):!0):!1},o.prototype.end=function(e){var t=this;e&&this.write(e),c(function(){t._end=!0,t._process()})},o.prototype.destroy=function(){this.writable=!1,this.end()},o.prototype.destroySoon=function(){this.end()},o.prototype.add=function(e){return e.props?(e.props.Directory?e.pipe(this._db.writeStream(this._options)):(e.props.File||e.File||"File"==e.type)&&this._write(e),!0):void 0},o.prototype._processDelayed=function(){var e=this;c(function(){e._process()})},o.prototype._process=function(){var e,t=this,r=function(e){return t.writable?("closed"!=t._status&&(t._status="ready"),e?(t.writable=!1,t.emit("error",e)):void t._process()):void 0};return"ready"!=t._status&&t.writable?void(t._buffer.length&&"closed"!=t._status&&t._processDelayed()):t._buffer.length&&t.writable?(t._status="writing",e=t._buffer,t._buffer=[],t._db.batch(e.map(function(e){return{type:e.type||t._options.type,key:e.key,value:e.value,keyEncoding:e.keyEncoding||t._options.keyEncoding,valueEncoding:e.valueEncoding||e.encoding||t._options.valueEncoding}}),r),void(t._writeBlock&&(t._writeBlock=!1,t.emit("drain")))):void(t._end&&"closed"!=t._status&&(t._status="closed",t.writable=!1,t.emit("close")))},o.prototype._write=function(e){var t=e.path||e.props.path,r=this;t&&e.pipe(u(function(e,n){return e?(r.writable=!1,r.emit("error",e)):(r._options.fstreamRoot&&t.indexOf(r._options.fstreamRoot)>-1&&(t=t.substr(r._options.fstreamRoot.length+1)),void r.write({key:t,value:n.slice(0)}))}))},o.prototype.toString=function(){return"LevelUP.WriteStream"},t.exports=o}).call(this,e("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./util":77,_process:24,bl:79,stream:36,util:39,xtend:96}],79:[function(e,t){(function(r){function n(e){if(!(this instanceof n))return new n(e);if(this._bufs=[],this.length=0,"function"==typeof e){this._callback=e;var t=function(e){this._callback&&(this._callback(e),this._callback=null)}.bind(this);this.on("pipe",function(e){e.on("error",t)}),this.on("unpipe",function(e){e.removeListener("error",t)})}else r.isBuffer(e)?this.append(e):Array.isArray(e)&&e.forEach(function(e){r.isBuffer(e)&&this.append(e)}.bind(this));o.call(this)}var o=e("readable-stream").Duplex,i=e("util");i.inherits(n,o),n.prototype._offset=function(e){for(var t,r=0,n=0;n<this._bufs.length;n++){if(t=r+this._bufs[n].length,t>e)return[n,e-r];r=t}},n.prototype.append=function(e){return this._bufs.push(r.isBuffer(e)?e:new r(e)),this.length+=e.length,this},n.prototype._write=function(e,t,r){this.append(e),r&&r()},n.prototype._read=function(e){return this.length?(e=Math.min(e,this.length),this.push(this.slice(0,e)),void this.consume(e)):this.push(null)},n.prototype.end=function(e){o.prototype.end.call(this,e),this._callback&&(this._callback(null,this.slice()),this._callback=null)},n.prototype.get=function(e){return this.slice(e,e+1)[0]},n.prototype.slice=function(e,t){return this.copy(null,0,e,t)},n.prototype.copy=function(e,t,n,o){if(("number"!=typeof n||0>n)&&(n=0),("number"!=typeof o||o>this.length)&&(o=this.length),n>=this.length)return e||new r(0);if(0>=o)return e||new r(0);var i,s,a=!!e,u=this._offset(n),c=o-n,f=c,l=a&&t||0,d=u[1];if(0===n&&o==this.length){if(!a)return r.concat(this._bufs);for(s=0;s<this._bufs.length;s++)this._bufs[s].copy(e,l),l+=this._bufs[s].length;return e}if(f<=this._bufs[u[0]].length-d)return a?this._bufs[u[0]].copy(e,t,d,d+f):this._bufs[u[0]].slice(d,d+f);for(a||(e=new r(c)),s=u[0];s<this._bufs.length;s++){if(i=this._bufs[s].length-d,!(f>i)){this._bufs[s].copy(e,l,d,d+f);break}this._bufs[s].copy(e,l,d),l+=i,f-=i,d&&(d=0)}return e},n.prototype.toString=function(e,t,r){return this.slice(t,r).toString(e)},n.prototype.consume=function(e){for(;this._bufs.length;){if(!(e>this._bufs[0].length)){this._bufs[0]=this._bufs[0].slice(e),this.length-=e;break}e-=this._bufs[0].length,this.length-=this._bufs[0].length,this._bufs.shift()}return this},n.prototype.duplicate=function(){for(var e=0,t=new n;e<this._bufs.length;e++)t.append(this._bufs[e]);return t},n.prototype.destroy=function(){this._bufs.length=0,this.length=0,this.push(null)},function(){var e={readDoubleBE:8,readDoubleLE:8,readFloatBE:4,readFloatLE:4,readInt32BE:4,readInt32LE:4,readUInt32BE:4,readUInt32LE:4,readInt16BE:2,readInt16LE:2,readUInt16BE:2,readUInt16LE:2,readInt8:1,readUInt8:1};for(var t in e)!function(t){n.prototype[t]=function(r){return this.slice(r,r+e[t])[t](0)}}(t)}(),t.exports=n}).call(this,e("buffer").Buffer)},{buffer:17,"readable-stream":95,util:39}],80:[function(e,t){(function(r,n){function o(e){s.call(this,"string"==typeof e?e:""),this._db=void 0,this._operations=[]}var i=e("util"),s=e("abstract-leveldown").AbstractLevelDOWN;i.inherits(o,s),o.prototype.setDb=function(e){this._db=e,this._operations.forEach(function(t){e[t.method].apply(e,t.args)})},o.prototype._open=function(e,t){return r.nextTick(t)},o.prototype._operation=function(e,t){return this._db?this._db[e].apply(this._db,t):void this._operations.push({method:e,args:t})},"put get del batch approximateSize".split(" ").forEach(function(e){o.prototype["_"+e]=function(){this._operation(e,arguments)}}),o.prototype._isBuffer=function(e){return n.isBuffer(e)},o.prototype._iterator=function(){throw new TypeError("not implemented")},t.exports=o}).call(this,e("_process"),e("buffer").Buffer)},{_process:24,"abstract-leveldown":83,buffer:17,util:39}],81:[function(e,t){t.exports=e(46)},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/abstract-leveldown/abstract-chained-batch.js":46,_process:24}],82:[function(e,t){t.exports=e(47)},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/abstract-leveldown/abstract-iterator.js":47,_process:24}],83:[function(e,t){t.exports=e(48)},{"./abstract-chained-batch":81,"./abstract-iterator":82,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/abstract-leveldown/abstract-leveldown.js":48,_process:24,buffer:17,xtend:96}],84:[function(e,t){function r(e,t,r){i(this,{type:e,name:e,cause:"string"!=typeof t?t:r,message:t&&"string"!=typeof t?t.message:t},"ewr")}function n(e,t){Error.call(this),Error.captureStackTrace&&Error.captureStackTrace(this,arguments.callee),r.call(this,"CustomError",e,t)}function o(e,t,o){var i=function(n,o){r.call(this,t,n,o),"FilesystemError"==t&&(this.code=this.cause.code,this.path=this.cause.path,this.errno=this.cause.errno,this.message=(e.errno[this.cause.errno]?e.errno[this.cause.errno].description:this.cause.message)+(this.cause.path?" ["+this.cause.path+"]":"")),Error.call(this),Error.captureStackTrace&&Error.captureStackTrace(this,arguments.callee)};return i.prototype=o?new o:new n,i}var i=e("prr");n.prototype=new Error,t.exports=function(e){var t=function(t,r){return o(e,t,r)};return{CustomError:n,FilesystemError:t("FilesystemError"),createError:t}}},{prr:86}],85:[function(e,t){var r=t.exports.all=[{errno:-1,code:"UNKNOWN",description:"unknown error"},{errno:0,code:"OK",description:"success"},{errno:1,code:"EOF",description:"end of file"},{errno:2,code:"EADDRINFO",description:"getaddrinfo error"},{errno:3,code:"EACCES",description:"permission denied"},{errno:4,code:"EAGAIN",description:"resource temporarily unavailable"},{errno:5,code:"EADDRINUSE",description:"address already in use"},{errno:6,code:"EADDRNOTAVAIL",description:"address not available"},{errno:7,code:"EAFNOSUPPORT",description:"address family not supported"},{errno:8,code:"EALREADY",description:"connection already in progress"},{errno:9,code:"EBADF",description:"bad file descriptor"},{errno:10,code:"EBUSY",description:"resource busy or locked"},{errno:11,code:"ECONNABORTED",description:"software caused connection abort"},{errno:12,code:"ECONNREFUSED",description:"connection refused"},{errno:13,code:"ECONNRESET",description:"connection reset by peer"},{errno:14,code:"EDESTADDRREQ",description:"destination address required"},{errno:15,code:"EFAULT",description:"bad address in system call argument"},{errno:16,code:"EHOSTUNREACH",description:"host is unreachable"},{errno:17,code:"EINTR",description:"interrupted system call"},{errno:18,code:"EINVAL",description:"invalid argument"},{errno:19,code:"EISCONN",description:"socket is already connected"},{errno:20,code:"EMFILE",description:"too many open files"},{errno:21,code:"EMSGSIZE",description:"message too long"},{errno:22,code:"ENETDOWN",description:"network is down"},{errno:23,code:"ENETUNREACH",description:"network is unreachable"},{errno:24,code:"ENFILE",description:"file table overflow"},{errno:25,code:"ENOBUFS",description:"no buffer space available"},{errno:26,code:"ENOMEM",description:"not enough memory"},{errno:27,code:"ENOTDIR",description:"not a directory"},{errno:28,code:"EISDIR",description:"illegal operation on a directory"},{errno:29,code:"ENONET",description:"machine is not on the network"},{errno:31,code:"ENOTCONN",description:"socket is not connected"},{errno:32,code:"ENOTSOCK",description:"socket operation on non-socket"},{errno:33,code:"ENOTSUP",description:"operation not supported on socket"},{errno:34,code:"ENOENT",description:"no such file or directory"},{errno:35,code:"ENOSYS",description:"function not implemented"},{errno:36,code:"EPIPE",description:"broken pipe"},{errno:37,code:"EPROTO",description:"protocol error"},{errno:38,code:"EPROTONOSUPPORT",description:"protocol not supported"},{errno:39,code:"EPROTOTYPE",description:"protocol wrong type for socket"},{errno:40,code:"ETIMEDOUT",description:"connection timed out"},{errno:41,code:"ECHARSET",description:"invalid Unicode character"},{errno:42,code:"EAIFAMNOSUPPORT",description:"address family for hostname not supported"},{errno:44,code:"EAISERVICE",description:"servname not supported for ai_socktype"},{errno:45,code:"EAISOCKTYPE",description:"ai_socktype not supported"},{errno:46,code:"ESHUTDOWN",description:"cannot send after transport endpoint shutdown"},{errno:47,code:"EEXIST",description:"file already exists"},{errno:48,code:"ESRCH",description:"no such process"},{errno:49,code:"ENAMETOOLONG",description:"name too long"},{errno:50,code:"EPERM",description:"operation not permitted"},{errno:51,code:"ELOOP",description:"too many symbolic links encountered"},{errno:52,code:"EXDEV",description:"cross-device link not permitted"},{errno:53,code:"ENOTEMPTY",description:"directory not empty"},{errno:54,code:"ENOSPC",description:"no space left on device"},{errno:55,code:"EIO",description:"i/o error"},{errno:56,code:"EROFS",description:"read-only file system"},{errno:57,code:"ENODEV",description:"no such device"},{errno:58,code:"ESPIPE",description:"invalid seek"},{errno:59,code:"ECANCELED",description:"operation canceled"}];t.exports.errno={"-1":r[0],0:r[1],1:r[2],2:r[3],3:r[4],4:r[5],5:r[6],6:r[7],7:r[8],8:r[9],9:r[10],10:r[11],11:r[12],12:r[13],13:r[14],14:r[15],15:r[16],16:r[17],17:r[18],18:r[19],19:r[20],20:r[21],21:r[22],22:r[23],23:r[24],24:r[25],25:r[26],26:r[27],27:r[28],28:r[29],29:r[30],31:r[31],32:r[32],33:r[33],34:r[34],35:r[35],36:r[36],37:r[37],38:r[38],39:r[39],40:r[40],41:r[41],42:r[42],44:r[43],45:r[44],46:r[45],47:r[46],48:r[47],49:r[48],50:r[49],51:r[50],52:r[51],53:r[52],54:r[53],55:r[54],56:r[55],57:r[56],58:r[57],59:r[58]},t.exports.code={UNKNOWN:r[0],OK:r[1],EOF:r[2],EADDRINFO:r[3],EACCES:r[4],EAGAIN:r[5],EADDRINUSE:r[6],EADDRNOTAVAIL:r[7],EAFNOSUPPORT:r[8],EALREADY:r[9],EBADF:r[10],EBUSY:r[11],ECONNABORTED:r[12],ECONNREFUSED:r[13],ECONNRESET:r[14],EDESTADDRREQ:r[15],EFAULT:r[16],EHOSTUNREACH:r[17],EINTR:r[18],EINVAL:r[19],EISCONN:r[20],EMFILE:r[21],EMSGSIZE:r[22],ENETDOWN:r[23],ENETUNREACH:r[24],ENFILE:r[25],ENOBUFS:r[26],ENOMEM:r[27],ENOTDIR:r[28],EISDIR:r[29],ENONET:r[30],ENOTCONN:r[31],ENOTSOCK:r[32],ENOTSUP:r[33],ENOENT:r[34],ENOSYS:r[35],EPIPE:r[36],EPROTO:r[37],EPROTONOSUPPORT:r[38],EPROTOTYPE:r[39],ETIMEDOUT:r[40],ECHARSET:r[41],EAIFAMNOSUPPORT:r[42],EAISERVICE:r[43],EAISOCKTYPE:r[44],ESHUTDOWN:r[45],EEXIST:r[46],ESRCH:r[47],ENAMETOOLONG:r[48],EPERM:r[49],ELOOP:r[50],EXDEV:r[51],ENOTEMPTY:r[52],ENOSPC:r[53],EIO:r[54],EROFS:r[55],ENODEV:r[56],ESPIPE:r[57],ECANCELED:r[58]},t.exports.custom=e("./custom")(t.exports),t.exports.create=t.exports.custom.createError},{"./custom":84}],86:[function(e,t){!function(e,r,n){"undefined"!=typeof t&&t.exports?t.exports=n():r[e]=n()}("prr",this,function(){var e="function"==typeof Object.defineProperty?function(e,t,r){return Object.defineProperty(e,t,r),e}:function(e,t,r){return e[t]=r.value,e},t=function(e,t){var r="object"==typeof t,n=!r&&"string"==typeof t,o=function(e){return r?!!t[e]:n?t.indexOf(e[0])>-1:!1};return{enumerable:o("enumerable"),configurable:o("configurable"),writable:o("writable"),value:e}},r=function(r,n,o,i){var s;if(i=t(o,i),"object"==typeof n){for(s in n)Object.hasOwnProperty.call(n,s)&&(i.value=n[s],e(r,s,i));return r}return e(r,n,i)};return r})},{}],87:[function(e,t){t.exports=e(26)},{"./_stream_readable":89,"./_stream_writable":91,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_duplex.js":26,_process:24,"core-util-is":92,inherits:44}],88:[function(e,t){t.exports=e(27)},{"./_stream_transform":90,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_passthrough.js":27,"core-util-is":92,inherits:44}],89:[function(e,t){t.exports=e(28)},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_readable.js":28,_process:24,buffer:17,"core-util-is":92,events:21,inherits:44,isarray:93,stream:36,"string_decoder/":94}],90:[function(e,t){t.exports=e(29) +},{"./_stream_duplex":87,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_transform.js":29,"core-util-is":92,inherits:44}],91:[function(e,t){t.exports=e(30)},{"./_stream_duplex":87,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_writable.js":30,_process:24,buffer:17,"core-util-is":92,inherits:44,stream:36}],92:[function(e,t){t.exports=e(31)},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/node_modules/core-util-is/lib/util.js":31,buffer:17}],93:[function(e,t){t.exports=e(22)},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/isarray/index.js":22}],94:[function(e,t){t.exports=e(37)},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/string_decoder/index.js":37,buffer:17}],95:[function(e,t){t.exports=e(33)},{"./lib/_stream_duplex.js":87,"./lib/_stream_passthrough.js":88,"./lib/_stream_readable.js":89,"./lib/_stream_transform.js":90,"./lib/_stream_writable.js":91,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/readable.js":33,stream:36}],96:[function(e,t){t.exports=e(49)},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/abstract-leveldown/node_modules/xtend/index.js":49}],97:[function(e,t){t.exports={name:"levelup",description:"Fast & simple storage - a Node.js-style LevelDB wrapper",version:"0.18.6",contributors:[{name:"Rod Vagg",email:"r@va.gg",url:"https://github.com/rvagg"},{name:"John Chesley",email:"john@chesl.es",url:"https://github.com/chesles/"},{name:"Jake Verbaten",email:"raynos2@gmail.com",url:"https://github.com/raynos"},{name:"Dominic Tarr",email:"dominic.tarr@gmail.com",url:"https://github.com/dominictarr"},{name:"Max Ogden",email:"max@maxogden.com",url:"https://github.com/maxogden"},{name:"Lars-Magnus Skog",email:"lars.magnus.skog@gmail.com",url:"https://github.com/ralphtheninja"},{name:"David Björklund",email:"david.bjorklund@gmail.com",url:"https://github.com/kesla"},{name:"Julian Gruber",email:"julian@juliangruber.com",url:"https://github.com/juliangruber"},{name:"Paolo Fragomeni",email:"paolo@async.ly",url:"https://github.com/hij1nx"},{name:"Anton Whalley",email:"anton.whalley@nearform.com",url:"https://github.com/No9"},{name:"Matteo Collina",email:"matteo.collina@gmail.com",url:"https://github.com/mcollina"},{name:"Pedro Teixeira",email:"pedro.teixeira@gmail.com",url:"https://github.com/pgte"},{name:"James Halliday",email:"mail@substack.net",url:"https://github.com/substack"}],repository:{type:"git",url:"https://github.com/rvagg/node-levelup.git"},homepage:"https://github.com/rvagg/node-levelup",keywords:["leveldb","stream","database","db","store","storage","json"],main:"lib/levelup.js",dependencies:{bl:"~0.8.1","deferred-leveldown":"~0.2.0",errno:"~0.1.1",prr:"~0.0.0","readable-stream":"~1.0.26",semver:"~2.3.1",xtend:"~3.0.0"},devDependencies:{leveldown:"~0.10.0",bustermove:"*",tap:"*",referee:"*",rimraf:"*",async:"*",fstream:"*",tar:"*",mkfiletree:"*",readfiletree:"*","slow-stream":">=0.0.4",delayed:"*",boganipsum:"*",du:"*",memdown:"*","msgpack-js":"*"},browser:{leveldown:!1,"leveldown/package":!1,semver:!1},scripts:{test:"tap test/*-test.js --stderr",functionaltests:"node ./test/functional/fstream-test.js && node ./test/functional/binary-data-test.js && node ./test/functional/compat-test.js",alltests:"npm test && npm run-script functionaltests"},license:"MIT",gitHead:"213e989e2b75273e2b44c23f84f95e35bff7ea11",bugs:{url:"https://github.com/rvagg/node-levelup/issues"},_id:"levelup@0.18.6",_shasum:"e6a01cb089616c8ecc0291c2a9bd3f0c44e3e5eb",_from:"levelup@~0.18.4",_npmVersion:"1.4.14",_npmUser:{name:"rvagg",email:"rod@vagg.org"},maintainers:[{name:"rvagg",email:"rod@vagg.org"}],dist:{shasum:"e6a01cb089616c8ecc0291c2a9bd3f0c44e3e5eb",tarball:"http://127.0.0.1:5080/tarballs/levelup/0.18.6.tgz"},_resolved:"http://127.0.0.1:5080/tarballs/levelup/0.18.6.tgz",readme:"ERROR: No README data found!"}},{}],98:[function(e,t){"use strict";function r(){}t.exports=r},{}],99:[function(e,t){"use strict";function r(e){function t(e,t){function n(e){c[t]=e,++f===r&!u&&(u=!0,a.resolve(d,c))}i(e).then(n,function(e){u||(u=!0,a.reject(d,e))})}if("[object Array]"!==Object.prototype.toString.call(e))return o(new TypeError("must be an array"));var r=e.length,u=!1;if(!r)return i([]);for(var c=new Array(r),f=0,l=-1,d=new n(s);++l<r;)t(e[l],l);return d}var n=e("./promise"),o=e("./reject"),i=e("./resolve"),s=e("./INTERNAL"),a=e("./handlers");t.exports=r},{"./INTERNAL":98,"./handlers":100,"./promise":102,"./reject":105,"./resolve":106}],100:[function(e,t,r){"use strict";function n(e){var t=e&&e.then;return e&&"object"==typeof e&&"function"==typeof t?function(){t.apply(e,arguments)}:void 0}var o=e("./tryCatch"),i=e("./resolveThenable"),s=e("./states");r.resolve=function(e,t){var a=o(n,t);if("error"===a.status)return r.reject(e,a.value);var u=a.value;if(u)i.safely(e,u);else{e.state=s.FULFILLED,e.outcome=t;for(var c=-1,f=e.queue.length;++c<f;)e.queue[c].callFulfilled(t)}return e},r.reject=function(e,t){e.state=s.REJECTED,e.outcome=t;for(var r=-1,n=e.queue.length;++r<n;)e.queue[r].callRejected(t);return e}},{"./resolveThenable":107,"./states":108,"./tryCatch":109}],101:[function(e,t,r){t.exports=r=e("./promise"),r.resolve=e("./resolve"),r.reject=e("./reject"),r.all=e("./all"),r.race=e("./race")},{"./all":99,"./promise":102,"./race":104,"./reject":105,"./resolve":106}],102:[function(e,t){"use strict";function r(e){if(!(this instanceof r))return new r(e);if("function"!=typeof e)throw new TypeError("reslover must be a function");this.state=s.PENDING,this.queue=[],this.outcome=void 0,e!==o&&i.safely(this,e)}var n=e("./unwrap"),o=e("./INTERNAL"),i=e("./resolveThenable"),s=e("./states"),a=e("./queueItem");t.exports=r,r.prototype["catch"]=function(e){return this.then(null,e)},r.prototype.then=function(e,t){if("function"!=typeof e&&this.state===s.FULFILLED||"function"!=typeof t&&this.state===s.REJECTED)return this;var i=new r(o);if(this.state!==s.PENDING){var u=this.state===s.FULFILLED?e:t;n(i,u,this.outcome)}else this.queue.push(new a(i,e,t));return i}},{"./INTERNAL":98,"./queueItem":103,"./resolveThenable":107,"./states":108,"./unwrap":110}],103:[function(e,t){"use strict";function r(e,t,r){this.promise=e,"function"==typeof t&&(this.onFulfilled=t,this.callFulfilled=this.otherCallFulfilled),"function"==typeof r&&(this.onRejected=r,this.callRejected=this.otherCallRejected)}var n=e("./handlers"),o=e("./unwrap");t.exports=r,r.prototype.callFulfilled=function(e){n.resolve(this.promise,e)},r.prototype.otherCallFulfilled=function(e){o(this.promise,this.onFulfilled,e)},r.prototype.callRejected=function(e){n.reject(this.promise,e)},r.prototype.otherCallRejected=function(e){o(this.promise,this.onRejected,e)}},{"./handlers":100,"./unwrap":110}],104:[function(e,t){"use strict";function r(e){function t(e){i(e).then(function(e){u||(u=!0,a.resolve(f,e))},function(e){u||(u=!0,a.reject(f,e))})}if("[object Array]"!==Object.prototype.toString.call(e))return o(new TypeError("must be an array"));var r=e.length,u=!1;if(!r)return i([]);for(var c=-1,f=new n(s);++c<r;)t(e[c]);return f}var n=e("./promise"),o=e("./reject"),i=e("./resolve"),s=e("./INTERNAL"),a=e("./handlers");t.exports=r},{"./INTERNAL":98,"./handlers":100,"./promise":102,"./reject":105,"./resolve":106}],105:[function(e,t){"use strict";function r(e){var t=new n(o);return i.reject(t,e)}var n=e("./promise"),o=e("./INTERNAL"),i=e("./handlers");t.exports=r},{"./INTERNAL":98,"./handlers":100,"./promise":102}],106:[function(e,t){"use strict";function r(e){if(e)return e instanceof n?e:i.resolve(new n(o),e);var t=typeof e;switch(t){case"boolean":return s;case"undefined":return u;case"object":return a;case"number":return c;case"string":return f}}var n=e("./promise"),o=e("./INTERNAL"),i=e("./handlers");t.exports=r;var s=i.resolve(new n(o),!1),a=i.resolve(new n(o),null),u=i.resolve(new n(o),void 0),c=i.resolve(new n(o),0),f=i.resolve(new n(o),"")},{"./INTERNAL":98,"./handlers":100,"./promise":102}],107:[function(e,t,r){"use strict";function n(e,t){function r(t){a||(a=!0,o.reject(e,t))}function n(t){a||(a=!0,o.resolve(e,t))}function s(){t(n,r)}var a=!1,u=i(s);"error"===u.status&&r(u.value)}var o=e("./handlers"),i=e("./tryCatch");r.safely=n},{"./handlers":100,"./tryCatch":109}],108:[function(e,t,r){r.REJECTED=["REJECTED"],r.FULFILLED=["FULFILLED"],r.PENDING=["PENDING"]},{}],109:[function(e,t){"use strict";function r(e,t){var r={};try{r.value=e(t),r.status="success"}catch(n){r.status="error",r.value=n}return r}t.exports=r},{}],110:[function(e,t){"use strict";function r(e,t,r){n(function(){var n;try{n=t(r)}catch(i){return o.reject(e,i)}n===e?o.reject(e,new TypeError("Cannot resolve promise with itself")):o.resolve(e,n)})}var n=e("immediate"),o=e("./handlers");t.exports=r},{"./handlers":100,immediate:111}],111:[function(e,t){"use strict";function r(){o=!0;for(var e,t,r=a.length;r;){for(t=a,a=[],e=-1;++e<r;)t[e]();r=a.length}o=!1}function n(e){1!==a.push(e)||o||i()}for(var o,i,s=[e("./nextTick"),e("./mutation.js"),e("./messageChannel"),e("./stateChange"),e("./timeout")],a=[],u=-1,c=s.length;++u<c;)if(s[u]&&s[u].test&&s[u].test()){i=s[u].install(r);break}t.exports=n},{"./messageChannel":112,"./mutation.js":113,"./nextTick":16,"./stateChange":114,"./timeout":115}],112:[function(e,t,r){(function(e){"use strict";r.test=function(){return e.setImmediate?!1:"undefined"!=typeof e.MessageChannel},r.install=function(t){var r=new e.MessageChannel;return r.port1.onmessage=t,function(){r.port2.postMessage(0)}}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],113:[function(e,t,r){(function(e){"use strict";var t=e.MutationObserver||e.WebKitMutationObserver;r.test=function(){return t},r.install=function(r){var n=0,o=new t(r),i=e.document.createTextNode("");return o.observe(i,{characterData:!0}),function(){i.data=n=++n%2}}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],114:[function(e,t,r){(function(e){"use strict";r.test=function(){return"document"in e&&"onreadystatechange"in e.document.createElement("script")},r.install=function(t){return function(){var r=e.document.createElement("script");return r.onreadystatechange=function(){t(),r.onreadystatechange=null,r.parentNode.removeChild(r),r=null},e.document.documentElement.appendChild(r),t}}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],115:[function(e,t,r){"use strict";r.test=function(){return!0},r.install=function(e){return function(){setTimeout(e,0)}}},{}],116:[function(e,t){"use strict";function r(e){return null===e?String(e):"object"==typeof e||"function"==typeof e?u[d.call(e)]||"object":typeof e}function n(e){return null!==e&&e===e.window}function o(e){if(!e||"object"!==r(e)||e.nodeType||n(e))return!1;try{if(e.constructor&&!h.call(e,"constructor")&&!h.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(t){return!1}var o;for(o in e);return void 0===o||h.call(e,o)}function i(e){return"function"===r(e)}function s(){for(var e=[],t=-1,r=arguments.length,n=new Array(r);++t<r;)n[t]=arguments[t];var o={};e.push({args:n,result:{container:o,key:"key"}});for(var i;i=e.pop();)a(e,i.args,i.result);return o.key}function a(e,t,r){var n,s,a,u,c,f,l,d=t[0]||{},h=1,v=t.length,y=!1,g=/\d+/;for("boolean"==typeof d&&(y=d,d=t[1]||{},h=2),"object"==typeof d||i(d)||(d={}),v===h&&(d=this,--h);v>h;h++)if(null!=(n=t[h])){l=p(n);for(s in n)if(!(s in Object.prototype)){if(l&&!g.test(s))continue;if(a=d[s],u=n[s],d===u)continue;y&&u&&(o(u)||(c=p(u)))?(c?(c=!1,f=a&&p(a)?a:[]):f=a&&o(a)?a:{},e.push({args:[y,f,u],result:{container:d,key:s}})):void 0!==u&&(p(n)&&i(u)||(d[s]=u))}}r.container[r.key]=d}for(var u={},c=["Boolean","Number","String","Function","Array","Date","RegExp","Object","Error"],f=0;f<c.length;f++){var l=c[f];u["[object "+l+"]"]=l.toLowerCase()}var d=u.toString,h=u.hasOwnProperty,p=Array.isArray||function(e){return"array"===r(e)};t.exports=s},{}],117:[function(e,t,r){!function(e){if("object"==typeof r)t.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var n;try{n=window}catch(o){n=self}n.SparkMD5=e()}}(function(){"use strict";var e=function(e,t){return e+t&4294967295},t=function(t,r,n,o,i,s){return r=e(e(r,t),e(o,s)),e(r<<i|r>>>32-i,n)},r=function(e,r,n,o,i,s,a){return t(r&n|~r&o,e,r,i,s,a)},n=function(e,r,n,o,i,s,a){return t(r&o|n&~o,e,r,i,s,a)},o=function(e,r,n,o,i,s,a){return t(r^n^o,e,r,i,s,a)},i=function(e,r,n,o,i,s,a){return t(n^(r|~o),e,r,i,s,a)},s=function(t,s){var a=t[0],u=t[1],c=t[2],f=t[3];a=r(a,u,c,f,s[0],7,-680876936),f=r(f,a,u,c,s[1],12,-389564586),c=r(c,f,a,u,s[2],17,606105819),u=r(u,c,f,a,s[3],22,-1044525330),a=r(a,u,c,f,s[4],7,-176418897),f=r(f,a,u,c,s[5],12,1200080426),c=r(c,f,a,u,s[6],17,-1473231341),u=r(u,c,f,a,s[7],22,-45705983),a=r(a,u,c,f,s[8],7,1770035416),f=r(f,a,u,c,s[9],12,-1958414417),c=r(c,f,a,u,s[10],17,-42063),u=r(u,c,f,a,s[11],22,-1990404162),a=r(a,u,c,f,s[12],7,1804603682),f=r(f,a,u,c,s[13],12,-40341101),c=r(c,f,a,u,s[14],17,-1502002290),u=r(u,c,f,a,s[15],22,1236535329),a=n(a,u,c,f,s[1],5,-165796510),f=n(f,a,u,c,s[6],9,-1069501632),c=n(c,f,a,u,s[11],14,643717713),u=n(u,c,f,a,s[0],20,-373897302),a=n(a,u,c,f,s[5],5,-701558691),f=n(f,a,u,c,s[10],9,38016083),c=n(c,f,a,u,s[15],14,-660478335),u=n(u,c,f,a,s[4],20,-405537848),a=n(a,u,c,f,s[9],5,568446438),f=n(f,a,u,c,s[14],9,-1019803690),c=n(c,f,a,u,s[3],14,-187363961),u=n(u,c,f,a,s[8],20,1163531501),a=n(a,u,c,f,s[13],5,-1444681467),f=n(f,a,u,c,s[2],9,-51403784),c=n(c,f,a,u,s[7],14,1735328473),u=n(u,c,f,a,s[12],20,-1926607734),a=o(a,u,c,f,s[5],4,-378558),f=o(f,a,u,c,s[8],11,-2022574463),c=o(c,f,a,u,s[11],16,1839030562),u=o(u,c,f,a,s[14],23,-35309556),a=o(a,u,c,f,s[1],4,-1530992060),f=o(f,a,u,c,s[4],11,1272893353),c=o(c,f,a,u,s[7],16,-155497632),u=o(u,c,f,a,s[10],23,-1094730640),a=o(a,u,c,f,s[13],4,681279174),f=o(f,a,u,c,s[0],11,-358537222),c=o(c,f,a,u,s[3],16,-722521979),u=o(u,c,f,a,s[6],23,76029189),a=o(a,u,c,f,s[9],4,-640364487),f=o(f,a,u,c,s[12],11,-421815835),c=o(c,f,a,u,s[15],16,530742520),u=o(u,c,f,a,s[2],23,-995338651),a=i(a,u,c,f,s[0],6,-198630844),f=i(f,a,u,c,s[7],10,1126891415),c=i(c,f,a,u,s[14],15,-1416354905),u=i(u,c,f,a,s[5],21,-57434055),a=i(a,u,c,f,s[12],6,1700485571),f=i(f,a,u,c,s[3],10,-1894986606),c=i(c,f,a,u,s[10],15,-1051523),u=i(u,c,f,a,s[1],21,-2054922799),a=i(a,u,c,f,s[8],6,1873313359),f=i(f,a,u,c,s[15],10,-30611744),c=i(c,f,a,u,s[6],15,-1560198380),u=i(u,c,f,a,s[13],21,1309151649),a=i(a,u,c,f,s[4],6,-145523070),f=i(f,a,u,c,s[11],10,-1120210379),c=i(c,f,a,u,s[2],15,718787259),u=i(u,c,f,a,s[9],21,-343485551),t[0]=e(a,t[0]),t[1]=e(u,t[1]),t[2]=e(c,t[2]),t[3]=e(f,t[3])},a=function(e){var t,r=[];for(t=0;64>t;t+=4)r[t>>2]=e.charCodeAt(t)+(e.charCodeAt(t+1)<<8)+(e.charCodeAt(t+2)<<16)+(e.charCodeAt(t+3)<<24);return r},u=function(e){var t,r=[];for(t=0;64>t;t+=4)r[t>>2]=e[t]+(e[t+1]<<8)+(e[t+2]<<16)+(e[t+3]<<24);return r},c=function(e){var t,r,n,o,i,u,c=e.length,f=[1732584193,-271733879,-1732584194,271733878];for(t=64;c>=t;t+=64)s(f,a(e.substring(t-64,t)));for(e=e.substring(t-64),r=e.length,n=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],t=0;r>t;t+=1)n[t>>2]|=e.charCodeAt(t)<<(t%4<<3);if(n[t>>2]|=128<<(t%4<<3),t>55)for(s(f,n),t=0;16>t;t+=1)n[t]=0;return o=8*c,o=o.toString(16).match(/(.*?)(.{0,8})$/),i=parseInt(o[2],16),u=parseInt(o[1],16)||0,n[14]=i,n[15]=u,s(f,n),f},f=function(e){var t,r,n,o,i,a,c=e.length,f=[1732584193,-271733879,-1732584194,271733878];for(t=64;c>=t;t+=64)s(f,u(e.subarray(t-64,t)));for(e=c>t-64?e.subarray(t-64):new Uint8Array(0),r=e.length,n=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],t=0;r>t;t+=1)n[t>>2]|=e[t]<<(t%4<<3);if(n[t>>2]|=128<<(t%4<<3),t>55)for(s(f,n),t=0;16>t;t+=1)n[t]=0;return o=8*c,o=o.toString(16).match(/(.*?)(.{0,8})$/),i=parseInt(o[2],16),a=parseInt(o[1],16)||0,n[14]=i,n[15]=a,s(f,n),f},l=["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"],d=function(e){var t,r="";for(t=0;4>t;t+=1)r+=l[e>>8*t+4&15]+l[e>>8*t&15];return r},h=function(e){var t;for(t=0;t<e.length;t+=1)e[t]=d(e[t]);return e.join("")},p=function(e){return h(c(e))},v=function(){this.reset()};return"5d41402abc4b2a76b9719d911017c592"!==p("hello")&&(e=function(e,t){var r=(65535&e)+(65535&t),n=(e>>16)+(t>>16)+(r>>16);return n<<16|65535&r}),v.prototype.append=function(e){return/[\u0080-\uFFFF]/.test(e)&&(e=unescape(encodeURIComponent(e))),this.appendBinary(e),this},v.prototype.appendBinary=function(e){this._buff+=e,this._length+=e.length;var t,r=this._buff.length;for(t=64;r>=t;t+=64)s(this._state,a(this._buff.substring(t-64,t)));return this._buff=this._buff.substr(t-64),this},v.prototype.end=function(e){var t,r,n=this._buff,o=n.length,i=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];for(t=0;o>t;t+=1)i[t>>2]|=n.charCodeAt(t)<<(t%4<<3);return this._finish(i,o),r=e?this._state:h(this._state),this.reset(),r},v.prototype._finish=function(e,t){var r,n,o,i=t;if(e[i>>2]|=128<<(i%4<<3),i>55)for(s(this._state,e),i=0;16>i;i+=1)e[i]=0;r=8*this._length,r=r.toString(16).match(/(.*?)(.{0,8})$/),n=parseInt(r[2],16),o=parseInt(r[1],16)||0,e[14]=n,e[15]=o,s(this._state,e)},v.prototype.reset=function(){return this._buff="",this._length=0,this._state=[1732584193,-271733879,-1732584194,271733878],this},v.prototype.destroy=function(){delete this._state,delete this._buff,delete this._length},v.hash=function(e,t){/[\u0080-\uFFFF]/.test(e)&&(e=unescape(encodeURIComponent(e)));var r=c(e);return t?r:h(r)},v.hashBinary=function(e,t){var r=c(e);return t?r:h(r)},v.ArrayBuffer=function(){this.reset()},v.ArrayBuffer.prototype.append=function(e){var t,r=this._concatArrayBuffer(this._buff,e),n=r.length;for(this._length+=e.byteLength,t=64;n>=t;t+=64)s(this._state,u(r.subarray(t-64,t)));return this._buff=n>t-64?r.subarray(t-64):new Uint8Array(0),this},v.ArrayBuffer.prototype.end=function(e){var t,r,n=this._buff,o=n.length,i=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];for(t=0;o>t;t+=1)i[t>>2]|=n[t]<<(t%4<<3);return this._finish(i,o),r=e?this._state:h(this._state),this.reset(),r},v.ArrayBuffer.prototype._finish=v.prototype._finish,v.ArrayBuffer.prototype.reset=function(){return this._buff=new Uint8Array(0),this._length=0,this._state=[1732584193,-271733879,-1732584194,271733878],this},v.ArrayBuffer.prototype.destroy=v.prototype.destroy,v.ArrayBuffer.prototype._concatArrayBuffer=function(e,t){var r=e.length,n=new Uint8Array(r+t.byteLength);return n.set(e),n.set(new Uint8Array(t),r),n},v.ArrayBuffer.hash=function(e,t){var r=f(new Uint8Array(e));return t?r:h(r)},v})},{}],118:[function(e,t){t.exports=e(26)},{"./_stream_readable":119,"./_stream_writable":121,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_duplex.js":26,_process:24,"core-util-is":122,inherits:44}],119:[function(e,t){t.exports=e(28)},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_readable.js":28,_process:24,buffer:17,"core-util-is":122,events:21,inherits:44,isarray:123,stream:36,"string_decoder/":124}],120:[function(e,t){t.exports=e(29)},{"./_stream_duplex":118,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_transform.js":29,"core-util-is":122,inherits:44}],121:[function(e,t){t.exports=e(30)},{"./_stream_duplex":118,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/lib/_stream_writable.js":30,_process:24,buffer:17,"core-util-is":122,inherits:44,stream:36}],122:[function(e,t){t.exports=e(31)},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/node_modules/core-util-is/lib/util.js":31,buffer:17}],123:[function(e,t){t.exports=e(22)},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/isarray/index.js":22}],124:[function(e,t){t.exports=e(37)},{"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/string_decoder/index.js":37,buffer:17}],125:[function(e,t){t.exports=e(34)},{"./lib/_stream_transform.js":120,"/Users/nolan/workspace/pouchdb/node_modules/browserify/node_modules/readable-stream/transform.js":34}],126:[function(e,t){t.exports=e(54)},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/has-keys.js":54}],127:[function(e,t){t.exports=e(55)},{"./has-keys":126,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/index.js":55,"object-keys":129}],128:[function(e,t){t.exports=e(56)},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/foreach.js":56}],129:[function(e,t){t.exports=e(57)},{"./shim":131,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/index.js":57}],130:[function(e,t){t.exports=e(58)},{"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/isArguments.js":58}],131:[function(e,t){t.exports=e(59)},{"./foreach":128,"./isArguments":130,"/Users/nolan/workspace/pouchdb/node_modules/level-js/node_modules/xtend/node_modules/object-keys/shim.js":59}],132:[function(e,t){function r(e,t,r){r(null,e)}function n(e){return function(t,n,o){return"function"==typeof t&&(o=n,n=t,t={}),"function"!=typeof n&&(n=r),"function"!=typeof o&&(o=null),e(t,n,o)}}var o=e("readable-stream/transform"),i=e("util").inherits,s=e("xtend");t.exports=n(function(e,t,r){var n=new o(e);return n._transform=t,r&&(n._flush=r),n}),t.exports.ctor=n(function(e,t,r){function n(t){return this instanceof n?(this.options=s(e,t),void o.call(this,this.options)):new n(t)}return i(n,o),n.prototype._transform=t,r&&(n.prototype._flush=r),n}),t.exports.obj=n(function(e,t,r){var n=new o(s({objectMode:!0},e));return n._transform=t,r&&(n._flush=r),n})},{"readable-stream/transform":125,util:39,xtend:127}],133:[function(e,t,r){"use strict";function n(e,t,r){var n=r[r.length-1];e===n.element&&(r.pop(),n=r[r.length-1]);var o=n.element,i=n.index;if(Array.isArray(o))o.push(e);else if(i===t.length-2){var s=t.pop();o[s]=e}else t.push(e)}r.stringify=function(e){var t=[];t.push({obj:e});for(var r,n,o,i,s,a,u,c,f,l,d,h="";r=t.pop();)if(n=r.obj,o=r.prefix||"",i=r.val||"",h+=o,i)h+=i;else if("object"!=typeof n)h+="undefined"==typeof n?null:JSON.stringify(n);else if(null===n)h+="null";else if(Array.isArray(n)){for(t.push({val:"]"}),s=n.length-1;s>=0;s--)a=0===s?"":",",t.push({obj:n[s],prefix:a});t.push({val:"["})}else{u=[];for(c in n)n.hasOwnProperty(c)&&u.push(c);for(t.push({val:"}"}),s=u.length-1;s>=0;s--)f=u[s],l=n[f],d=s>0?",":"",d+=JSON.stringify(f)+":",t.push({obj:l,prefix:d});t.push({val:"{"})}return h},r.parse=function(e){for(var t,r,o,i,s,a,u,c,f,l=[],d=[],h=0;;)if(t=e[h++],"}"!==t&&"]"!==t&&"undefined"!=typeof t)switch(t){case" ":case" ":case"\n":case":":case",":break;case"n":h+=3,n(null,l,d);break;case"t":h+=3,n(!0,l,d);break;case"f":h+=4,n(!1,l,d);break;case"0":case"1":case"2":case"3":case"4":case"5":case"6":case"7":case"8":case"9":case"-":for(r="",h--;;){if(o=e[h++],!/[\d\.\-e\+]/.test(o)){h--;break}r+=o}n(parseFloat(r),l,d);break;case'"':for(i="",s=void 0,a=0;;){if(u=e[h++],'"'===u&&("\\"!==s||a%2!==1))break;i+=u,s=u,"\\"===s?a++:a=0}n(JSON.parse('"'+i+'"'),l,d);break;case"[":c={element:[],index:l.length},l.push(c.element),d.push(c);break;case"{":f={element:{},index:l.length},l.push(f.element),d.push(f);break;default:throw new Error("unexpectedly reached end of input: "+t)}else{if(1===l.length)return l.pop();n(l.pop(),l,d)}}},{}],"adapter-config":[function(e,t){"use strict";t.exports={name:"memory",valid:function(){return!0},use_prefix:!1}},{}],leveldown:[function(e,t){(function(r){function n(e){if(!(this instanceof n))return new n(e);if(!e)throw new Error("constructor requires at least a location argument");this.IDBOptions={},this.location=e}t.exports=n;var o=e("idb-wrapper"),i=e("abstract-leveldown").AbstractLevelDOWN,s=e("util"),a=e("./iterator"),u=e("isbuffer"),c=e("xtend"),f=e("typedarray-to-buffer");s.inherits(n,i),n.prototype._open=function(e,t){var r=this,n={storeName:this.location,autoIncrement:!1,keyPath:null,onStoreReady:function(){t&&t(null,r.idb)},onError:function(e){t&&t(e)}};c(n,e),this.IDBOptions=n,this.idb=new o(n)},n.prototype._get=function(e,t,n){this.idb.get(e,function(o){if(void 0===o)return n(new Error("NotFound"));var i=!0;return t.asBuffer===!1&&(i=!1),t.raw&&(i=!1),i&&(o=o instanceof Uint8Array?f(o):new r(String(o))),n(null,o,e)},n)},n.prototype._del=function(e,t,r){this.idb.remove(e,r,r)},n.prototype._put=function(e,t,n,o){t instanceof ArrayBuffer&&(t=f(new Uint8Array(t)));var i=this.convertEncoding(e,t,n);r.isBuffer(i.value)&&(i.value=new Uint8Array(t.toArrayBuffer())),this.idb.put(i.key,i.value,function(){o()},o)},n.prototype.convertEncoding=function(e,t,r){if(r.raw)return{key:e,value:t};if(t){var n=t.toString();"NaN"===n&&(t="NaN")}var o=r.valueEncoding,i={key:e,value:t};return!t||o&&"binary"===o||"object"!=typeof i.value&&(i.value=n),i},n.prototype.iterator=function(e){return"object"!=typeof e&&(e={}),new a(this.idb,e)},n.prototype._batch=function(e,t,r){var n,o,i,s,a=[];if(0===e.length)return setTimeout(r,0);for(n=0;n<e.length;n++){i={},s=e[n],a[n]=i;var u=this.convertEncoding(s.key,s.value,t);s.key=u.key,s.value=u.value;for(o in s)i[o]="type"===o&&"del"==s[o]?"remove":s[o]}return this.idb.batch(a,function(){r()},r)},n.prototype._close=function(e){this.idb.db.close(),e()},n.prototype._approximateSize=function(e,t,r){var n=new Error("Not implemented");if(r)return r(n);throw n},n.prototype._isBuffer=function(e){return r.isBuffer(e)},n.destroy=function(e,t){if("object"==typeof e)var r=e.IDBOptions.storePrefix||"IDBWrapper-",n=e.location;else var r="IDBWrapper-",n=e;var o=indexedDB.deleteDatabase(r+n);o.onsuccess=function(){t()},o.onerror=function(e){t(e)}};n.prototype._checkKeyValue=function(e,t){return null===e||void 0===e?new Error(t+" cannot be `null` or `undefined`"):null===e||void 0===e?new Error(t+" cannot be `null` or `undefined`"):u(e)&&0===e.byteLength?new Error(t+" cannot be an empty ArrayBuffer"):""===String(e)?new Error(t+" cannot be an empty String"):0===e.length?new Error(t+" cannot be an empty Array"):void 0}}).call(this,e("buffer").Buffer)},{"./iterator":45,"abstract-leveldown":48,buffer:17,"idb-wrapper":50,isbuffer:51,"typedarray-to-buffer":53,util:39,xtend:55}]},{},[11]); \ No newline at end of file
diff --git a/dist/pouchdb.min.js b/dist/pouchdb.min.js new file mode 100644 index 0000000..46a4b16 --- /dev/null +++ b/dist/pouchdb.min.js
@@ -0,0 +1,11 @@ +// PouchDB 3.2.0 +// +// (c) 2012-2014 Dale Harvey and the PouchDB team +// PouchDB may be freely distributed under the Apache license, version 2.0. +// For all details and documentation: +// http://pouchdb.com +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;"undefined"!=typeof window?t=window:"undefined"!=typeof global?t=global:"undefined"!=typeof self&&(t=self),t.PouchDB=e()}}(function(){var define,module,exports;return function e(t,n,r){function o(s,a){if(!n[s]){if(!t[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(i)return i(s,!0);var c=new Error("Cannot find module '"+s+"'");throw c.code="MODULE_NOT_FOUND",c}var f=n[s]={exports:{}};t[s][0].call(f.exports,function(e){var n=t[s][1][e];return o(n?n:e)},f,f.exports,e,t,n,r)}return n[s].exports}for(var i="function"==typeof require&&require,s=0;s<r.length;s++)o(r[s]);return o}({1:[function(e,t){"use strict";function n(e,t){for(var n=0;n<e.length;n++)if(t(e[n],n)===!0)return e[n];return!1}function r(e){return function(t,n){t||n[0]&&n[0].error?e(t||n[0]):e(null,n.length?n[0]:n)}}function o(e){var t={},n=[];return u.traverseRevTree(e,function(e,r,o,i){var s=r+"-"+o;return e&&(t[s]=0),void 0!==i&&n.push({from:i,to:s}),s}),n.reverse(),n.forEach(function(e){t[e.from]=void 0===t[e.from]?1+t[e.to]:Math.min(t[e.from],1+t[e.to])}),t}function i(e,t,n){var r="limit"in t?t.keys.slice(t.skip,t.limit+t.skip):t.skip>0?t.keys.slice(t.skip):t.keys;if(t.descending&&r.reverse(),!r.length)return e._allDocs({limit:0},n);var o={offset:t.skip};return h.all(r.map(function(n){var r=a.extend(!0,{key:n,deleted:"ok"},t);return["limit","skip","keys"].forEach(function(e){delete r[e]}),new h(function(t,i){e._allDocs(r,function(e,r){return e?i(e):(o.total_rows=r.total_rows,void t(r.rows[0]||{key:n,error:"not_found"}))})})})).then(function(e){return o.rows=e,o})}function s(){var e=this;f.call(this),e.autoCompact=function(t){return e.auto_compaction&&"http"!==e.type()?function(n,r){if(n)t(n);else{var o=r.length,i=function(){o--,o||t(null,r)};if(!r.length)return t(null,r);r.forEach(function(t){t.ok&&t.id?e.compactDocument(t.id,0,i):i()})}}:t};var t,n=0,r=["change","delete","create","update"];this.on("newListener",function(o){if(~r.indexOf(o)){if(n)return void n++;n++;var i=0;t=this.changes({conflicts:!0,include_docs:!0,continuous:!0,since:"now",onChange:function(t){t.seq<=i||(i=t.seq,e.emit("change",t),t.doc._deleted?e.emit("delete",t):"1"===t.doc._rev.split("-")[0]?e.emit("create",t):e.emit("update",t))}})}}),this.on("removeListener",function(e){~r.indexOf(e)&&(n--,n||t.cancel())})}var a=e("./utils"),u=e("./merge"),c=e("./deps/errors"),f=e("events").EventEmitter,l=e("./deps/upsert"),d=e("./changes"),h=a.Promise;a.inherits(s,f),t.exports=s,s.prototype.post=a.adapterFun("post",function(e,t,n){return"function"==typeof t&&(n=t,t={}),"object"!=typeof e||Array.isArray(e)?n(c.NOT_AN_OBJECT):void this.bulkDocs({docs:[e]},t,this.autoCompact(r(n)))}),s.prototype.put=a.adapterFun("put",a.getArguments(function(e){var t,n,o,i,s=e.shift(),u="_id"in s;if("object"!=typeof s||Array.isArray(s))return(i=e.pop())(c.NOT_AN_OBJECT);for(s=a.clone(s);;)if(t=e.shift(),n=typeof t,"string"!==n||u?"string"!==n||!u||"_rev"in s?"object"===n?o=t:"function"===n&&(i=t):s._rev=t:(s._id=t,u=!0),!e.length)break;o=o||{};var f=a.invalidIdError(s._id);return f?i(f):a.isLocalId(s._id)&&"function"==typeof this._putLocal?s._deleted?this._removeLocal(s,i):this._putLocal(s,i):void this.bulkDocs({docs:[s]},o,this.autoCompact(r(i)))})),s.prototype.putAttachment=a.adapterFun("putAttachment",function(e,t,n,r,o,i){function s(e){return e._attachments=e._attachments||{},e._attachments[t]={content_type:o,data:r},a.put(e)}var a=this;return"function"==typeof o&&(i=o,o=r,r=n,n=null),"undefined"==typeof o&&(o=r,r=n,n=null),a.get(e).then(function(e){if(e._rev!==n)throw c.REV_CONFLICT;return s(e)},function(t){if(t.error===c.MISSING_DOC.error)return s({_id:e});throw t})}),s.prototype.removeAttachment=a.adapterFun("removeAttachment",function(e,t,n,r){var o=this;o.get(e,function(e,i){return e?void r(e):i._rev!==n?void r(c.REV_CONFLICT):i._attachments?(delete i._attachments[t],0===Object.keys(i._attachments).length&&delete i._attachments,void o.put(i,r)):r()})}),s.prototype.remove=a.adapterFun("remove",function(e,t,n,o){var i;"string"==typeof t?(i={_id:e,_rev:t},"function"==typeof n&&(o=n,n={})):(i=e,"function"==typeof t?(o=t,n={}):(o=n,n=t)),n=a.clone(n||{}),n.was_delete=!0;var s={_id:i._id,_rev:i._rev||n.rev};return s._deleted=!0,a.isLocalId(s._id)&&"function"==typeof this._removeLocal?this._removeLocal(i,o):void this.bulkDocs({docs:[s]},n,r(o))}),s.prototype.revsDiff=a.adapterFun("revsDiff",function(e,t,n){function r(e,t){c.has(e)||c.set(e,{missing:[]}),c.get(e).missing.push(t)}function o(t,n){var o=e[t].slice(0);u.traverseRevTree(n,function(e,n,i,s,a){var u=n+"-"+i,c=o.indexOf(u);-1!==c&&(o.splice(c,1),"available"!==a.status&&r(t,u))}),o.forEach(function(e){r(t,e)})}"function"==typeof t&&(n=t,t={}),t=a.clone(t);var i=Object.keys(e);if(!i.length)return n(null,{});var s=0,c=new a.Map;i.map(function(t){this._getRevisionTree(t,function(r,a){if(r&&404===r.status&&"missing"===r.message)c.set(t,{missing:e[t]});else{if(r)return n(r);o(t,a)}if(++s===i.length){var u={};return c.forEach(function(e,t){u[t]=e}),n(null,u)}})},this)}),s.prototype.compactDocument=a.adapterFun("compactDocument",function(e,t,n){var r=this;this._getRevisionTree(e,function(i,s){if(i)return n(i);var a=o(s),c=[],f=[];Object.keys(a).forEach(function(e){a[e]>t&&c.push(e)}),u.traverseRevTree(s,function(e,t,n,r,o){var i=t+"-"+n;"available"===o.status&&-1!==c.indexOf(i)&&f.push(i)}),r._doCompaction(e,f,n)})}),s.prototype.compact=a.adapterFun("compact",function(e,t){"function"==typeof e&&(t=e,e={});var n=this;e=a.clone(e||{}),n.get("_local/compaction")["catch"](function(){return!1}).then(function(r){return"function"==typeof n._compact?(r&&r.last_seq&&(e.last_seq=r.last_seq),n._compact(e,t)):void 0})}),s.prototype._compact=function(e,t){function n(){l(c,"_local/compaction",function(e){return!e.last_seq||e.last_seq<i?(e.last_seq=i,e):!1},t)}function r(){a--,!a&&s&&n()}function o(e){a++,c.compactDocument(e.id,0).then(r,t)}var i,s=!1,a=0,u={returnDocs:!1},c=this;e.last_seq&&(u.since=e.last_seq),c.changes(u).on("change",o).on("complete",function(e){s=!0,i=e.last_seq,a||n()}).on("error",t)},s.prototype.get=a.adapterFun("get",function(e,t,r){function o(){var n=[],o=i.length;return o?void i.forEach(function(i){s.get(e,{rev:i,revs:t.revs,attachments:t.attachments},function(e,t){n.push(e?{missing:i}:{ok:t}),o--,o||r(null,n)})}):r(null,n)}if("function"==typeof t&&(r=t,t={}),"string"!=typeof e)return r(c.INVALID_ID);if(a.isLocalId(e)&&"function"==typeof this._getLocal)return this._getLocal(e,r);var i=[],s=this;if(!t.open_revs)return this._get(e,t,function(e,o){if(t=a.clone(t),e)return r(e);var i=o.doc;if(!i)return r(new Error("no doc!"));var c=o.metadata,f=o.ctx;if(t.conflicts){var l=u.collectConflicts(c);l.length&&(i._conflicts=l)}if(t.revs||t.revs_info){var d=u.rootToLeaf(c.rev_tree),h=n(d,function(e){return-1!==e.ids.map(function(e){return e.id}).indexOf(i._rev.split("-")[1])}),p=h.ids.map(function(e){return e.id}).indexOf(i._rev.split("-")[1])+1,v=h.ids.length-p;if(h.ids.splice(p,v),h.ids.reverse(),t.revs&&(i._revisions={start:h.pos+h.ids.length-1,ids:h.ids.map(function(e){return e.id})}),t.revs_info){var g=h.pos+h.ids.length;i._revs_info=h.ids.map(function(e){return g--,{rev:g+"-"+e.id,status:e.opts.status}})}}if(t.local_seq&&(i._local_seq=o.metadata.seq),t.attachments&&i._attachments){var y=i._attachments,m=Object.keys(y).length;if(0===m)return r(null,i);Object.keys(y).forEach(function(e){this._getAttachment(y[e],{encode:!0,ctx:f},function(t,n){var o=i._attachments[e];o.data=n,delete o.stub,delete o.length,--m||r(null,i)})},s)}else{if(i._attachments)for(var _ in i._attachments)i._attachments.hasOwnProperty(_)&&(i._attachments[_].stub=!0);r(null,i)}});if("all"===t.open_revs)this._getRevisionTree(e,function(e,t){e&&(t=[]),i=u.collectLeaves(t).map(function(e){return e.rev}),o()});else{if(!Array.isArray(t.open_revs))return r(c.error(c.UNKNOWN_ERROR,"function_clause"));i=t.open_revs;for(var f=0;f<i.length;f++){var l=i[f];if("string"!=typeof l||!/^\d+-/.test(l))return r(c.error(c.BAD_REQUEST,"Invalid rev format"))}o()}}),s.prototype.getAttachment=a.adapterFun("getAttachment",function(e,t,n,r){var o=this;n instanceof Function&&(r=n,n={}),n=a.clone(n),this._get(e,n,function(e,i){return e?r(e):i.doc._attachments&&i.doc._attachments[t]?(n.ctx=i.ctx,void o._getAttachment(i.doc._attachments[t],n,r)):r(c.MISSING_DOC)})}),s.prototype.allDocs=a.adapterFun("allDocs",function(e,t){if("function"==typeof e&&(t=e,e={}),e=a.clone(e),e.skip="undefined"!=typeof e.skip?e.skip:0,"keys"in e){if(!Array.isArray(e.keys))return t(new TypeError("options.keys must be an array"));var n=["startkey","endkey","key"].filter(function(t){return t in e})[0];if(n)return void t(c.error(c.QUERY_PARSE_ERROR,"Query parameter `"+n+"` is not compatible with multi-get"));if("http"!==this.type())return i(this,e,t)}return this._allDocs(e,t)}),s.prototype.changes=function(e,t){return"function"==typeof e&&(t=e,e={}),new d(this,e,t)},s.prototype.close=a.adapterFun("close",function(e){return this._closed=!0,this._close(e)}),s.prototype.info=a.adapterFun("info",function(e){var t=this;this._info(function(n,r){return n?e(n):(r.db_name=r.db_name||t._db_name,r.auto_compaction=!(!t._auto_compaction||"http"===t.type()),void e(null,r))})}),s.prototype.id=a.adapterFun("id",function(e){return this._id(e)}),s.prototype.type=function(){return"function"==typeof this._type?this._type():this.adapter},s.prototype.bulkDocs=a.adapterFun("bulkDocs",function(e,t,n){if("function"==typeof t&&(n=t,t={}),t=a.clone(t),Array.isArray(e)&&(e={docs:e}),!e||!e.docs||!Array.isArray(e.docs))return n(c.MISSING_BULK_DOCS);for(var r=0;r<e.docs.length;++r)if("object"!=typeof e.docs[r]||Array.isArray(e.docs[r]))return n(c.NOT_AN_OBJECT);return e=a.clone(e),"new_edits"in t||(t.new_edits="new_edits"in e?e.new_edits:!0),t.new_edits||"http"===this.type()||e.docs.sort(function(e,t){var n=a.compare(e._id,t._id);if(0!==n)return n;var r=e._revisions?e._revisions.start:0,o=t._revisions?t._revisions.start:0;return a.compare(r,o)}),e.docs.forEach(function(e){e._deleted&&delete e._attachments}),this._bulkDocs(e,t,this.autoCompact(function(e,r){return e?n(e):(t.new_edits||(r=r.filter(function(e){return e.error})),void n(null,r))}))}),s.prototype.registerDependentDatabase=a.adapterFun("registerDependentDatabase",function(e,t){function n(t){return t.dependentDbs=t.dependentDbs||{},t.dependentDbs[e]?!1:(t.dependentDbs[e]=!0,t)}var r={};this.__opts.db&&(r.db=this.__opts.db),this._adapter&&(r.adapter=this._adapter);var o=new this.constructor(e,r);l(this,"_local/_pouch_dependentDbs",n,function(e){return e?t(e):t(null,{db:o})})})},{"./changes":6,"./deps/errors":12,"./deps/upsert":16,"./merge":20,"./utils":25,events:33}],2:[function(e,t){(function(n,r){"use strict";function o(e){return/^_(design|local)/.test(e)?e:encodeURIComponent(e)}function i(e){return e._attachments&&Object.keys(e._attachments)?d.Promise.all(Object.keys(e._attachments).map(function(t){var n=e._attachments[t];if(n.data&&"string"!=typeof n.data){if(v)return new d.Promise(function(e){d.readAsBinaryString(n.data,function(t){n.data=d.btoa(t),e()})});n.data=n.data.toString("base64")}})):d.Promise.resolve()}function s(e,t){if(/http(s?):/.test(e)){var n=d.parseUri(e);n.remote=!0,(n.user||n.password)&&(n.auth={username:n.user,password:n.password});var r=n.path.replace(/(^\/|\/$)/g,"").split("/");if(n.db=r.pop(),n.path=r.join("/"),t=t||{},t=d.clone(t),n.headers=t.headers||{},t.auth||n.auth){var o=t.auth||n.auth,i=d.btoa(o.username+":"+o.password);n.headers.Authorization="Basic "+i}return t.headers&&(n.headers=t.headers),n}return{host:"",path:"/",db:e,auth:!1}}function a(e,t){return u(e,e.db+"/"+t)}function u(e,t){if(e.remote){var n=e.path?"/":"";return e.protocol+"://"+e.host+":"+e.port+"/"+e.path+n+t}return"/"+t}function c(e,t){function n(e,t){var n=d.extend({},_,e);return p(n.method+" "+n.url),d.ajax(n,t)}function c(e){return e.split("/").map(encodeURIComponent).join("/")}var g=this;g.getHost=e.getHost?e.getHost:s;var y=g.getHost(e.name,e),m=a(y,"");g.getUrl=function(){return m},g.getHeaders=function(){return d.clone(y.headers)};var _=e.ajax||{};e=d.clone(e);var b=function(){n({headers:y.headers,method:"PUT",url:m},function(e){e&&401===e.status?n({headers:y.headers,method:"HEAD",url:m},function(e){e?t(e):t(null,g)}):e&&412!==e.status?t(e):t(null,g)})};e.skipSetup||n({headers:y.headers,method:"GET",url:m},function(e){e?404===e.status?(d.explain404("PouchDB is just detecting if the remote DB exists."),b()):t(e):t(null,g)}),g.type=function(){return"http"},g.id=d.adapterFun("id",function(e){n({headers:y.headers,method:"GET",url:u(y,"")},function(t,n){var r=n&&n.uuid?n.uuid+y.db:a(y,"");e(null,r)})}),g.request=d.adapterFun("request",function(e,t){e.headers=y.headers,e.url=a(y,e.url),n(e,t)}),g.compact=d.adapterFun("compact",function(e,t){"function"==typeof e&&(t=e,e={}),e=d.clone(e),n({headers:y.headers,url:a(y,"_compact"),method:"POST"},function(){function n(){g.info(function(r,o){o.compact_running?setTimeout(n,e.interval||200):t()})}"function"==typeof t&&n()})}),g._info=function(e){n({headers:y.headers,method:"GET",url:a(y,"")},function(t,n){t?e(t):(n.host=a(y,""),e(null,n))})},g.get=d.adapterFun("get",function(e,t,r){"function"==typeof t&&(r=t,t={}),t=d.clone(t),void 0===t.auto_encode&&(t.auto_encode=!0);var i=[];t.revs&&i.push("revs=true"),t.revs_info&&i.push("revs_info=true"),t.local_seq&&i.push("local_seq=true"),t.open_revs&&("all"!==t.open_revs&&(t.open_revs=JSON.stringify(t.open_revs)),i.push("open_revs="+t.open_revs)),t.attachments&&i.push("attachments=true"),t.rev&&i.push("rev="+t.rev),t.conflicts&&i.push("conflicts="+t.conflicts),i=i.join("&"),i=""===i?"":"?"+i,t.auto_encode&&(e=o(e));var s={headers:y.headers,method:"GET",url:a(y,e+i)},u=e.split("/");(u.length>1&&"_design"!==u[0]&&"_local"!==u[0]||u.length>2&&"_design"===u[0]&&"_local"!==u[0])&&(s.binary=!0),n(s,function(e,t,n){return e?r(e):void r(null,t,n)})}),g.remove=d.adapterFun("remove",function(e,t,r,i){var s;"string"==typeof t?(s={_id:e,_rev:t},"function"==typeof r&&(i=r,r={})):(s=e,"function"==typeof t?(i=t,r={}):(i=r,r=t));var u=s._rev||r.rev;n({headers:y.headers,method:"DELETE",url:a(y,o(s._id))+"?rev="+u},i)}),g.getAttachment=d.adapterFun("getAttachment",function(e,t,n,r){"function"==typeof n&&(r=n,n={}),n=d.clone(n),void 0===n.auto_encode&&(n.auto_encode=!0),n.auto_encode&&(e=o(e)),n.auto_encode=!1,g.get(e+"/"+c(t),n,r)}),g.removeAttachment=d.adapterFun("removeAttachment",function(e,t,r,i){var s=a(y,o(e)+"/"+c(t))+"?rev="+r;n({headers:y.headers,method:"DELETE",url:s},i)}),g.putAttachment=d.adapterFun("putAttachment",function(e,t,i,s,u,f){"function"==typeof u&&(f=u,u=s,s=i,i=null),"undefined"==typeof u&&(u=s,s=i,i=null);var l=o(e)+"/"+c(t),p=a(y,l);if(i&&(p+="?rev="+i),"string"==typeof s){var g;try{g=d.atob(s)}catch(m){return f(d.extend({},h.BAD_ARG,{reason:"Attachments need to be base64 encoded"}))}s=v?d.createBlob([d.fixBinary(g)],{type:u}):g?new r(g,"binary"):""}var _={headers:d.clone(y.headers),method:"PUT",url:p,processData:!1,body:s,timeout:6e4};_.headers["Content-Type"]=u,n(_,f)}),g.put=d.adapterFun("put",d.getArguments(function(e){var t,r,s,u=e.shift(),c="_id"in u,f=e.pop();return"object"!=typeof u||Array.isArray(u)?f(h.NOT_AN_OBJECT):(u=d.clone(u),void i(u).then(function(){for(;;)if(t=e.shift(),r=typeof t,"string"!==r||c?"string"!==r||!c||"_rev"in u?"object"===r&&(s=d.clone(t)):u._rev=t:(u._id=t,c=!0),!e.length)break;s=s||{};var i=d.invalidIdError(u._id);if(i)throw i;var l=[];s&&"undefined"!=typeof s.new_edits&&l.push("new_edits="+s.new_edits),l=l.join("&"),""!==l&&(l="?"+l),n({headers:y.headers,method:"PUT",url:a(y,o(u._id))+l,body:u},function(e,t){return e?f(e):(t.ok=!0,void f(null,t))})})["catch"](f))})),g.post=d.adapterFun("post",function(e,t,n){return"function"==typeof t&&(n=t,t={}),t=d.clone(t),"object"!=typeof e?n(h.NOT_AN_OBJECT):("_id"in e||(e._id=d.uuid()),void g.put(e,t,function(e,t){return e?n(e):(t.ok=!0,void n(null,t))}))}),g._bulkDocs=function(e,t,r){"undefined"!=typeof t.new_edits&&(e.new_edits=t.new_edits),d.Promise.all(e.docs.map(i)).then(function(){n({headers:y.headers,method:"POST",url:a(y,"_bulk_docs"),body:e},function(e,t){return e?r(e):(t.forEach(function(e){e.ok=!0}),void r(null,t))})})["catch"](r)},g.allDocs=d.adapterFun("allDocs",function(e,t){"function"==typeof e&&(t=e,e={}),e=d.clone(e);var r,o=[],i="GET";if(e.conflicts&&o.push("conflicts=true"),e.descending&&o.push("descending=true"),e.include_docs&&o.push("include_docs=true"),e.attachments&&o.push("attachments=true"),e.key&&o.push("key="+encodeURIComponent(JSON.stringify(e.key))),e.startkey&&o.push("startkey="+encodeURIComponent(JSON.stringify(e.startkey))),e.endkey&&o.push("endkey="+encodeURIComponent(JSON.stringify(e.endkey))),"undefined"!=typeof e.inclusive_end&&o.push("inclusive_end="+!!e.inclusive_end),"undefined"!=typeof e.limit&&o.push("limit="+e.limit),"undefined"!=typeof e.skip&&o.push("skip="+e.skip),o=o.join("&"),""!==o&&(o="?"+o),"undefined"!=typeof e.keys){var s="keys="+encodeURIComponent(JSON.stringify(e.keys));s.length+o.length+1<=l?o+=(-1!==o.indexOf("?")?"&":"?")+s:(i="POST",r=JSON.stringify({keys:e.keys}))}n({headers:y.headers,method:i,url:a(y,"_all_docs"+o),body:r},t)}),g._changes=function(e){var t="batch_size"in e?e.batch_size:f;e=d.clone(e),e.timeout=e.timeout||3e4;var r={timeout:e.timeout-5e3},o="undefined"!=typeof e.limit?e.limit:!1;0===o&&(o=1);var i;i="returnDocs"in e?e.returnDocs:!0;var s=o;if(e.style&&(r.style=e.style),(e.include_docs||e.filter&&"function"==typeof e.filter)&&(r.include_docs=!0),e.attachments&&(r.attachments=!0),e.continuous&&(r.feed="longpoll"),e.conflicts&&(r.conflicts=!0),e.descending&&(r.descending=!0),e.filter&&"string"==typeof e.filter&&(r.filter=e.filter,"_view"===e.filter&&e.view&&"string"==typeof e.view&&(r.view=e.view)),e.query_params&&"object"==typeof e.query_params)for(var u in e.query_params)e.query_params.hasOwnProperty(u)&&(r[u]=e.query_params[u]);var c,p="GET";if(e.doc_ids){r.filter="_doc_ids";var v=JSON.stringify(e.doc_ids);v.length<l?r.doc_ids=v:(p="POST",c={doc_ids:e.doc_ids})}if(e.continuous&&g._useSSE)return g.sse(e,r,i);var m,_,b=function(i,u){if(!e.aborted){r.since=i,e.descending?o&&(r.limit=s):r.limit=!o||s>t?t:s;var f="?"+Object.keys(r).map(function(e){return e+"="+r[e]}).join("&"),l={headers:y.headers,method:p,url:a(y,"_changes"+f),timeout:e.timeout,body:c};_=i,e.aborted||(m=n(l,u))}},w=10,E=0,S={results:[]},A=function(n,r){if(!e.aborted){var a=0;if(r&&r.results){a=r.results.length,S.last_seq=r.last_seq;var u={};u.query=e.query_params,r.results=r.results.filter(function(t){s--;var n=d.filterChange(e)(t);return n&&(i&&S.results.push(t),d.call(e.onChange,t)),n})}else if(n)return e.aborted=!0,void d.call(e.complete,n);r&&r.last_seq&&(_=r.last_seq);var c=o&&0>=s||r&&t>a||e.descending;if((!e.continuous||o&&0>=s)&&c)d.call(e.complete,null,S);else{n?E+=1:E=0;var f=1<<E,l=w*f,p=e.maximumWait||3e4;if(l>p)return void d.call(e.complete,n||h.UNKNOWN_ERROR);setTimeout(function(){b(_,A)},l)}}};return b(e.since||0,A),{cancel:function(){e.aborted=!0,m&&m.abort()}}},g.sse=function(e,t,n){function r(t){var r=JSON.parse(t.data);n&&c.results.push(r),c.last_seq=r.seq,d.call(e.onChange,r)}function o(t){return u.removeEventListener("message",r,!1),l===!1?(g._useSSE=!1,void(f=g._changes(e))):(u.close(),void d.call(e.complete,t))}t.feed="eventsource",t.since=e.since||0,t.limit=e.limit,delete t.timeout;var i="?"+Object.keys(t).map(function(e){return e+"="+t[e]}).join("&"),s=a(y,"_changes"+i),u=new EventSource(s),c={results:[],last_seq:!1},f=!1,l=!1;return u.addEventListener("message",r,!1),u.onopen=function(){l=!0},u.onerror=o,{cancel:function(){return f?f.cancel():(u.removeEventListener("message",r,!1),void u.close())}}},g._useSSE=!1,g.revsDiff=d.adapterFun("revsDiff",function(e,t,r){"function"==typeof t&&(r=t,t={}),n({headers:y.headers,method:"POST",url:a(y,"_revs_diff"),body:JSON.stringify(e)},r)}),g._close=function(e){e()},g.destroy=d.adapterFun("destroy",function(e){n({url:a(y,""),method:"DELETE",headers:y.headers},function(t,n){t?(g.emit("error",t),e(t)):(g.emit("destroyed"),e(null,n))})})}var f=25,l=1800,d=e("../utils"),h=e("../deps/errors"),p=e("debug")("pouchdb:http"),v="undefined"==typeof n||n.browser;c.destroy=d.toPromise(function(e,t,n){var r=s(e,t);t=t||{},"function"==typeof t&&(n=t,t={}),t=d.clone(t),t.headers=r.headers,t.method="DELETE",t.url=a(r,"");var o=t.ajax||{};t=d.extend({},t,o),d.ajax(t,n)}),c.valid=function(){return!0},t.exports=c}).call(this,e("_process"),e("buffer").Buffer)},{"../deps/errors":12,"../utils":25,_process:34,buffer:29,debug:35}],3:[function(e,t){(function(n,r){"use strict";function o(e,t,n){try{e.apply(t,n)}catch(r){window.PouchDB&&window.PouchDB.emit("error",r)}}function i(){if(!q.running&&q.queue.length){q.running=!0;var e=q.queue.shift();e.action(function(t,r){o(e.callback,this,[t,r]),q.running=!1,n.nextTick(i)})}}function s(e){return function(t){var n=t.target&&t.target.error&&t.target.error.name||t.target;e(m.error(m.IDB_ERROR,n,t.type))}}function a(e,t,n){var r={data:_.stringify(e)};return r.winningRev=t,r.deletedOrLocal=n?"1":"0",r.id=e.id,r}function u(e){if(!e)return null;if(!e.data)return e;var t=_.parse(e.data);return t.winningRev=e.winningRev,t.deletedOrLocal="1"===e.deletedOrLocal,t}function c(e,t,n,r){n?e?"string"!=typeof e?g.readAsBinaryString(e,function(e){r(g.btoa(e))}):r(e):r(""):e?"string"!=typeof e?r(e):(e=g.fixBinary(atob(e)),r(g.createBlob([e],{type:t}))):r(g.createBlob([""],{type:t}))}function f(e,t,n,r){function o(){++a===s.length&&r&&r()}function i(e,t){var r=e._attachments[t],i=r.digest;n.objectStore(S).get(i).onsuccess=function(e){r.body=e.target.result.body,o()}}var s=Object.keys(e._attachments||{});if(!s.length)return r&&r();var a=0;s.forEach(function(n){t.attachments&&t.include_docs?i(e,n):(e._attachments[n].stub=!0,o())})}function l(e){return g.Promise.all(e.map(function(e){if(e.doc&&e.doc._attachments){var t=Object.keys(e.doc._attachments);return g.Promise.all(t.map(function(t){var n=e.doc._attachments[t];if("body"in n){var r=n.body,o=n.content_type;return new g.Promise(function(i){c(r,o,!0,function(r){e.doc._attachments[t]=g.extend(g.pick(n,["digest","content_type"]),{data:r}),i()})})}}))}}))}function d(e,t){var n=this;q.queue.push({action:function(t){h(n,e,t)},callback:t}),i()}function h(e,t,o){function i(e){var t=e.createObjectStore(w,{keyPath:"id"});t.createIndex("seq","seq",{unique:!0}),e.createObjectStore(E,{autoIncrement:!0}).createIndex("_doc_id_rev","_doc_id_rev",{unique:!0}),e.createObjectStore(S,{keyPath:"digest"}),e.createObjectStore(k,{keyPath:"id",autoIncrement:!1}),e.createObjectStore(x),t.createIndex("deletedOrLocal","deletedOrLocal",{unique:!1}),e.createObjectStore(T,{keyPath:"_id"});var n=e.createObjectStore(A,{autoIncrement:!0});n.createIndex("seq","seq"),n.createIndex("digestSeq","digestSeq",{unique:!0})}function h(e,t){var n=e.objectStore(w);n.createIndex("deletedOrLocal","deletedOrLocal",{unique:!1}),n.openCursor().onsuccess=function(e){var r=e.target.result;if(r){var o=r.value,i=g.isDeleted(o);o.deletedOrLocal=i?"1":"0",n.put(o),r["continue"]()}else t()}}function p(e){e.createObjectStore(T,{keyPath:"_id"}).createIndex("_doc_id_rev","_doc_id_rev",{unique:!0})}function _(e,t){var n=e.objectStore(T),o=e.objectStore(w),i=e.objectStore(E),s=o.openCursor();s.onsuccess=function(e){var s=e.target.result;if(s){var a=s.value,u=a.id,c=g.isLocalId(u),f=y.winningRev(a);if(c){var l=u+"::"+f,d=u+"::",h=u+"::~",p=i.index("_doc_id_rev"),v=r.IDBKeyRange.bound(d,h,!1,!1),m=p.openCursor(v);m.onsuccess=function(e){if(m=e.target.result){var t=m.value;t._doc_id_rev===l&&n.put(t),i["delete"](m.primaryKey),m["continue"]()}else o["delete"](s.primaryKey),s["continue"]()}}else s["continue"]()}else t&&t()}}function q(e){var t=e.createObjectStore(A,{autoIncrement:!0});t.createIndex("seq","seq"),t.createIndex("digestSeq","digestSeq",{unique:!0})}function R(e){var t=e.objectStore(E),n=e.objectStore(S),r=e.objectStore(A),o=n.count();o.onsuccess=function(e){var n=e.target.result;n&&(t.openCursor().onsuccess=function(e){var t=e.target.result;if(t){for(var n=t.value,o=t.primaryKey,i=Object.keys(n._attachments||{}),s={},a=0;a<i.length;a++){var u=n._attachments[i[a]];s[u.digest]=!0}var c=Object.keys(s);for(a=0;a<c.length;a++){var f=c[a];r.put({seq:o,digestSeq:f+"::"+o})}t["continue"]()}})}}function O(e,t,n){function o(){n(null,{total_rows:e,offset:t.skip,rows:I})}var i="startkey"in t?t.startkey:!1,s="endkey"in t?t.endkey:!1,a="key"in t?t.key:!1,c=t.skip||0,d="number"==typeof t.limit?t.limit:-1,h=t.inclusive_end!==!1,p="descending"in t&&t.descending?"prev":null,v=!1;p&&i&&s&&(v=s,s=!1);var _=null;try{i&&s?_=r.IDBKeyRange.bound(i,s,!1,!h):i?_=p?r.IDBKeyRange.upperBound(i):r.IDBKeyRange.lowerBound(i):s?_=p?r.IDBKeyRange.lowerBound(s,!h):r.IDBKeyRange.upperBound(s,!h):a&&(_=r.IDBKeyRange.only(a))}catch(b){return"DataError"===b.name&&0===b.code?n(null,{total_rows:e,offset:t.skip,rows:[]}):n(m.error(m.IDB_ERROR,b.name,b.message))}var A=[w,E];t.attachments&&A.push(S);var k=B.transaction(A,"readonly");k.oncomplete=function(){t.attachments?l(I).then(o):o()};var T=k.objectStore(w),x=p?T.openCursor(_,p):T.openCursor(_),I=[];x.onsuccess=function(e){function n(e,n){var o={id:e.id,key:e.id,value:{rev:i}};t.include_docs&&(o.doc=n,o.doc._rev=i,o.doc._doc_id_rev&&delete o.doc._doc_id_rev,t.conflicts&&(o.doc._conflicts=y.collectConflicts(e)),f(o.doc,t,k));var s=g.isDeleted(e,i);if("ok"===t.deleted)s&&(o.value.deleted=!0,o.doc=null),I.push(o);else if(!s&&c--<=0){if(v){if(h&&o.key<v)return;if(!h&&o.key<=v)return}if(I.push(o),0===--d)return}r["continue"]()}if(e.target.result){var r=e.target.result,o=u(r.value),i=o.winningRev||y.winningRev(o);if(t.include_docs){var s=k.objectStore(E).index("_doc_id_rev"),a=o.id+"::"+i;s.get(a).onsuccess=function(e){n(u(r.value),e.target.result)}}else n(o)}}}function D(e){if(-1!==P)return e(null,P);var t,n=B.transaction([w],"readonly"),o=n.objectStore(w).index("deletedOrLocal");o.count(r.IDBKeyRange.only("0")).onsuccess=function(e){t=e.target.result},n.onerror=s(e),n.oncomplete=function(){P=t,e(null,P)}}var C=t.name,N=null,j=!1,B=null,P=-1;e.type=function(){return"idb"},e._id=g.toPromise(function(e){e(null,N)}),e._bulkDocs=function(t,n,r){function o(){g.processDocs(_,e,q,x,I,h,n)}function i(e){function t(){++n===_.length&&e()}if(!_.length)return e();var n=0;_.forEach(function(e){if(e._id&&g.isLocalId(e._id))return t();var n=e.metadata.id,r=x.objectStore(w).get(n);r.onsuccess=function(e){var r=u(e.target.result);r&&q.set(n,r),t()}})}function c(){if(!R){var e=I.map(function(e){if(!Object.keys(e).length)return{ok:!0};if(e.error)return e;var t=e.metadata,n=y.winningRev(t);return{ok:!0,id:t.id,rev:n}});d.Changes.notify(C),P=-1,r(null,e)}}function f(e,t){var n=x.objectStore([S]).get(e);n.onsuccess=function(n){if(n.target.result)t();else{var r=new Error("unknown stub attachment with digest "+e);r.status=412,t(r)}}}function l(e){function t(){++o===n.length&&e(r)}var n=[];if(_.forEach(function(e){e.data&&e.data._attachments&&Object.keys(e.data._attachments).forEach(function(t){var r=e.data._attachments[t];r.stub&&n.push(r.digest)})}),!n.length)return e();var r,o=0;n.forEach(function(e){f(e,function(e){e&&!r&&(r=e),t()})})}function h(e,t,n,r,o,i){function s(e){l||(e?(l=e,r(l)):d===m.length&&f())}function u(e){d++,s(e)}function c(t,n){function r(){++i===s.length&&n()}function o(n){var o=e.data._attachments[n].digest,i=x.objectStore(A).put({seq:t,digestSeq:o+"::"+t});i.onsuccess=r,i.onerror=function(e){e.preventDefault(),e.stopPropagation(),r()}}var i=0,s=Object.keys(e.data._attachments||{});if(!s.length)return n();for(var a=0;a<s.length;a++)o(s[a])}function f(){function o(o){var s=e.metadata,u=o.target.result;s.seq=u,delete s.rev;var f=a(s,t,n),l=x.objectStore(w).put(f);l.onsuccess=function(){delete s.deletedOrLocal,delete s.winningRev,I[i]=e,q.set(e.metadata.id,e.metadata),c(u,function(){g.call(r)})}}e.data._doc_id_rev=y;var s=x.objectStore(E),u=s.index("_doc_id_rev"),f=s.put(e.data);f.onsuccess=o,f.onerror=function(t){t.preventDefault(),t.stopPropagation();var n=u.getKey(e.data._doc_id_rev);n.onsuccess=function(t){var n=s.put(e.data,t.target.result);n.onsuccess=o}}}var l=null,d=0,h=e.data._id=e.metadata.id,v=e.data._rev=e.metadata.rev,y=h+"::"+v;n&&(e.data._deleted=!0);var m=e.data._attachments?Object.keys(e.data._attachments):[];for(var _ in e.data._attachments)if(e.data._attachments[_].stub)d++,s();else{var b=e.data._attachments[_].data;delete e.data._attachments[_].data;var S=e.data._attachments[_].digest;p(S,b,u)}m.length||f()}function p(e,t,n){var r=x.objectStore(S);r.get(e).onsuccess=function(o){var i=o.target.result;if(i)return g.call(n);var s={digest:e,body:t};r.put(s).onsuccess=function(){g.call(n)}}}var v=n.new_edits,m=t.docs,_=m.map(function(e){if(e._id&&g.isLocalId(e._id))return e;var t=g.parseDoc(e,v);return t}),b=_.filter(function(e){return e.error});if(b.length)return r(b[0]);var x,I=new Array(_.length),q=new g.Map,R=!1,O=L?"blob":"base64";g.preprocessAttachments(_,O,function(e){if(e)return r(e);var t=[w,E,S,k,T,A];x=B.transaction(t,"readwrite"),x.onerror=s(r),x.ontimeout=s(r),x.oncomplete=c,l(function(e){return e?(R=!0,r(e)):void i(o)})})},e._get=function(e,t,n){function r(){n(s,{doc:o,metadata:i,ctx:a})}var o,i,s,a;t=g.clone(t),a=t.ctx?t.ctx:B.transaction([w,E,S],"readonly"),a.objectStore(w).get(e).onsuccess=function(e){if(i=u(e.target.result),!i)return s=m.MISSING_DOC,r();if(g.isDeleted(i)&&!t.rev)return s=m.error(m.MISSING_DOC,"deleted"),r();var n=a.objectStore(E),c=t.rev||i.winningRev||y.winningRev(i),f=i.id+"::"+c;n.index("_doc_id_rev").get(f).onsuccess=function(e){return o=e.target.result,o&&o._doc_id_rev&&delete o._doc_id_rev,o?void r():(s=m.MISSING_DOC,r())}}},e._getAttachment=function(e,t,n){var r;t=g.clone(t),r=t.ctx?t.ctx:B.transaction([w,E,S],"readonly");var o=e.digest,i=e.content_type;r.objectStore(S).get(o).onsuccess=function(e){var r=e.target.result.body;c(r,i,t.encode,function(e){n(null,e)})}},e._allDocs=function(e,t){D(function(n,r){return n?t(n):0===e.limit?t(null,{total_rows:r,offset:e.skip,rows:[]}):void O(r,e,t)})},e._info=function(e){D(function(t,n){if(t)return e(t);if(null===B){var r=new Error("db isn't open");return r.id="idbNull",e(r)}var o=0,i=B.transaction([E],"readonly");i.objectStore(E).openCursor(null,"prev").onsuccess=function(e){var t=e.target.result;o=t?t.key:0},i.oncomplete=function(){e(null,{doc_count:n,update_seq:o})}})},e._changes=function(t){function n(){var e=[w,E];t.attachments&&e.push(S),_=B.transaction(e,"readonly"),_.onerror=s(t.complete),_.oncomplete=i;var n;n=h?_.objectStore(E).openCursor(r.IDBKeyRange.lowerBound(t.since,!0),h):_.objectStore(E).openCursor(r.IDBKeyRange.lowerBound(t.since,!0)),n.onsuccess=o,n.onerror=onerror}function o(e){var n=e.target.result;if(n){var r=n.value;if(c&&!c.has(r._id))return n["continue"]();var o=_.objectStore(w);o.get(r._id).onsuccess=function(e){var o=u(e.target.result);p<o.seq&&(p=o.seq);var i=o.winningRev||y.winningRev(o);if(r._rev!==i)return n["continue"]();delete r._doc_id_rev;var s=t.processChange(r,o,t);s.seq=n.key,k(s)&&(A++,m&&b.push(s),t.attachments&&t.include_docs?f(r,t,_,function(){l([s]).then(function(){t.onChange(s)})}):t.onChange(s)),A!==v&&n["continue"]()}}}function i(){function e(){t.complete(null,{results:b,last_seq:p})}t.continuous||(t.attachments?l(b).then(e):e())}if(t=g.clone(t),t.continuous){var a=C+":"+g.uuid();return d.Changes.addListener(C,a,e,t),d.Changes.notify(C),{cancel:function(){d.Changes.removeListener(C,a)}}}var c=t.doc_ids&&new g.Set(t.doc_ids),h=t.descending?"prev":null,p=0;t.since=t.since&&!h?t.since:0;var v="limit"in t?t.limit:-1;0===v&&(v=1);var m;m="returnDocs"in t?t.returnDocs:!0;var _,b=[],A=0,k=g.filterChange(t);n()},e._close=function(e){return null===B?e(m.NOT_OPEN):(B.close(),delete I[C],B=null,void e()) +},e._getRevisionTree=function(e,t){var n=B.transaction([w],"readonly"),r=n.objectStore(w).get(e);r.onsuccess=function(e){var n=u(e.target.result);n?t(null,n.rev_tree):t(m.MISSING_DOC)}},e._doCompaction=function(e,t,n){function o(){h.length&&h.forEach(function(e){var t=d.index("digestSeq").count(r.IDBKeyRange.bound(e+"::",e+"::ï¿¿",!1,!1));t.onsuccess=function(t){var n=t.target.result;n||l["delete"](e)}})}var i=B.transaction([w,E,S,A],"readwrite"),c=i.objectStore(w),f=i.objectStore(E),l=i.objectStore(S),d=i.objectStore(A),h=[];c.get(e).onsuccess=function(n){var s=u(n.target.result);y.traverseRevTree(s.rev_tree,function(e,n,r,o,i){var s=n+"-"+r;-1!==t.indexOf(s)&&(i.status="missing")});var c=t.length;t.forEach(function(t){var n=f.index("_doc_id_rev"),u=e+"::"+t;n.getKey(u).onsuccess=function(e){var t=e.target.result;if("number"==typeof t){f["delete"](t);var n=d.index("seq").openCursor(r.IDBKeyRange.only(t));n.onsuccess=function(e){var t=e.target.result;if(t){var n=t.value.digestSeq.split("::")[0];h.push(n),d["delete"](t.primaryKey),t["continue"]()}else if(c--,!c){var r=s.winningRev||y.winningRev(s),u=s.deletedOrLocal;i.objectStore(w).put(a(s,r,u)),o()}}}}})},i.onerror=s(n),i.oncomplete=function(){g.call(n)}},e._getLocal=function(e,t){var n=B.transaction([T],"readonly"),r=n.objectStore(T).get(e);r.onerror=s(t),r.onsuccess=function(e){var n=e.target.result;n?(delete n._doc_id_rev,t(null,n)):t(m.MISSING_DOC)}},e._putLocal=function(e,t,n){"function"==typeof t&&(n=t,t={}),delete e._revisions;var r=e._rev,o=e._id;e._rev=r?"0-"+(parseInt(r.split("-")[1],10)+1):"0-1";var i,a=t.ctx;a||(a=B.transaction([T],"readwrite"),a.onerror=s(n),a.oncomplete=function(){i&&n(null,i)});var u,c=a.objectStore(T);r?(u=c.get(o),u.onsuccess=function(o){var s=o.target.result;if(s&&s._rev===r){var a=c.put(e);a.onsuccess=function(){i={ok:!0,id:e._id,rev:e._rev},t.ctx&&n(null,i)}}else n(m.REV_CONFLICT)}):(u=c.add(e),u.onerror=function(e){n(m.REV_CONFLICT),e.preventDefault(),e.stopPropagation()},u.onsuccess=function(){i={ok:!0,id:e._id,rev:e._rev},t.ctx&&n(null,i)})},e._removeLocal=function(e,t){var n,r=B.transaction([T],"readwrite");r.oncomplete=function(){n&&t(null,n)};var o=e._id,i=r.objectStore(T),a=i.get(o);a.onerror=s(t),a.onsuccess=function(r){var s=r.target.result;s&&s._rev===e._rev?(i["delete"](o),n={ok:!0,id:o,rev:"0-0"}):t(m.MISSING_DOC)}};var U=I[C];if(U)return B=U.idb,N=U.instanceId,j=U.idStored,void n.nextTick(function(){o(null,e)});var F=r.indexedDB.open(C,b);"openReqList"in d||(d.openReqList={}),d.openReqList[C]=F,F.onupgradeneeded=function(e){var t=e.target.result;if(e.oldVersion<1)return void i(t);var n=e.currentTarget.transaction;e.oldVersion<4&&(q(t),e.oldVersion<3?(p(t),e.oldVersion<2?h(n,function(){_(n,function(){R(n)})}):_(n,function(){R(n)})):R(n))},F.onsuccess=function(t){B=t.target.result,B.onversionchange=function(){B.close(),delete I[C]},B.onabort=function(){B.close(),delete I[C]};var n=B.transaction([k,x],"readwrite"),r=n.objectStore(k).get(k);r.onsuccess=function(t){var r=function(){null!==L&&j&&(I[C]={idb:B,instanceId:N,idStored:j,loaded:!0},o(null,e))},i=t.target.result||{id:k};C+"_id"in i?(N=i[C+"_id"],j=!0,r()):(N=g.uuid(),i[C+"_id"]=N,n.objectStore(k).put(i).onsuccess=function(){j=!0,r()}),v||(v=new g.Promise(function(e){var t=g.createBlob([""],{type:"image/png"});n.objectStore(x).put(t,"key"),n.oncomplete=function(){n=B.transaction([k,x],"readwrite");var t=n.objectStore(x).get("key");t.onsuccess=function(t){var n=t.target.result,r=URL.createObjectURL(n);g.ajax({url:r,cache:!0,binary:!0},function(t,n){t&&405===t.status?e(!0):(e(!(!n||"image/png"!==n.type)),t&&404===t.status&&g.explain404("PouchDB is just detecting blob URL support.")),URL.revokeObjectURL(r)})}}})["catch"](function(){L=!1,r()})),v.then(function(e){L=e,r()})}},F.onerror=s(o)}function p(e,t,n){"openReqList"in d||(d.openReqList={}),d.Changes.removeAllListeners(e),d.openReqList[e]&&d.openReqList[e].result&&d.openReqList[e].result.close();var o=r.indexedDB.deleteDatabase(e);o.onsuccess=function(){d.openReqList[e]&&(d.openReqList[e]=null),g.hasLocalStorage()&&e in r.localStorage&&delete r.localStorage[e],delete I[e],n(null,{ok:!0})},o.onerror=s(n)}var v,g=e("../utils"),y=e("../merge"),m=e("../deps/errors"),_=e("vuvuzela"),b=4,w="document-store",E="by-sequence",S="attach-store",A="attach-seq-store",k="meta-store",T="local-store",x="detect-blob-support",I={},q={running:!1,queue:[]},L=null;d.valid=function(){var e="undefined"!=typeof openDatabase&&/Safari/.test(navigator.userAgent)&&!/Chrome/.test(navigator.userAgent);return!e&&r.indexedDB&&r.IDBKeyRange},d.destroy=g.toPromise(function(e,t,n){q.queue.push({action:function(n){p(e,t,n)},callback:n}),i()}),d.Changes=new g.Changes,t.exports=d}).call(this,e("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../deps/errors":12,"../merge":20,"../utils":25,_process:34,vuvuzela:67}],4:[function(e,t){t.exports=["idb","websql"]},{}],5:[function(e,t){(function(n){"use strict";function r(e){return"'"+e+"'"}function o(e){return e.replace(/\u0002/g,"").replace(/\u0001/g,"").replace(/\u0000/g,"")}function i(e){return e.replace(/\u0001\u0001/g,"\x00").replace(/\u0001\u0002/g,"").replace(/\u0002\u0002/g,"")}function s(e,t,n,r,o){function i(){++u===a.length&&o&&o()}function s(e,t){var o=e._attachments[t],s={encode:!0,ctx:r};n._getAttachment(o,s,function(n,r){e._attachments[t]=h.extend(h.pick(o,["digest","content_type"]),{data:r}),i()})}var a=Object.keys(e._attachments||{});if(!a.length)return o&&o();var u=0;a.forEach(function(n){t.attachments&&t.include_docs?s(e,n):(e._attachments[n].stub=!0,i())})}function a(e,t,n,r,o){return"SELECT "+e+" FROM "+("string"==typeof t?t:t.join(" JOIN "))+(n?" ON "+n:"")+(r?" WHERE "+("string"==typeof r?r:r.join(" AND ")):"")+(o?" ORDER BY "+o:"")}function u(e){return function(t){var n=t&&t.constructor.toString().match(/function ([^\(]+)/),r=n&&n[1]||t.type,o=t.target||t.message;e(v.error(v.WSQ_ERROR,o,r))}}function c(e){return delete e._id,delete e._rev,JSON.stringify(e)}function f(e,t,n){return e=JSON.parse(e),e._id=t,e._rev=n,e}function l(e){if("size"in e)return 1e6*e.size;var t=/Android/.test(window.navigator.userAgent);return t?5e6:1}function d(e,t){function r(){h.hasLocalStorage()&&(n.localStorage["_pouch__websqldb_"+K]=!0),t(null,H)}function m(e,t){e.executeSql(L),e.executeSql("ALTER TABLE "+S+" ADD COLUMN deleted TINYINT(1) DEFAULT 0",[],function(){e.executeSql(I),e.executeSql("ALTER TABLE "+E+" ADD COLUMN local TINYINT(1) DEFAULT 0",[],function(){e.executeSql("CREATE INDEX IF NOT EXISTS 'doc-store-local-idx' ON "+E+" (local, id)");var n="SELECT "+E+".winningseq AS seq, "+E+".json AS metadata FROM "+S+" JOIN "+E+" ON "+S+".seq = "+E+".winningseq";e.executeSql(n,[],function(e,n){for(var r=[],o=[],i=0;i<n.rows.length;i++){var s=n.rows.item(i),a=s.seq,u=JSON.parse(s.metadata);h.isDeleted(u)&&r.push(a),h.isLocalId(u.id)&&o.push(u.id)}e.executeSql("UPDATE "+E+"SET local = 1 WHERE id IN ("+o.map(function(){return"?"}).join(",")+")",o,function(){e.executeSql("UPDATE "+S+" SET deleted = 1 WHERE seq IN ("+r.map(function(){return"?"}).join(",")+")",r,t)})})})})}function N(e,t){var n="CREATE TABLE IF NOT EXISTS "+k+" (id UNIQUE, rev, json)";e.executeSql(n,[],function(){var n="SELECT "+E+".id AS id, "+S+".json AS data FROM "+S+" JOIN "+E+" ON "+S+".seq = "+E+".winningseq WHERE local = 1";e.executeSql(n,[],function(e,n){function r(){if(!o.length)return t(e);var n=o.shift(),i=JSON.parse(n.data)._rev;e.executeSql("INSERT INTO "+k+" (id, rev, json) VALUES (?,?,?)",[n.id,i,n.data],function(e){e.executeSql("DELETE FROM "+E+" WHERE id=?",[n.id],function(e){e.executeSql("DELETE FROM "+S+" WHERE seq=?",[n.seq],function(){r()})})})}for(var o=[],i=0;i<n.rows.length;i++)o.push(n.rows.item(i));r()})})}function j(e,t){function n(n){function r(){if(!n.length)return t(e);var o=n.shift(),i=y(o.hex,V),s=i.lastIndexOf("::"),a=i.substring(0,s),u=i.substring(s+2),c="UPDATE "+S+" SET doc_id=?, rev=? WHERE doc_id_rev=?";e.executeSql(c,[a,u,i],function(){r()})}r()}var r="ALTER TABLE "+S+" ADD COLUMN doc_id";e.executeSql(r,[],function(e){var t="ALTER TABLE "+S+" ADD COLUMN rev";e.executeSql(t,[],function(e){e.executeSql(q,[],function(e){var t="SELECT hex(doc_id_rev) as hex FROM "+S;e.executeSql(t,[],function(e,t){for(var r=[],o=0;o<t.rows.length;o++)r.push(t.rows.item(o));n(r)})})})})}function B(e,t){function n(e){var n="SELECT COUNT(*) AS cnt FROM "+A;e.executeSql(n,[],function(e,n){function r(){var n=a(C+", "+E+".id AS id",[E,S],D,null,E+".id ");n+=" LIMIT "+s+" OFFSET "+i,i+=s,e.executeSql(n,[],function(e,n){function o(e,t){var n=i[e]=i[e]||[];-1===n.indexOf(t)&&n.push(t)}if(!n.rows.length)return t(e);for(var i={},s=0;s<n.rows.length;s++)for(var a=n.rows.item(s),u=f(a.data,a.id,a.rev),c=Object.keys(u._attachments||{}),l=0;l<c.length;l++){var d=u._attachments[c[l]];o(d.digest,a.seq)}var h=[];if(Object.keys(i).forEach(function(e){var t=i[e];t.forEach(function(t){h.push([e,t])})}),!h.length)return r();var p=0;h.forEach(function(t){var n="INSERT INTO "+x+" (digest, seq) VALUES (?,?)";e.executeSql(n,t,function(){++p===h.length&&r()})})})}var o=n.rows.item(0).cnt;if(!o)return t(e);var i=0,s=10;r()})}var r="CREATE TABLE IF NOT EXISTS "+x+" (digest, seq INTEGER)";e.executeSql(r,[],function(e){e.executeSql(O,[],function(e){e.executeSql(R,[],n)})})}function P(e,t){var n="ALTER TABLE "+A+" ADD COLUMN escaped TINYINT(1) DEFAULT 0";e.executeSql(n,[],t)}function U(e,t){e.executeSql('SELECT HEX("a") AS hex',[],function(e,n){var r=n.rows.item(0).hex;V=2===r.length?"UTF-8":"UTF-16",t()})}function F(){for(;X.length>0;){var e=X.pop();e(null,W)}}function M(e,t){if(0===t){var n="CREATE TABLE IF NOT EXISTS "+T+" (dbid, db_version INTEGER)",r="CREATE TABLE IF NOT EXISTS "+A+" (digest UNIQUE, escaped TINYINT(1), body BLOB)",o="CREATE TABLE IF NOT EXISTS "+x+" (digest, seq INTEGER)",i="CREATE TABLE IF NOT EXISTS "+E+" (id unique, json, winningseq)",s="CREATE TABLE IF NOT EXISTS "+S+" (seq INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, json, deleted TINYINT(1), doc_id, rev)",a="CREATE TABLE IF NOT EXISTS "+k+" (id UNIQUE, rev, json)";e.executeSql(r),e.executeSql(a),e.executeSql(o,[],function(){e.executeSql(R),e.executeSql(O)}),e.executeSql(i,[],function(){e.executeSql(L),e.executeSql(s,[],function(){e.executeSql(I),e.executeSql(q),e.executeSql(n,[],function(){var t="INSERT INTO "+T+" (db_version, dbid) VALUES (?,?)";W=h.uuid();var n=[w,W];e.executeSql(t,n,function(){F()})})})})}else{var u=function(){var n=w>t;n&&e.executeSql("UPDATE "+T+" SET db_version = "+w);var r="SELECT dbid FROM "+T;e.executeSql(r,[],function(e,t){W=t.rows.item(0).dbid,F()})},c=[m,N,j,B,P,u],f=t,l=function(e){c[f-1](e,l),f++};l(e)}}function G(){Q.transaction(function(e){U(e,function(){J(e)})},u(t),r)}function J(e){var t="SELECT sql FROM sqlite_master WHERE tbl_name = "+T;e.executeSql(t,[],function(e,t){t.rows.length?/db_version/.test(t.rows.item(0).sql)?e.executeSql("SELECT db_version FROM "+T,[],function(e,t){var n=t.rows.item(0).db_version;M(e,n)}):e.executeSql("ALTER TABLE "+T+" ADD COLUMN db_version INTEGER",[],function(){M(e,1)}):M(e,0)})}function Y(e,t){if(-1!==$)return t($);var n=a("COUNT("+E+".id) AS 'num'",[E,S],D,S+".deleted=0");e.executeSql(n,[],function(e,n){$=n.rows.item(0).num,t($)})}var V,H=this,W=null,K=e.name,z=l(e),X=[],$=-1,Q=_(K,b,K,z);return Q?("function"!=typeof Q.readTransaction&&(Q.readTransaction=Q.transaction),h.isCordova()&&"undefined"!=typeof n?n.addEventListener(K+"_pouch",function Z(){n.removeEventListener(K+"_pouch",Z,!1),G()},!1):G(),H.type=function(){return"websql"},H._id=h.toPromise(function(e){e(null,W)}),H._info=function(e){Q.readTransaction(function(t){Y(t,function(n){var r="SELECT MAX(seq) AS seq FROM "+S;t.executeSql(r,[],function(t,r){var o=r.rows.item(0).seq||0;e(null,{doc_count:n,update_seq:o})})})},u(e))},H._bulkDocs=function(e,t,n){function r(){if(T)return n(T);var e=I.map(function(e){if(!Object.keys(e).length)return{ok:!0};if(e.error)return e;var t=e.metadata,n=p.winningRev(t);return{ok:!0,id:t.id,rev:n}});d.Changes.notify(K),$=-1,n(null,e)}function i(e,t){var n="SELECT count(*) as cnt FROM "+A+" WHERE digest=?";k.executeSql(n,[e],function(n,r){if(0===r.rows.item(0).cnt){var o=new Error("unknown stub attachment with digest "+e);o.status=412,t(o)}else t()})}function s(e){function t(){++o===n.length&&e(r)}var n=[];if(b.forEach(function(e){e.data&&e.data._attachments&&Object.keys(e.data._attachments).forEach(function(t){var r=e.data._attachments[t];r.stub&&n.push(r.digest)})}),!n.length)return e();var r,o=0;n.forEach(function(e){i(e,function(e){e&&!r&&(r=e),t()})})}function f(e,t,n,r,o,i){function s(){function t(e,t){function n(){return++i===s.length&&t(),!1}function o(t){var o="INSERT INTO "+x+" (digest, seq) VALUES (?,?)",i=[r._attachments[t].digest,e];k.executeSql(o,i,n,n)}var i=0,s=Object.keys(r._attachments||{});if(!s.length)return t();for(var a=0;a<s.length;a++)o(s[a])}var r=e.data,o=n?1:0,i=r._id,s=r._rev,u=c(r),f="INSERT INTO "+S+" (doc_id, rev, json, deleted) VALUES (?, ?, ?, ?);",d=[i,s,u,o];k.executeSql(f,d,function(e,n){var r=n.insertId;t(r,function(){l(e,r)})},function(){var e=a("seq",S,null,"doc_id=? AND rev=?");return k.executeSql(e,[i,s],function(e,n){var r=n.rows.item(0).seq,a="UPDATE "+S+" SET json=?, deleted=? WHERE doc_id=? AND rev=?;",c=[u,o,i,s];e.executeSql(a,c,function(e){t(r,function(){l(e,r)})})}),!1})}function u(e){d||(e?(d=e,r(d)):h===p.length&&s())}function f(e){h++,u(e)}function l(n,s){e.metadata.seq=s,delete e.metadata.rev;var a=o?"UPDATE "+E+" SET json=?, winningseq=(SELECT seq FROM "+S+" WHERE doc_id="+E+".id AND rev=?) WHERE id=?":"INSERT INTO "+E+" (id, winningseq, json) VALUES (?, ?, ?);",u=g.stringify(e.metadata),c=e.metadata.id,f=o?[u,t,c]:[c,s,u];n.executeSql(a,f,function(){I[i]=e,q.set(c,e.metadata),r()})}var d=null,h=0;e.data._id=e.metadata.id,e.data._rev=e.metadata.rev,n&&(e.data._deleted=!0);var p=e.data._attachments?Object.keys(e.data._attachments):[];for(var v in e.data._attachments)if(e.data._attachments[v].stub)h++,u();else{var m=e.data._attachments[v].data;delete e.data._attachments[v].data;var _=e.data._attachments[v].digest;y(_,m,f)}p.length||s()}function l(){h.processDocs(b,H,q,k,I,f,t)}function v(e){function t(){++n===b.length&&e()}if(!b.length)return e();var n=0;b.forEach(function(e){if(e._id&&h.isLocalId(e._id))return t();var n=e.metadata.id;k.executeSql("SELECT json FROM "+E+" WHERE id = ?",[n],function(e,r){if(r.rows.length){var o=g.parse(r.rows.item(0).json);q.set(n,o)}t()})})}function y(e,t,n){var r="SELECT digest FROM "+A+" WHERE digest=?";k.executeSql(r,[e],function(i,s){return s.rows.length?n():(r="INSERT INTO "+A+" (digest, body, escaped) VALUES (?,?,1)",void i.executeSql(r,[e,o(t)],function(){n()},function(){return n(),!1}))})}var m=t.new_edits,_=e.docs,b=_.map(function(e){if(e._id&&h.isLocalId(e._id))return e;var t=h.parseDoc(e,m);return t}),w=b.filter(function(e){return e.error});if(w.length)return n(w[0]);var k,T,I=new Array(b.length),q=new h.Map;h.preprocessAttachments(b,"binary",function(e){return e?n(e):void Q.transaction(function(e){k=e,s(function(e){e?T=e:v(l)})},u(n),r)})},H._get=function(e,t,n){function r(){n(s,{doc:o,metadata:i,ctx:l})}t=h.clone(t);var o,i,s;if(!t.ctx)return void Q.readTransaction(function(r){t.ctx=r,H._get(e,t,n)});var u,c,l=t.ctx;t.rev?(u=a(C,[E,S],E+".id="+S+".doc_id",[S+".doc_id=?",S+".rev=?"]),c=[e,t.rev]):(u=a(C,[E,S],D,E+".id=?"),c=[e]),l.executeSql(u,c,function(e,n){if(!n.rows.length)return s=v.MISSING_DOC,r();var a=n.rows.item(0);return i=g.parse(a.metadata),a.deleted&&!t.rev?(s=v.error(v.MISSING_DOC,"deleted"),r()):(o=f(a.data,i.id,a.rev),void r())})},H._allDocs=function(e,t){var n,r=[],o="startkey"in e?e.startkey:!1,i="endkey"in e?e.endkey:!1,c="key"in e?e.key:!1,l="descending"in e?e.descending:!1,d="limit"in e?e.limit:-1,h="skip"in e?e.skip:0,v=e.inclusive_end!==!1,y=[],m=[];if(c!==!1)m.push(E+".id = ?"),y.push(c);else if(o!==!1||i!==!1){if(o!==!1&&(m.push(E+".id "+(l?"<=":">=")+" ?"),y.push(o)),i!==!1){var _=l?">":"<";v&&(_+="="),m.push(E+".id "+_+" ?"),y.push(i)}c!==!1&&(m.push(E+".id = ?"),y.push(c))}"ok"!==e.deleted&&m.push(S+".deleted = 0"),Q.readTransaction(function(t){Y(t,function(o){if(n=o,0!==d){var i=a(C,[E,S],D,m,E+".id "+(l?"DESC":"ASC"));i+=" LIMIT "+d+" OFFSET "+h,t.executeSql(i,y,function(t,n){for(var o=0,i=n.rows.length;i>o;o++){var a=n.rows.item(o),u=g.parse(a.metadata),c=f(a.data,u.id,a.rev),l=c._rev,d={id:u.id,key:u.id,value:{rev:l}};if(e.include_docs&&(d.doc=c,d.doc._rev=l,e.conflicts&&(d.doc._conflicts=p.collectConflicts(u)),s(d.doc,e,H,t)),a.deleted){if("ok"!==e.deleted)continue;d.value.deleted=!0,d.doc=null}r.push(d)}})}})},u(t),function(){t(null,{total_rows:n,offset:e.skip,rows:r})})},H._changes=function(e){function t(){var t=[E+".winningseq > "+e.since],n=[];e.doc_ids&&(t.push(E+".id IN ("+e.doc_ids.map(function(){return"?"}).join(",")+")"),n=e.doc_ids);var d=a(C,[E,S],D,t,E+".winningseq "+(r?"DESC":"ASC")),p=h.filterChange(e);e.view||e.filter||(d+=" LIMIT "+o);var v=0;Q.readTransaction(function(t){t.executeSql(d,n,function(t,n){function r(t){return function(){e.onChange(t)}}for(var a=0,u=n.rows.length;u>a;a++){var d=n.rows.item(a),h=g.parse(d.metadata);v<d.seq&&(v=d.seq);var y=f(d.data,h.id,d.rev),m=e.processChange(y,h,e);if(m.seq=d.seq,p(m)&&(l++,i&&c.push(m),e.attachments&&e.include_docs?s(y,e,H,t,r(m)):r(m)()),l===o)break}})},u(e.complete),function(){e.continuous||e.complete(null,{results:c,last_seq:v})})}if(e=h.clone(e),e.continuous){var n=K+":"+h.uuid();return d.Changes.addListener(K,n,H,e),d.Changes.notify(K),{cancel:function(){d.Changes.removeListener(K,n)}}}var r=e.descending;e.since=e.since&&!r?e.since:0;var o="limit"in e?e.limit:-1;0===o&&(o=1);var i;i="returnDocs"in e?e.returnDocs:!0;var c=[],l=0;t()},H._close=function(e){e()},H._getAttachment=function(e,t,n){var r,o=t.ctx,s=e.digest,a=e.content_type,u="SELECT escaped, CASE WHEN escaped = 1 THEN body ELSE HEX(body) END AS body FROM "+A+" WHERE digest=?";o.executeSql(u,[s],function(e,o){var s=o.rows.item(0),u=s.escaped?i(s.body):y(s.body,V);t.encode?r=btoa(u):(u=h.fixBinary(u),r=h.createBlob([u],{type:a})),n(null,r)})},H._getRevisionTree=function(e,t){Q.readTransaction(function(n){var r="SELECT json AS metadata FROM "+E+" WHERE id = ?";n.executeSql(r,[e],function(e,n){if(n.rows.length){var r=g.parse(n.rows.item(0).metadata);t(null,r.rev_tree)}else t(v.MISSING_DOC)})})},H._doCompaction=function(e,t,n){return t.length?void Q.transaction(function(n){var r="SELECT json AS metadata FROM "+E+" WHERE id = ?";n.executeSql(r,[e],function(n,r){var o=g.parse(r.rows.item(0).metadata);p.traverseRevTree(o.rev_tree,function(e,n,r,o,i){var s=n+"-"+r;-1!==t.indexOf(s)&&(i.status="missing")});var i="UPDATE "+E+" SET json = ? WHERE id = ?";n.executeSql(i,[g.stringify(o),e])}),t.forEach(function(t){var r="SELECT seq FROM "+S+" WHERE doc_id=? AND rev=?";n.executeSql(r,[e,t],function(e,t){if(t.rows.length){var n=t.rows.item(0).seq,r="SELECT a1.digest AS digest FROM "+x+" a1 JOIN "+x+" a2 ON a1.digest=a2.digest WHERE a1.seq=? GROUP BY a1.digest HAVING COUNT(*) = 1";e.executeSql(r,[n],function(e,t){for(var r=[],o=0;o<t.rows.length;o++)r.push(t.rows.item(o).digest);e.executeSql("DELETE FROM "+S+" WHERE seq=?",[n]),e.executeSql("DELETE FROM "+x+" WHERE seq=?",[n]),r.forEach(function(t){e.executeSql("DELETE FROM "+x+" WHERE digest=?",[t]),e.executeSql("DELETE FROM "+A+" WHERE digest=?",[t])})})}})})},u(n),function(){n()}):n()},H._getLocal=function(e,t){Q.readTransaction(function(n){var r="SELECT json, rev FROM "+k+" WHERE id=?";n.executeSql(r,[e],function(n,r){if(r.rows.length){var o=r.rows.item(0),i=f(o.json,e,o.rev);t(null,i)}else t(v.MISSING_DOC)})})},H._putLocal=function(e,t,n){function r(e){var r,u;i?(r="UPDATE "+k+" SET rev=?, json=? WHERE id=? AND rev=?",u=[o,f,s,i]):(r="INSERT INTO "+k+" (id, rev, json) VALUES (?,?,?)",u=[s,o,f]),e.executeSql(r,u,function(e,r){r.rowsAffected?(a={ok:!0,id:s,rev:o},t.ctx&&n(null,a)):n(v.REV_CONFLICT)},function(){return n(v.REV_CONFLICT),!1})}"function"==typeof t&&(n=t,t={}),delete e._revisions;var o,i=e._rev,s=e._id;o=e._rev=i?"0-"+(parseInt(i.split("-")[1],10)+1):"0-1";var a,f=c(e);t.ctx?r(t.ctx):Q.transaction(function(e){r(e)},u(n),function(){a&&n(null,a)})},void(H._removeLocal=function(e,t){var n;Q.transaction(function(r){var o="DELETE FROM "+k+" WHERE id=? AND rev=?",i=[e._id,e._rev];r.executeSql(o,i,function(r,o){return o.rowsAffected?void(n={ok:!0,id:e._id,rev:"0-0"}):t(v.MISSING_DOC)})},u(t),function(){n&&t(null,n)})})):t(v.UNKNOWN_ERROR)}var h=e("../utils"),p=e("../merge"),v=e("../deps/errors"),g=e("vuvuzela"),y=e("../deps/parse-hex"),m={},_=h.getArguments(function(e){if("undefined"!=typeof n){if(n.navigator&&n.navigator.sqlitePlugin&&n.navigator.sqlitePlugin.openDatabase)return navigator.sqlitePlugin.openDatabase.apply(navigator.sqlitePlugin,e);if(n.sqlitePlugin&&n.sqlitePlugin.openDatabase)return n.sqlitePlugin.openDatabase.apply(n.sqlitePlugin,e);var t=m[e[0]];return t||(t=m[e[0]]=n.openDatabase.apply(n,e)),t}}),b=1,w=6,E=r("document-store"),S=r("by-sequence"),A=r("attach-store"),k=r("local-store"),T=r("metadata-store"),x=r("attach-seq-store"),I="CREATE INDEX IF NOT EXISTS 'by-seq-deleted-idx' ON "+S+" (seq, deleted)",q="CREATE UNIQUE INDEX IF NOT EXISTS 'by-seq-doc-id-rev' ON "+S+" (doc_id, rev)",L="CREATE INDEX IF NOT EXISTS 'doc-winningseq-idx' ON "+E+" (winningseq)",R="CREATE INDEX IF NOT EXISTS 'attach-seq-seq-idx' ON "+x+" (seq)",O="CREATE UNIQUE INDEX IF NOT EXISTS 'attach-seq-digest-idx' ON "+x+" (digest, seq)",D=S+".seq = "+E+".winningseq",C=S+".seq AS seq, "+S+".deleted AS deleted, "+S+".json AS data, "+S+".rev AS rev, "+E+".json AS metadata";d.valid=function(){if("undefined"!=typeof n){if(n.navigator&&n.navigator.sqlitePlugin&&n.navigator.sqlitePlugin.openDatabase)return!0;if(n.sqlitePlugin&&n.sqlitePlugin.openDatabase)return!0;if(n.openDatabase)return!0}return!1},d.destroy=h.toPromise(function(e,t,r){d.Changes.removeAllListeners(e);var o=l(t),i=_(e,b,e,o);i.transaction(function(e){var t=[E,S,A,T,k,x];t.forEach(function(t){e.executeSql("DROP TABLE IF EXISTS "+t,[])})},u(r),function(){h.hasLocalStorage()&&(delete n.localStorage["_pouch__websqldb_"+e],delete n.localStorage[e]),r(null,{ok:!0})})}),d.Changes=new h.Changes,t.exports=d}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../deps/errors":12,"../deps/parse-hex":14,"../merge":20,"../utils":25,vuvuzela:67}],6:[function(e,t){"use strict";function n(e,t,n){function r(){i.cancel()}a.call(this);var i=this;this.db=e,t=t?o.clone(t):{};var s=n||t.complete||function(){},u=t.complete=o.once(function(t,n){t?i.emit("error",t):i.emit("complete",n),i.removeAllListeners(),e.removeListener("destroyed",r)});s&&(i.on("complete",function(e){s(null,e)}),i.on("error",function(e){s(e)}));var c=t.onChange;c&&i.on("change",c),e.once("destroyed",r),t.onChange=function(e){t.isCancelled||(i.emit("change",e),i.startSeq&&i.startSeq<=e.seq&&(i.emit("uptodate"),i.startSeq=!1),e.deleted?i.emit("delete",e):1===e.changes.length&&"1-"===e.changes[0].rev.slice(0,2)?i.emit("create",e):i.emit("update",e))};var f=new o.Promise(function(e,n){t.complete=function(t,r){t?n(t):e(r)}});i.once("cancel",function(){c&&i.removeListener("change",c),t.complete(null,{status:"cancelled"})}),this.then=f.then.bind(f),this["catch"]=f["catch"].bind(f),this.then(function(e){u(null,e)},u),e.taskqueue.isReady?i.doChanges(t):e.taskqueue.addTask(function(){i.isCancelled?i.emit("cancel"):i.doChanges(t)})}function r(e,t,n){var r=[{rev:e._rev}];"all_docs"===n.style&&(r=i.collectLeaves(t.rev_tree).map(function(e){return{rev:e.rev}}));var s={id:t.id,changes:r,doc:e};return o.isDeleted(t,e._rev)&&(s.deleted=!0),n.conflicts&&(s.doc._conflicts=i.collectConflicts(t),s.doc._conflicts.length||delete s.doc._conflicts),s}var o=e("./utils"),i=e("./merge"),s=e("./deps/errors"),a=e("events").EventEmitter,u=e("./evalFilter"),c=e("./evalView");t.exports=n,o.inherits(n,a),n.prototype.cancel=function(){this.isCancelled=!0,this.db.taskqueue.isReady&&this.emit("cancel")},n.prototype.doChanges=function(e){var t=this,n=e.complete;if(e=o.clone(e),"live"in e&&!("continuous"in e)&&(e.continuous=e.live),e.processChange=r,"latest"===e.since&&(e.since="now"),e.since||(e.since=0),"now"===e.since)return void this.db.info().then(function(r){return t.isCancelled?void n(null,{status:"cancelled"}):(e.since=r.update_seq-1,void t.doChanges(e))},n);if(e.continuous&&"now"!==e.since&&this.db.info().then(function(e){t.startSeq=e.update_seq-1},function(e){if("idbNull"!==e.id)throw e}),"http"!==this.db.type()&&e.filter&&"string"==typeof e.filter&&!e.doc_ids)return this.filterChanges(e);"descending"in e||(e.descending=!1),e.limit=0===e.limit?1:e.limit,e.complete=n;var i=this.db._changes(e);if(i&&"function"==typeof i.cancel){var s=t.cancel;t.cancel=o.getArguments(function(e){i.cancel(),s.apply(this,e)})}},n.prototype.filterChanges=function(e){var t=this,n=e.complete;if("_view"===e.filter){if(!e.view||"string"!=typeof e.view){var r=new Error("`view` filter parameter is not provided.");return r.status=s.BAD_REQUEST.status,r.name=s.BAD_REQUEST.name,r.error=!0,void n(r)}var o=e.view.split("/");this.db.get("_design/"+o[0],function(r,i){if(t.isCancelled)return void n(null,{status:"cancelled"});if(r)return void n(r);if(i&&i.views&&i.views[o[1]]){var a=c(i.views[o[1]].map);return e.filter=a,void t.doChanges(e)}var u=i.views?"missing json key: "+o[1]:"missing json key: views";r||(r=new Error(u),r.status=s.MISSING_DOC.status,r.name=s.MISSING_DOC.name,r.error=!0),n(r)})}else{var i=e.filter.split("/");this.db.get("_design/"+i[0],function(r,o){if(t.isCancelled)return void n(null,{status:"cancelled"});if(r)return void n(r);if(o&&o.filters&&o.filters[i[1]]){var a=u(o.filters[i[1]]);return e.filter=a,void t.doChanges(e)}var c=o&&o.filters?"missing json key: "+i[1]:"missing json key: filters";return r||(r=new Error(c),r.status=s.MISSING_DOC.status,r.name=s.MISSING_DOC.name,r.error=!0),void n(r)})}}},{"./deps/errors":12,"./evalFilter":18,"./evalView":19,"./merge":20,"./utils":25,events:33}],7:[function(e,t){"use strict";function n(e,t,n,r){return e.get(t)["catch"](function(n){if(404===n.status)return"http"===e.type()&&o.explain404("PouchDB is just checking if a remote checkpoint exists."),{_id:t};throw n}).then(function(t){return r.cancelled?void 0:(t.last_seq=n,e.put(t))})}function r(e,t,n,r){this.src=e,this.target=t,this.id=n,this.returnValue=r}var o=e("./utils");r.prototype.writeCheckpoint=function(e){var t=this;return this.updateTarget(e).then(function(){return t.updateSource(e)})},r.prototype.updateTarget=function(e){return n(this.target,this.id,e,this.returnValue)},r.prototype.updateSource=function(e){var t=this;return this.readOnlySource?o.Promise.resolve(!0):n(this.src,this.id,e,this.returnValue)["catch"](function(e){var n="number"==typeof e.status&&4===Math.floor(e.status/100);if(n)return t.readOnlySource=!0,!0;throw e})},r.prototype.getCheckpoint=function(){var e=this;return e.target.get(e.id).then(function(t){return e.src.get(e.id).then(function(e){return t.last_seq===e.last_seq?e.last_seq:0},function(n){if(404===n.status&&t.last_seq)return e.src.put({_id:e.id,last_seq:0}).then(function(){return 0},function(n){return 401===n.status?(e.readOnlySource=!0,t.last_seq):0});throw n})})["catch"](function(e){if(404!==e.status)throw e;return 0})},t.exports=r},{"./utils":25}],8:[function(e,t){(function(n){"use strict";function r(e){e&&n.debug&&console.error(e)}function o(e,t,n){if(!(this instanceof o))return new o(e,t,n);var c=this;("function"==typeof t||"undefined"==typeof t)&&(n=t,t={}),e&&"object"==typeof e&&(t=e,e=void 0),"undefined"==typeof n&&(n=r),t=t||{},this.__opts=t;var f=n;c.auto_compaction=t.auto_compaction,c.prefix=o.prefix,i.call(c),c.taskqueue=new a;var l=new u(function(r,i){n=function(e,t){return e?i(e):(delete t.then,void r(t))},t=s.clone(t);var a,u,f=t.name||e;return function(){try{if("string"!=typeof f)throw u=new Error("Missing/invalid DB name"),u.code=400,u;if(a=o.parseAdapter(f,t),t.originalName=f,t.name=a.name,t.prefix&&"http"!==a.adapter&&"https"!==a.adapter&&(t.name=t.prefix+t.name),t.adapter=t.adapter||a.adapter,c._adapter=t.adapter,c._db_name=f,!o.adapters[t.adapter])throw u=new Error("Adapter is missing"),u.code=404,u;if(!o.adapters[t.adapter].valid())throw u=new Error("Invalid Adapter"),u.code=404,u}catch(e){c.taskqueue.fail(e),c.changes=s.toPromise(function(t){t.complete&&t.complete(e)})}}(),u?i(u):(c.adapter=t.adapter,c.replicate={},c.replicate.from=function(e,t,n){return c.constructor.replicate(e,c,t,n)},c.replicate.to=function(e,t,n){return c.constructor.replicate(c,e,t,n)},c.sync=function(e,t,n){return c.constructor.sync(c,e,t,n)},c.replicate.sync=c.sync,c.destroy=s.adapterFun("destroy",function(e){var t=this;t.info(function(n,r){return n?e(n):void t.constructor.destroy(r.db_name,e)})}),o.adapters[t.adapter].call(c,t,function(e){function r(e){"destroyed"===e&&(c.emit("destroyed"),o.removeListener(f,r))}return e?void(n&&(c.taskqueue.fail(e),n(e))):(o.on(f,r),c.emit("created",c),o.emit("created",t.originalName),c.taskqueue.ready(c),void n(null,c))}),t.skipSetup&&c.taskqueue.ready(c),void(s.isCordova()&&cordova.fireWindowEvent(t.name+"_pouch",{})))});l.then(function(e){f(null,e)},f),c.then=l.then.bind(l),c["catch"]=l["catch"].bind(l)}var i=e("./adapter"),s=e("./utils"),a=e("./taskqueue"),u=s.Promise;s.inherits(o,i),o.debug=e("debug"),t.exports=o}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./adapter":1,"./taskqueue":24,"./utils":25,debug:35}],9:[function(e,t){"use strict";function n(e,t){function n(t,n,r){if(e.binary||e.json||!e.processData||"string"==typeof t){if(!e.binary&&e.json&&"string"==typeof t)try{t=JSON.parse(t)}catch(o){return r(o)}}else t=JSON.stringify(t);Array.isArray(t)&&(t=t.map(function(e){var t;return e.ok?e:e.error&&"conflict"===e.error?(t=i.REV_CONFLICT,t.id=e.id,t):e.error&&"forbidden"===e.error?(t=i.FORBIDDEN,t.id=e.id,t.reason=e.reason,t):e.missing?(t=i.MISSING_DOC,t.missing=e.missing,t):e})),r(null,t,n)}function a(e,t){var n,r,o,s;try{n=JSON.parse(e.responseText);for(s in i)if(i.hasOwnProperty(s)&&i[s].name===n.error){o=i[s];break}o||(o=i.UNKNOWN_ERROR,e.status&&(o.status=e.status),e.statusText&&(e.name=e.statusText)),r=i.error(o,n.reason)}catch(a){for(var s in i)if(i.hasOwnProperty(s)&&i[s].status===e.status){o=i[s];break}o||(o=i.UNKNOWN_ERROR,e.status&&(o.status=e.status),e.statusText&&(e.name=e.statusText)),r=i.error(o)}e.withCredentials&&0===e.status&&(r.status=405,r.statusText="Method Not Allowed"),t(r)}var u=!1,c=s.getArguments(function(e){u||(t.apply(this,e),u=!0)});"function"==typeof e&&(c=e,e={}),e=s.clone(e);var f={method:"GET",headers:{},json:!0,processData:!0,timeout:1e4,cache:!1};if(e=s.extend(!0,f,e),"GET"===e.method&&!e.cache){var l=-1!==e.url.indexOf("?");e.url+=(l?"&":"?")+"_nonce="+s.uuid(16)}var d,h;h=e.xhr?new e.xhr:new XMLHttpRequest,h.open(e.method,e.url),h.withCredentials=!0,e.json&&(e.headers.Accept="application/json",e.headers["Content-Type"]=e.headers["Content-Type"]||"application/json",e.body&&e.processData&&"string"!=typeof e.body&&(e.body=JSON.stringify(e.body))),e.binary&&(h.responseType="arraybuffer");var p=function(e,t,n){var r="";if(n){var o=new Date;o.setTime(o.getTime()+24*n*60*60*1e3),r="; expires="+o.toGMTString()}document.cookie=e+"="+t+r+"; path=/"};for(var v in e.headers)if("Cookie"===v){var g=e.headers[v].split("=");p(g[0],g[1],10)}else h.setRequestHeader(v,e.headers[v]);"body"in e||(e.body=null);var y=function(){u||(h.abort(),a(h,c))};return h.onreadystatechange=function(){if(4===h.readyState&&!u)if(clearTimeout(d),h.status>=200&&h.status<300){var t;t=e.binary?o([h.response||""],{type:h.getResponseHeader("Content-Type")}):h.responseText,n(t,h,c)}else a(h,c)},e.timeout>0&&(d=setTimeout(y,e.timeout),h.onprogress=function(){clearTimeout(d),d=setTimeout(y,e.timeout) +},"undefined"==typeof r&&(r=-1!==Object.keys(h).indexOf("upload")),r&&(h.upload.onprogress=h.onprogress)),e.body&&e.body instanceof Blob?s.readAsBinaryString(e.body,function(e){h.send(s.fixBinary(e))}):h.send(e.body),{abort:y}}var r,o=e("./blob.js"),i=e("./errors"),s=e("../utils");t.exports=n},{"../utils":25,"./blob.js":10,"./errors":12}],10:[function(e,t){(function(e){"use strict";function n(t,n){t=t||[],n=n||{};try{return new Blob(t,n)}catch(r){if("TypeError"!==r.name)throw r;for(var o=e.BlobBuilder||e.MSBlobBuilder||e.MozBlobBuilder||e.WebKitBlobBuilder,i=new o,s=0;s<t.length;s+=1)i.append(t[s]);return i.getBlob(n.type)}}t.exports=n}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],11:[function(e,t,n){"use strict";function r(){this.store={}}function o(e){if(this.store=new r,e&&Array.isArray(e))for(var t=0,n=e.length;n>t;t++)this.add(e[t])}n.Map=r,n.Set=o,r.prototype.mangle=function(e){if("string"!=typeof e)throw new TypeError("key must be a string but Got "+e);return"$"+e},r.prototype.unmangle=function(e){return e.substring(1)},r.prototype.get=function(e){var t=this.mangle(e);return t in this.store?this.store[t]:void 0},r.prototype.set=function(e,t){var n=this.mangle(e);return this.store[n]=t,!0},r.prototype.has=function(e){var t=this.mangle(e);return t in this.store},r.prototype["delete"]=function(e){var t=this.mangle(e);return t in this.store?(delete this.store[t],!0):!1},r.prototype.forEach=function(e){var t=this,n=Object.keys(t.store);n.forEach(function(n){var r=t.store[n];n=t.unmangle(n),e(r,n)})},o.prototype.add=function(e){return this.store.set(e,!0)},o.prototype.has=function(e){return this.store.has(e)},o.prototype["delete"]=function(e){return this.store["delete"](e)}},{}],12:[function(e,t,n){"use strict";function r(e){this.status=e.status,this.name=e.error,this.message=e.reason,this.error=!0}r.prototype__proto__=Error.prototype,r.prototype.toString=function(){return JSON.stringify({status:this.status,name:this.name,message:this.message})},n.UNAUTHORIZED=new r({status:401,error:"unauthorized",reason:"Name or password is incorrect."}),n.MISSING_BULK_DOCS=new r({status:400,error:"bad_request",reason:"Missing JSON list of 'docs'"}),n.MISSING_DOC=new r({status:404,error:"not_found",reason:"missing"}),n.REV_CONFLICT=new r({status:409,error:"conflict",reason:"Document update conflict"}),n.INVALID_ID=new r({status:400,error:"invalid_id",reason:"_id field must contain a string"}),n.MISSING_ID=new r({status:412,error:"missing_id",reason:"_id is required for puts"}),n.RESERVED_ID=new r({status:400,error:"bad_request",reason:"Only reserved document ids may start with underscore."}),n.NOT_OPEN=new r({status:412,error:"precondition_failed",reason:"Database not open"}),n.UNKNOWN_ERROR=new r({status:500,error:"unknown_error",reason:"Database encountered an unknown error"}),n.BAD_ARG=new r({status:500,error:"badarg",reason:"Some query argument is invalid"}),n.INVALID_REQUEST=new r({status:400,error:"invalid_request",reason:"Request was invalid"}),n.QUERY_PARSE_ERROR=new r({status:400,error:"query_parse_error",reason:"Some query parameter is invalid"}),n.DOC_VALIDATION=new r({status:500,error:"doc_validation",reason:"Bad special document member"}),n.BAD_REQUEST=new r({status:400,error:"bad_request",reason:"Something wrong with the request"}),n.NOT_AN_OBJECT=new r({status:400,error:"bad_request",reason:"Document must be a JSON object"}),n.DB_MISSING=new r({status:404,error:"not_found",reason:"Database not found"}),n.IDB_ERROR=new r({status:500,error:"indexed_db_went_bad",reason:"unknown"}),n.WSQ_ERROR=new r({status:500,error:"web_sql_went_bad",reason:"unknown"}),n.LDB_ERROR=new r({status:500,error:"levelDB_went_went_bad",reason:"unknown"}),n.FORBIDDEN=new r({status:403,error:"forbidden",reason:"Forbidden by design doc validate_doc_update function"}),n.error=function(e,t,n){function r(){this.message=t,n&&(this.name=n)}return r.prototype=e,new r(t)}},{}],13:[function(e,t){(function(n,r){"use strict";function o(e,t,n){if("function"==typeof e.slice)return t?n?e.slice(t,n):e.slice(t):e.slice();t=Math.floor(t||0),n=Math.floor(n||0);var r=e.byteLength;if(t=0>t?Math.max(t+r,0):Math.min(r,t),n=0>n?Math.max(n+r,0):Math.min(r,n),0>=n-t)return new ArrayBuffer(0);var o=new ArrayBuffer(n-t),i=new Uint8Array(o),s=new Uint8Array(e,t,n-t);return i.set(s),o}function i(e){var t=[255&e,e>>>8&255,e>>>16&255,e>>>24&255];return t.map(function(e){return String.fromCharCode(e)}).join("")}function s(e){for(var t="",n=0;n<e.length;n++)t+=i(e[n]);return r.btoa(t)}var a=e("crypto"),u=e("spark-md5"),c=r.setImmediate||r.setTimeout,f=32768;t.exports=function(e,t){function r(e,t,n,r){d?e.appendBinary(t.substring(n,r)):e.append(o(t,n,r))}function i(){var n=g*p,o=n+p;if(n+p>=e.size&&(o=e.size),g++,v>g)r(y,e,n,o),c(i);else{r(y,e,n,o);var a=y.end(!0),u=s(a);t(null,u),y.destroy()}}if(!n.browser){var l=a.createHash("md5").update(e).digest("base64");return void t(null,l)}var d="string"==typeof e,h=d?e.length:e.byteLength,p=Math.min(f,h),v=Math.ceil(h/p),g=0,y=d?new u:new u.ArrayBuffer;i()}}).call(this,e("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{_process:34,crypto:28,"spark-md5":66}],14:[function(e,t){"use strict";function n(e){return decodeURIComponent(window.escape(e))}function r(e){return 65>e?e-48:e-55}function o(e,t,n){for(var o="";n>t;)o+=String.fromCharCode(r(e.charCodeAt(t++))<<4|r(e.charCodeAt(t++)));return o}function i(e,t,n){for(var o="";n>t;)o+=String.fromCharCode(r(e.charCodeAt(t+2))<<12|r(e.charCodeAt(t+3))<<8|r(e.charCodeAt(t))<<4|r(e.charCodeAt(t+1))),t+=4;return o}function s(e,t){return"UTF-8"===t?n(o(e,0,e.length)):i(e,0,e.length)}t.exports=s},{}],15:[function(e,t){"use strict";function n(e){for(var t=r,n=t.parser[t.strictMode?"strict":"loose"].exec(e),o={},i=14;i--;){var s=t.key[i],a=n[i]||"",u=-1!==["user","password"].indexOf(s);o[s]=u?decodeURIComponent(a):a}return o[t.q.name]={},o[t.key[12]].replace(t.q.parser,function(e,n,r){n&&(o[t.q.name][n]=r)}),o}var r={strictMode:!1,key:["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],q:{name:"queryKey",parser:/(?:^|&)([^&=]*)=?([^&]*)/g},parser:{strict:/^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,loose:/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/}};t.exports=n},{}],16:[function(e,t){"use strict";function n(e,t,n){return new o(function(o,i){return t&&"object"==typeof t&&(t=t._id),"string"!=typeof t?i(new Error("doc id is required")):void e.get(t,function(s,a){if(s)return 404!==s.status?i(s):o(r(e,n({_id:t}),n));var u=n(a);return u?void o(r(e,u,n)):o(a)})})}function r(e,t,r){return e.put(t)["catch"](function(o){if(409!==o.status)throw o;return n(e,t,r)})}var o=e("../utils").Promise;t.exports=function(e,t,r,o){return"function"!=typeof o?n(e,t,r):void n(e,t,r).then(function(e){o(null,e)},o)}},{"../utils":25}],17:[function(e,t){"use strict";function n(e){return 0|Math.random()*e}function r(e,t){t=t||o.length;var r="",i=-1;if(e){for(;++i<e;)r+=o[n(t)];return r}for(;++i<36;)switch(i){case 8:case 13:case 18:case 23:r+="-";break;case 19:r+=o[3&n(16)|8];break;default:r+=o[n(16)]}return r}var o="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split("");t.exports=r},{}],18:[function(_dereq_,module,exports){"use strict";function evalFilter(input){return eval(["(function () { return ",input," })()"].join(""))}module.exports=evalFilter},{}],19:[function(_dereq_,module,exports){"use strict";function evalView(input){return eval(["(function () {"," return function (doc) {"," var emitted = false;"," var emit = function (a, b) {"," emitted = true;"," };"," var view = "+input+";"," view(doc);"," if (emitted) {"," return true;"," }"," }","})()"].join("\n"))}module.exports=evalView},{}],20:[function(e,t){"use strict";function n(e){for(var t,n=e.shift(),r=[n.id,n.opts,[]],o=r;e.length;)n=e.shift(),t=[n.id,n.opts,[]],o[2].push(t),o=t;return r}function r(e,t){for(var n=[{tree1:e,tree2:t}],r=!1;n.length>0;){var o=n.pop(),i=o.tree1,s=o.tree2;(i[1].status||s[1].status)&&(i[1].status="available"===i[1].status||"available"===s[1].status?"available":"missing");for(var a=0;a<s[2].length;a++)if(i[2][0]){for(var u=!1,c=0;c<i[2].length;c++)i[2][c][0]===s[2][a][0]&&(n.push({tree1:i[2][c],tree2:s[2][a]}),u=!0);u||(r="new_branch",i[2].push(s[2][a]),i[2].sort())}else r="new_leaf",i[2][0]=s[2][a]}return{conflicts:r,tree:e}}function o(e,t,n){var o,i=[],s=!1,a=!1;return e.length?(e.forEach(function(e){if(e.pos===t.pos&&e.ids[0]===t.ids[0])o=r(e.ids,t.ids),i.push({pos:e.pos,ids:o.tree}),s=s||o.conflicts,a=!0;else if(n!==!0){var u=e.pos<t.pos?e:t,c=e.pos<t.pos?t:e,f=c.pos-u.pos,l=[],d=[];for(d.push({ids:u.ids,diff:f,parent:null,parentIdx:null});d.length>0;){var h=d.pop();0!==h.diff?h.ids&&h.ids[2].forEach(function(e,t){d.push({ids:e,diff:h.diff-1,parent:h.ids,parentIdx:t})}):h.ids[0]===c.ids[0]&&l.push(h)}var p=l[0];p?(o=r(p.ids,c.ids),p.parent[2][p.parentIdx]=o.tree,i.push({pos:u.pos,ids:u.ids}),s=s||o.conflicts,a=!0):i.push(e)}else i.push(e)}),a||i.push(t),i.sort(function(e,t){return e.pos-t.pos}),{tree:i,conflicts:s||"internal_node"}):{tree:[t],conflicts:"new_leaf"}}function i(e,t){var r=a.rootToLeaf(e).map(function(e){var r=e.ids.slice(-t);return{pos:e.pos+(e.ids.length-r.length),ids:n(r)}});return r.reduce(function(e,t){return o(e,t,!0).tree},[r.shift()])}var s=e("pouchdb-extend"),a={};a.merge=function(e,t,n){e=s(!0,[],e),t=s(!0,{},t);var r=o(e,t);return{tree:i(r.tree,n),conflicts:r.conflicts}},a.winningRev=function(e){var t=[];return a.traverseRevTree(e.rev_tree,function(e,n,r,o,i){e&&t.push({pos:n,id:r,deleted:!!i.deleted})}),t.sort(function(e,t){return e.deleted!==t.deleted?e.deleted>t.deleted?1:-1:e.pos!==t.pos?t.pos-e.pos:e.id<t.id?1:-1}),t[0].pos+"-"+t[0].id},a.traverseRevTree=function(e,t){for(var n,r=e.slice();n=r.pop();)for(var o=n.pos,i=n.ids,s=i[2],a=t(0===s.length,o,i[0],n.ctx,i[1]),u=0,c=s.length;c>u;u++)r.push({pos:o+1,ids:s[u],ctx:a})},a.collectLeaves=function(e){var t=[];return a.traverseRevTree(e,function(e,n,r,o,i){e&&t.unshift({rev:n+"-"+r,pos:n,opts:i})}),t.sort(function(e,t){return t.pos-e.pos}),t.map(function(e){delete e.pos}),t},a.collectConflicts=function(e){var t=a.winningRev(e),n=a.collectLeaves(e.rev_tree),r=[];return n.forEach(function(e){e.rev===t||e.opts.deleted||r.push(e.rev)}),r},a.rootToLeaf=function(e){var t=[];return a.traverseRevTree(e,function(e,n,r,o,i){if(o=o?o.slice(0):[],o.push({id:r,opts:i}),e){var s=n+1-o.length;t.unshift({pos:s,ids:o})}return o}),t},t.exports=a},{"pouchdb-extend":57}],21:[function(e,t,n){"use strict";function r(e,t){e=parseInt(e,10),t=parseInt(t,10),e!==e&&(e=0),t!==t||e>=t?t=(e||1)<<1:t+=1;var n=Math.random(),r=t-e;return~~(r*n+e)}function o(e){var t=0;return e||(t=2e3),r(e,t)}function i(e,t,n,r,i,s,a){return r.retry===!1?(i.emit("error",a),void i.removeAllListeners()):(r.default_back_off=r.default_back_off||0,r.retries=r.retries||0,"function"!=typeof r.back_off_function&&(r.back_off_function=o),r.retries++,r.max_retries&&r.retries>r.max_retries?(i.emit("error",new Error("tried "+r.retries+" times but replication failed")),void i.removeAllListeners()):(i.emit("requestError",a),"active"===i.state&&(i.emit("syncStopped"),i.state="stopped",i.once("syncRestarted",function(){r.current_back_off=r.default_back_off})),r.current_back_off=r.current_back_off||r.default_back_off,r.current_back_off=r.back_off_function(r.current_back_off),void setTimeout(function(){u(e,t,n,r,i)},r.current_back_off)))}function s(){d.call(this),this.cancelled=!1,this.state="pending";var e=this,t=new l.Promise(function(t,n){e.once("complete",t),e.once("error",n)});e.then=function(e,n){return t.then(e,n)},e["catch"]=function(e){return t["catch"](e)},e["catch"](function(){})}function a(e,t,n){var r=n.filter?n.filter.toString():"";return e.id().then(function(e){return t.id().then(function(t){var o=e+t+r+JSON.stringify(n.query_params)+n.doc_ids;return l.MD5(o).then(function(e){return e=e.replace(/\//g,".").replace(/\+/g,"_"),"_local/"+e})})})}function u(e,t,n,r,o,s){function a(){if(0!==T.docs.length){var e=T.docs;return n.bulkDocs({docs:e},{new_edits:!1}).then(function(e){if(P.cancelled)throw b(),new Error("cancelled");var t=[];e.forEach(function(e){if(e.error){s.doc_write_failures++;var n=new Error(e.reason||e.message||"Unknown reason");n.name=e.name||e.error,t.push(n)}}),s.errors=s.errors.concat(t),s.docs_written+=T.docs.length-t.length;var n=t.filter(function(e){return"unauthorized"!==e.name&&"forbidden"!==e.name});if(n.length>0){var r=new Error("bulkDocs error");throw r.other_errors=t,_("target.bulkDocs failed to write docs",r),new Error("bulkWrite partial failure")}},function(t){throw s.doc_write_failures+=e.length,t})}}function u(){for(var e=T.diffs,n=Object.keys(e)[0],r=e[n].missing,o=[],i=0;i<r.length;i+=p)o.push(r.slice(i,Math.min(r.length,i+p)));return l.Promise.all(o.map(function(r){return t.get(n,{revs:!0,open_revs:r,attachments:!0}).then(function(t){t.forEach(function(e){return P.cancelled?b():void(e.ok&&(s.docs_read++,T.pendingRevs++,T.docs.push(e.ok)))}),delete e[n]})}))}function c(){return Object.keys(T.diffs).length>0?u().then(c):l.Promise.resolve()}function f(){var e=Object.keys(T.diffs).filter(function(e){var t=T.diffs[e].missing;return 1===t.length&&"1-"===t[0].slice(0,2)});return t.allDocs({keys:e,include_docs:!0}).then(function(e){if(P.cancelled)throw b(),new Error("cancelled");e.rows.forEach(function(e){!e.doc||e.deleted||"1-"!==e.value.rev.slice(0,2)||e.doc._attachments&&0!==Object.keys(e.doc._attachments).length||(s.docs_read++,T.pendingRevs++,T.docs.push(e.doc),delete T.diffs[e.id])})})}function d(){return f().then(c)}function v(){return q=!0,U.writeCheckpoint(T.seq).then(function(){if(q=!1,P.cancelled)throw b(),new Error("cancelled");s.last_seq=O=T.seq,o.emit("change",l.clone(s)),T=void 0,A()})["catch"](function(e){throw q=!1,_("writeCheckpoint completed with error",e),e})}function g(){var e={};return T.changes.forEach(function(t){e[t.id]=t.changes.map(function(e){return e.rev})}),n.revsDiff(e).then(function(e){if(P.cancelled)throw b(),new Error("cancelled");T.diffs=e,T.pendingRevs=0})}function y(){if(!P.cancelled&&!T){if(0===x.length)return void m(!0);T=x.shift(),g().then(d).then(a).then(v).then(y)["catch"](function(e){_("batch processing terminated with error",e)})}}function m(e){return 0===I.changes.length?void(0!==x.length||T||((D&&F.live||L)&&o.emit("uptodate",l.clone(s)),L&&b())):void((e||L||I.changes.length>=C)&&(x.push(I),I={seq:0,changes:[],docs:[]},y()))}function _(e,t){R||(s.ok=!1,s.status="aborting",s.errors.push(t),x=[],I={seq:0,changes:[],docs:[]},b())}function b(){if(!(R||P.cancelled&&(s.status="cancelled",q))){s.status=s.status||"complete",s.end_time=new Date,s.last_seq=O,R=P.cancelled=!0;var a=s.errors.filter(function(e){return"unauthorized"!==e.name&&"forbidden"!==e.name});if(a.length>0){var u=s.errors.pop();s.errors.length>0&&(u.other_errors=s.errors),u.result=s,i(e,t,n,r,o,s,u)}else o.emit("complete",s),o.removeAllListeners()}}function w(e){return P.cancelled?b():(0!==I.changes.length||0!==x.length||T||o.emit("outofdate",l.clone(s)),I.seq=e.seq,I.changes.push(e),void m(0===x.length))}function E(e){return j=!1,P.cancelled?b():(F.since<e.last_seq?(F.since=e.last_seq,A()):D?(F.live=!0,A()):L=!0,void m(!0))}function S(e){return j=!1,P.cancelled?b():void _("changes rejected",e)}function A(){function e(){r.cancel()}function n(){o.removeListener("cancel",e)}if(!j&&!L&&x.length<N){j=!0,o.once("cancel",e);var r=t.changes(F).on("change",w);r.then(n,n),r.then(E)["catch"](S)}}function k(){U.getCheckpoint().then(function(e){O=e,F={since:O,limit:C,batch_size:C,style:"all_docs",doc_ids:B,returnDocs:!1},r.filter&&(F.filter=r.filter),r.query_params&&(F.query_params=r.query_params),A()})["catch"](function(e){_("getCheckpoint rejected with ",e)})}var T,x=[],I={seq:0,changes:[],docs:[]},q=!1,L=!1,R=!1,O=0,D=r.continuous||r.live||!1,C=r.batch_size||100,N=r.batches_limit||10,j=!1,B=r.doc_ids,P={cancelled:!1},U=new h(t,n,e,P);s=s||{ok:!0,start_time:new Date,docs_read:0,docs_written:0,doc_write_failures:0,errors:[]};var F={};o.ready(t,n),o.once("cancel",b),"function"==typeof r.onChange&&o.on("change",r.onChange),"function"==typeof r.complete&&(o.once("error",r.complete),o.once("complete",function(e){r.complete(null,e)})),"undefined"==typeof r.since?k():(q=!0,U.writeCheckpoint(r.since).then(function(){return q=!1,P.cancelled?void b():(O=r.since,void k())})["catch"](function(e){throw q=!1,_("writeCheckpoint completed with error",e),e}))}function c(e,t){var n=t.PouchConstructor;return"string"==typeof e?new n(e):e.then?e:l.Promise.resolve(e)}function f(e,t,n,r){"function"==typeof n&&(r=n,n={}),"undefined"==typeof n&&(n={}),n.complete||(n.complete=r||function(){}),n=l.clone(n),n.continuous=n.continuous||n.live,n.retry=n.retry||!1,n.PouchConstructor=n.PouchConstructor||this;var o=new s(n);return c(e,n).then(function(e){return c(t,n).then(function(t){return a(e,t,n).then(function(r){u(r,e,t,n,o)})})})["catch"](function(e){o.emit("error",e),n.complete(e)}),o}var l=e("./utils"),d=e("events").EventEmitter,h=e("./checkpointer"),p=50;l.inherits(s,d),s.prototype.cancel=function(){this.cancelled=!0,this.state="cancelled",this.emit("cancel")},s.prototype.ready=function(e,t){function n(){o.cancel()}function r(){e.removeListener("destroyed",n),t.removeListener("destroyed",n)}var o=this;this.once("change",function(){"pending"===this.state?(o.state="active",o.emit("syncStarted")):"stopped"===o.state&&(o.state="active",o.emit("syncRestarted"))}),e.once("destroyed",n),t.once("destroyed",n),this.then(r,r)},n.toPouch=c,n.replicate=f},{"./checkpointer":7,"./utils":25,events:33}],22:[function(e,t){(function(n){"use strict";var r=e("./constructor"),o=e("./utils"),i=o.Promise,s=e("events").EventEmitter;r.adapters={},r.preferredAdapters=e("./adapters/preferredAdapters.js"),r.prefix="_pouch_";var a=new s,u=["on","addListener","emit","listeners","once","removeAllListeners","removeListener","setMaxListeners"];u.forEach(function(e){r[e]=a[e].bind(a)}),r.setMaxListeners(0),r.parseAdapter=function(e,t){var i,s,a=e.match(/([a-z\-]*):\/\/(.*)/);if(a){if(e=/http(s?)/.test(a[1])?a[1]+"://"+a[2]:a[2],i=a[1],!r.adapters[i].valid())throw"Invalid adapter";return{name:e,adapter:a[1]}}var u="idb"in r.adapters&&"websql"in r.adapters&&o.hasLocalStorage()&&n.localStorage["_pouch__websqldb_"+r.prefix+e];if("undefined"!=typeof t&&t.db)s="leveldb";else for(var c=0;c<r.preferredAdapters.length;++c)if(s=r.preferredAdapters[c],s in r.adapters){if(u&&"idb"===s)continue;break}if(i=r.adapters[s],s&&i){var f="use_prefix"in i?i.use_prefix:!0;return{name:f?r.prefix+e:e,adapter:s}}throw"No valid adapter found"},r.destroy=o.toPromise(function(e,t,n){function s(){c.destroy(d,t,function(t,o){t?n(t):(r.emit("destroyed",e),r.emit(e,"destroyed"),n(null,o||{ok:!0}))})}("function"==typeof t||"undefined"==typeof t)&&(n=t,t={}),e&&"object"==typeof e&&(t=e,e=void 0);var a=r.parseAdapter(t.name||e,t),u=a.name,c=r.adapters[a.adapter],f="use_prefix"in c?c.use_prefix:!0,l=f?u.replace(new RegExp("^"+r.prefix),""):u,d=("http"===a.adapter||"https"===a.adapter?"":t.prefix||"")+u,h=o.extend(!0,{},t,{adapter:a.adapter});new r(l,h,function(e,u){return e?n(e):void u.get("_local/_pouch_dependentDbs",function(e,u){if(e)return 404!==e.status?n(e):s();var c=u.dependentDbs,l=Object.keys(c).map(function(e){var n=f?e.replace(new RegExp("^"+r.prefix),""):e,i=o.extend(!0,t,{adapter:a.adapter});return r.destroy(n,i)});i.all(l).then(s,function(e){n(e)})})})}),r.allDbs=o.toPromise(function(e){var t=new Error("allDbs method removed");t.stats="400",e(t)}),r.adapter=function(e,t){t.valid()&&(r.adapters[e]=t)},r.plugin=function(e){Object.keys(e).forEach(function(t){r.prototype[t]=e[t]})},r.defaults=function(e){function t(t,n,i){("function"==typeof n||"undefined"==typeof n)&&(i=n,n={}),t&&"object"==typeof t&&(n=t,t=void 0),n=o.extend(!0,{},e,n),r.call(this,t,n,i)}return o.inherits(t,r),t.destroy=o.toPromise(function(t,n,i){return("function"==typeof n||"undefined"==typeof n)&&(i=n,n={}),t&&"object"==typeof t&&(n=t,t=void 0),n=o.extend(!0,{},e,n),r.destroy(t,n,i)}),u.forEach(function(e){t[e]=a[e].bind(a)}),t.setMaxListeners(0),t.preferredAdapters=r.preferredAdapters.slice(),Object.keys(r).forEach(function(e){e in t||(t[e]=r[e])}),t},t.exports=r}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./adapters/preferredAdapters.js":4,"./constructor":8,"./utils":25,events:33}],23:[function(e,t){"use strict";function n(e,t,n,s){return"function"==typeof n&&(s=n,n={}),"undefined"==typeof n&&(n={}),n=o.clone(n),n.PouchConstructor=n.PouchConstructor||this,e=i.toPouch(e,n),t=i.toPouch(t,n),new r(e,t,n,s)}function r(e,t,n,r){function i(e){h||(h=!0,f.emit("cancel",e))}function a(e){f.emit("change",{direction:"pull",change:e})}function u(e){f.emit("change",{direction:"push",change:e})}function c(e){return function(t,n){var r="change"===t&&(n===a||n===u),o="cancel"===t&&n===i,s=t in p&&n===p[t];(r||o||s)&&(t in v||(v[t]={}),v[t][e]=!0,2===Object.keys(v[t]).length&&f.removeAllListeners(t))}}var f=this;this.canceled=!1;var l,d;"onChange"in n&&(l=n.onChange,delete n.onChange),"function"!=typeof r||n.complete?"complete"in n&&(d=n.complete,delete n.complete):d=r,this.push=s(e,t,n),this.pull=s(t,e,n);var h=!1,p={},v={};this.on("newListener",function(e){"change"===e?(f.pull.on("change",a),f.push.on("change",u)):"cancel"===e?(f.pull.on("cancel",i),f.push.on("cancel",i)):"error"===e||"removeListener"===e||"complete"===e||e in p||(p[e]=function(t){f.emit(e,t)},f.pull.on(e,p[e]),f.push.on(e,p[e]))}),this.on("removeListener",function(e){"change"===e?(f.pull.removeListener("change",a),f.push.removeListener("change",u)):"cancel"===e?(f.pull.removeListener("cancel",i),f.push.removeListener("cancel",i)):e in p&&"function"==typeof p[e]&&(f.pull.removeListener(e,p[e]),f.push.removeListener(e,p[e]),delete p[e])}),this.pull.on("removeListener",c("pull")),this.push.on("removeListener",c("push"));var g=o.Promise.all([this.push,this.pull]).then(function(e){var t={push:e[0],pull:e[1]};return f.emit("complete",t),d&&d(null,t),f.removeAllListeners(),t},function(e){throw f.cancel(),f.emit("error",e),d&&d(e),f.removeAllListeners(),e});this.then=function(e,t){return g.then(e,t)},this["catch"]=function(e){return g["catch"](e)}}var o=e("./utils"),i=e("./replicate"),s=i.replicate,a=e("events").EventEmitter;o.inherits(r,a),t.exports=n,r.prototype.cancel=function(){this.canceled||(this.canceled=!0,this.push.cancel(),this.pull.cancel())}},{"./replicate":21,"./utils":25,events:33}],24:[function(e,t){"use strict";function n(){this.isReady=!1,this.failed=!1,this.queue=[]}t.exports=n,n.prototype.execute=function(){var e,t;if(this.failed)for(;e=this.queue.shift();)"function"!=typeof e?(t=e.parameters[e.parameters.length-1],"function"==typeof t?t(this.failed):"changes"===e.name&&"function"==typeof t.complete&&t.complete(this.failed)):e(this.failed);else if(this.isReady)for(;e=this.queue.shift();)"function"==typeof e?e():e.task=this.db[e.name].apply(this.db,e.parameters)},n.prototype.fail=function(e){this.failed=e,this.execute()},n.prototype.ready=function(e){return this.failed?!1:0===arguments.length?this.isReady:(this.isReady=e?!0:!1,this.db=e,void this.execute())},n.prototype.addTask=function(e,t){if("function"!=typeof e){var n={name:e,parameters:t};return this.queue.push(n),this.failed&&this.execute(),n}this.queue.push(e),this.failed&&this.execute()}},{}],25:[function(e,t,n){(function(t,r){function o(e){var t={};return e.forEach(function(e){t[e]=!0}),t}function i(){return"undefined"!=typeof chrome&&"undefined"!=typeof chrome.storage&&"undefined"!=typeof chrome.storage.local}function s(){if(!(this instanceof s))return new s;var e=this;f.call(this),this.isChrome=i(),this.listeners={},this.hasLocal=!1,this.isChrome||(this.hasLocal=n.hasLocalStorage()),this.isChrome?chrome.storage.onChanged.addListener(function(t){null!=t.db_name&&e.emit(t.dbName.newValue)}):this.hasLocal&&(r.addEventListener?r.addEventListener("storage",function(t){e.emit(t.key)}):r.attachEvent("storage",function(t){e.emit(t.key)}))}var a=e("./merge");n.extend=e("pouchdb-extend"),n.ajax=e("./deps/ajax"),n.createBlob=e("./deps/blob"),n.uuid=e("./deps/uuid"),n.getArguments=e("argsarray");var u=e("./deps/buffer"),c=e("./deps/errors"),f=e("events").EventEmitter,l=e("./deps/collections");n.Map=l.Map,n.Set=l.Set,n.Promise="function"==typeof r.Promise?r.Promise:e("bluebird");var d=n.Promise,h=o(["_id","_rev","_attachments","_deleted","_revisions","_revs_info","_conflicts","_deleted_conflicts","_local_seq","_rev_tree","_replication_id","_replication_state","_replication_state_time","_replication_state_reason","_replication_stats"]),p=o(["_attachments","_replication_id","_replication_state","_replication_state_time","_replication_state_reason","_replication_stats"]);n.lastIndexOf=function(e,t){for(var n=e.length-1;n>=0;n--)if(e.charAt(n)===t)return n;return-1},n.clone=function(e){return n.extend(!0,{},e)},n.pick=function(e,t){for(var n={},r=0,o=t.length;o>r;r++){var i=t[r];n[i]=e[i]}return n},n.inherits=e("inherits"),n.invalidIdError=function(e){var t;if(e?"string"!=typeof e?(t=new TypeError(c.INVALID_ID.message),t.status=400):/^_/.test(e)&&!/^_(design|local)/.test(e)&&(t=new TypeError(c.RESERVED_ID.message),t.status=400):(t=new TypeError(c.MISSING_ID.message),t.status=412),t)throw t},n.call=n.getArguments(function(e){if(e.length){var t=e.shift();"function"==typeof t&&t.apply(this,e)}}),n.isLocalId=function(e){return/^_local/.test(e)},n.isDeleted=function(e,t){t||(t=a.winningRev(e));var n=t.indexOf("-");-1!==n&&(t=t.substring(n+1));var r=!1;return a.traverseRevTree(e.rev_tree,function(e,n,o,i,s){o===t&&(r=!!s.deleted)}),r},n.revExists=function(e,t){var n=!1;return a.traverseRevTree(e.rev_tree,function(e,r,o){r+"-"+o===t&&(n=!0)}),n},n.filterChange=function(e){var t={},n=e.filter&&"function"==typeof e.filter;return t.query=e.query_params,function(r){if(e.filter&&n&&!e.filter.call(this,r.doc,t))return!1;if(e.include_docs){if(!e.attachments)for(var o in r.doc._attachments)r.doc._attachments.hasOwnProperty(o)&&(r.doc._attachments[o].stub=!0)}else delete r.doc;return!0}},n.parseDoc=function(e,t){var r,o,i,s,a={status:"available"};if(e._deleted&&(a.deleted=!0),t)if(e._id||(e._id=n.uuid()),o=n.uuid(32,16).toLowerCase(),e._rev){if(i=/^(\d+)-(.+)$/.exec(e._rev),!i)return s=new Error("bad_request"),s.message="Invalid rev format",s.error=!0,s;e._rev_tree=[{pos:parseInt(i[1],10),ids:[i[2],{status:"missing"},[[o,a,[]]]]}],r=parseInt(i[1],10)+1}else e._rev_tree=[{pos:1,ids:[o,a,[]]}],r=1;else if(e._revisions&&(e._rev_tree=[{pos:e._revisions.start-e._revisions.ids.length+1,ids:e._revisions.ids.reduce(function(e,t){return null===e?[t,a,[]]:[t,{status:"missing"},[e]]},null)}],r=e._revisions.start,o=e._revisions.ids[0]),!e._rev_tree){if(i=/^(\d+)-(.+)$/.exec(e._rev),!i)return s=new Error("bad_request"),s.message="Invalid rev format",s.error=!0,s;r=parseInt(i[1],10),o=i[2],e._rev_tree=[{pos:parseInt(i[1],10),ids:[i[2],a,[]]}]}n.invalidIdError(e._id),e._rev=[r,o].join("-");var u={metadata:{},data:{}};for(var f in e)if(e.hasOwnProperty(f)){var l="_"===f[0];if(l&&!h[f])throw s=new Error(c.DOC_VALIDATION.message+": "+f),s.status=c.DOC_VALIDATION.status,s;l&&!p[f]?u.metadata[f.slice(1)]=e[f]:u.data[f]=e[f]}return u},n.isCordova=function(){return"undefined"!=typeof cordova||"undefined"!=typeof PhoneGap||"undefined"!=typeof phonegap},n.hasLocalStorage=function(){if(i())return!1;try{return r.localStorage}catch(e){return!1}},n.Changes=s,n.inherits(s,f),s.prototype.addListener=function(e,t,r,o){function i(){r.changes({include_docs:o.include_docs,attachments:o.attachments,conflicts:o.conflicts,continuous:!1,descending:!1,filter:o.filter,doc_ids:o.doc_ids,view:o.view,since:o.since,query_params:o.query_params,onChange:function(e){e.seq>o.since&&!o.cancelled&&(o.since=e.seq,n.call(o.onChange,e))}})}this.listeners[t]||(this.listeners[t]=i,this.on(e,i))},s.prototype.removeListener=function(e,t){t in this.listeners&&f.prototype.removeListener.call(this,e,this.listeners[t])},s.prototype.notifyLocalWindows=function(e){this.isChrome?chrome.storage.local.set({dbName:e}):this.hasLocal&&(localStorage[e]="a"===localStorage[e]?"b":"a")},s.prototype.notify=function(e){this.emit(e),this.notifyLocalWindows(e)},n.atob=t.browser&&"atob"in r?function(e){return atob(e)}:function(e){var t=new u(e,"base64");if(t.toString("base64")!==e)throw"Cannot base64 encode full string";return t.toString("binary")},n.btoa=t.browser&&"btoa"in r?function(e){return btoa(e)}:function(e){return new u(e,"binary").toString("base64")},n.fixBinary=function(e){if(!t.browser)return e;for(var n=e.length,r=new ArrayBuffer(n),o=new Uint8Array(r),i=0;n>i;i++)o[i]=e.charCodeAt(i);return r},n.readAsBinaryString=function(e,t){var r=new FileReader,o="function"==typeof r.readAsBinaryString;r.onloadend=function(e){var r=e.target.result||"";return o?t(r):void t(n.arrayBufferToBinaryString(r))},o?r.readAsBinaryString(e):r.readAsArrayBuffer(e)},n.once=function(e){var t=!1;return n.getArguments(function(n){if(t)throw new Error("once called more than once");t=!0,e.apply(this,n)})},n.toPromise=function(e){return n.getArguments(function(r){var o,i=this,s="function"==typeof r[r.length-1]?r.pop():!1;s&&(o=function(e,n){t.nextTick(function(){s(e,n)})});var a=new d(function(t,o){var s;try{var a=n.once(function(e,n){e?o(e):t(n)});r.push(a),s=e.apply(i,r),s&&"function"==typeof s.then&&t(s)}catch(u){o(u)}});return o&&a.then(function(e){o(null,e)},o),a.cancel=function(){return this},a})},n.adapterFun=function(t,r){function o(e,t,n){if(i.enabled){for(var r=[e._db_name,t],o=0;o<n.length-1;o++)r.push(n[o]);i.apply(null,r);var s=n[n.length-1];n[n.length-1]=function(n,r){var o=[e._db_name,t];o=o.concat(n?["error",n]:["success",r]),i.apply(null,o),s(n,r)}}}var i=e("debug")("pouchdb:api");return n.toPromise(n.getArguments(function(e){if(this._closed)return d.reject(new Error("database is closed"));var i=this;return o(i,t,e),this.taskqueue.isReady?r.apply(this,e):new n.Promise(function(n,r){i.taskqueue.addTask(function(o){o?r(o):n(i[t].apply(i,e))})})}))},n.arrayBufferToBinaryString=function(e){for(var t="",n=new Uint8Array(e),r=n.byteLength,o=0;r>o;o++)t+=String.fromCharCode(n[o]);return t},n.cancellableFun=function(e,t,r){r=r?n.clone(!0,{},r):{};var o=new f,i=r.complete||function(){},s=r.complete=n.once(function(e,t){e?i(e):(o.emit("end",t),i(null,t)),o.removeAllListeners()}),a=r.onChange||function(){},u=0;t.on("destroyed",function(){o.removeAllListeners()}),r.onChange=function(e){a(e),e.seq<=u||(u=e.seq,o.emit("change",e),e.deleted?o.emit("delete",e):1===e.changes.length&&"1-"===e.changes[0].rev.slice(0,1)?o.emit("create",e):o.emit("update",e))};var c=new d(function(e,t){r.complete=function(n,r){n?t(n):e(r)}});return c.then(function(e){s(null,e)},s),c.cancel=function(){c.isCancelled=!0,t.taskqueue.isReady&&r.complete(null,{status:"cancelled"})},t.taskqueue.isReady?e(t,r,c):t.taskqueue.addTask(function(){c.isCancelled?r.complete(null,{status:"cancelled"}):e(t,r,c)}),c.on=o.on.bind(o),c.once=o.once.bind(o),c.addListener=o.addListener.bind(o),c.removeListener=o.removeListener.bind(o),c.removeAllListeners=o.removeAllListeners.bind(o),c.setMaxListeners=o.setMaxListeners.bind(o),c.listeners=o.listeners.bind(o),c.emit=o.emit.bind(o),c},n.MD5=n.toPromise(e("./deps/md5")),n.explain404=function(e){t.browser&&"console"in r&&"info"in console&&console.info("The above 404 is totally normal. "+e)},n.parseUri=e("./deps/parse-uri"),n.compare=function(e,t){return t>e?-1:e>t?1:0},n.updateDoc=function(e,t,r,o,i,s,u){if(n.revExists(e,t.metadata.rev))return r[o]=t,i(); +var f=n.isDeleted(e),l=n.isDeleted(t.metadata),d=/^1-/.test(t.metadata.rev);if(f&&!l&&u&&d){var h=t.data;h._rev=a.winningRev(e),h._id=t.metadata.id,t=n.parseDoc(h,u)}var p=a.merge(e.rev_tree,t.metadata.rev_tree[0],1e3),v=u&&(f&&l||!f&&"new_leaf"!==p.conflicts||f&&!l&&"new_branch"===p.conflicts);if(v){var g=c.REV_CONFLICT;return r[o]=g,i()}t.metadata.rev_tree=p.tree;var y=a.winningRev(t.metadata);l=n.isDeleted(t.metadata,y),s(t,y,l,i,!0,o)},n.processDocs=function(e,t,r,o,i,s,u){function f(e,t,r){var o=a.winningRev(e.metadata),f=n.isDeleted(e.metadata,o);return"was_delete"in u&&f?(i[t]=c.MISSING_DOC,r()):void s(e,o,f,r,!1,t)}if(e.length){var l=u.new_edits,d=new n.Map;e.forEach(function(e,r){if(e._id&&n.isLocalId(e._id))return void t[e._deleted?"_removeLocal":"_putLocal"](e,{ctx:o},function(e){i[r]=e?e:{}});var s=e.metadata.id;d.has(s)?d.get(s).push([e,r]):d.set(s,[[e,r]])}),d.forEach(function(e,t){function o(){++u<e.length&&a()}function a(){var a=e[u],c=a[0],d=a[1];r.has(t)?n.updateDoc(r.get(t),c,i,d,o,s,l):f(c,d,o)}var u=0;a()})}},n.preprocessAttachments=function(e,t,r){function o(e){try{return n.atob(e)}catch(t){var r=c.error(c.BAD_ARG,"Attachments need to be base64 encoded");return{error:r}}}function i(e,r){if(e.stub)return r();if("string"==typeof e.data){var i=o(e.data);if(i.error)return r(i.error);e.length=i.length,e.data="blob"===t?n.createBlob([n.fixBinary(i)],{type:e.content_type}):"base64"===t?n.btoa(i):i,n.MD5(i).then(function(t){e.digest="md5-"+t,r()})}else n.readAsBinaryString(e.data,function(o){"binary"===t?e.data=o:"base64"===t&&(e.data=n.btoa(o)),n.MD5(o).then(function(t){e.digest="md5-"+t,e.length=o.length,r()})})}function s(){u++,e.length===u&&(a?r(a):r())}if(!e.length)return r();var a,u=0;e.forEach(function(e){function t(e){a=e,r++,r===n.length&&s()}var n=e.data&&e.data._attachments?Object.keys(e.data._attachments):[],r=0;if(!n.length)return s();for(var o in e.data._attachments)e.data._attachments.hasOwnProperty(o)&&i(e.data._attachments[o],t)})}}).call(this,e("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./deps/ajax":9,"./deps/blob":10,"./deps/buffer":28,"./deps/collections":11,"./deps/errors":12,"./deps/md5":13,"./deps/parse-uri":15,"./deps/uuid":17,"./merge":20,_process:34,argsarray:27,bluebird:42,debug:35,events:33,inherits:38,"pouchdb-extend":57}],26:[function(e,t){t.exports="3.2.0"},{}],27:[function(e,t){"use strict";function n(e){return function(){var t=arguments.length;if(t){for(var n=[],r=-1;++r<t;)n[r]=arguments[r];return e.call(this,n)}return e.call(this,[])}}t.exports=n},{}],28:[function(){},{}],29:[function(e,t,n){function r(e,t,n){if(!(this instanceof r))return new r(e,t,n);var o,i=typeof e;if("number"===i)o=e>0?e>>>0:0;else if("string"===i)"base64"===t&&(e=S(e)),o=r.byteLength(e,t);else{if("object"!==i||null===e)throw new TypeError("must start with number, buffer, array or string");"Buffer"===e.type&&N(e.data)&&(e=e.data),o=+e.length>0?Math.floor(+e.length):0}if(this.length>j)throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+j.toString(16)+" bytes");var s;r.TYPED_ARRAY_SUPPORT?s=r._augment(new Uint8Array(o)):(s=this,s.length=o,s._isBuffer=!0);var a;if(r.TYPED_ARRAY_SUPPORT&&"number"==typeof e.byteLength)s._set(e);else if(k(e))if(r.isBuffer(e))for(a=0;o>a;a++)s[a]=e.readUInt8(a);else for(a=0;o>a;a++)s[a]=(e[a]%256+256)%256;else if("string"===i)s.write(e,0,t);else if("number"===i&&!r.TYPED_ARRAY_SUPPORT&&!n)for(a=0;o>a;a++)s[a]=0;return s}function o(e,t,n,r){n=Number(n)||0;var o=e.length-n;r?(r=Number(r),r>o&&(r=o)):r=o;var i=t.length;if(i%2!==0)throw new Error("Invalid hex string");r>i/2&&(r=i/2);for(var s=0;r>s;s++){var a=parseInt(t.substr(2*s,2),16);if(isNaN(a))throw new Error("Invalid hex string");e[n+s]=a}return s}function i(e,t,n,r){var o=R(x(t),e,n,r);return o}function s(e,t,n,r){var o=R(I(t),e,n,r);return o}function a(e,t,n,r){return s(e,t,n,r)}function u(e,t,n,r){var o=R(L(t),e,n,r);return o}function c(e,t,n,r){var o=R(q(t),e,n,r);return o}function f(e,t,n){return D.fromByteArray(0===t&&n===e.length?e:e.slice(t,n))}function l(e,t,n){var r="",o="";n=Math.min(e.length,n);for(var i=t;n>i;i++)e[i]<=127?(r+=O(o)+String.fromCharCode(e[i]),o=""):o+="%"+e[i].toString(16);return r+O(o)}function d(e,t,n){var r="";n=Math.min(e.length,n);for(var o=t;n>o;o++)r+=String.fromCharCode(e[o]);return r}function h(e,t,n){return d(e,t,n)}function p(e,t,n){var r=e.length;(!t||0>t)&&(t=0),(!n||0>n||n>r)&&(n=r);for(var o="",i=t;n>i;i++)o+=T(e[i]);return o}function v(e,t,n){for(var r=e.slice(t,n),o="",i=0;i<r.length;i+=2)o+=String.fromCharCode(r[i]+256*r[i+1]);return o}function g(e,t,n){if(e%1!==0||0>e)throw new RangeError("offset is not uint");if(e+t>n)throw new RangeError("Trying to access beyond buffer length")}function y(e,t,n,o,i,s){if(!r.isBuffer(e))throw new TypeError("buffer must be a Buffer instance");if(t>i||s>t)throw new TypeError("value is out of bounds");if(n+o>e.length)throw new TypeError("index out of range")}function m(e,t,n,r){0>t&&(t=65535+t+1);for(var o=0,i=Math.min(e.length-n,2);i>o;o++)e[n+o]=(t&255<<8*(r?o:1-o))>>>8*(r?o:1-o)}function _(e,t,n,r){0>t&&(t=4294967295+t+1);for(var o=0,i=Math.min(e.length-n,4);i>o;o++)e[n+o]=t>>>8*(r?o:3-o)&255}function b(e,t,n,r,o,i){if(t>o||i>t)throw new TypeError("value is out of bounds");if(n+r>e.length)throw new TypeError("index out of range")}function w(e,t,n,r,o){return o||b(e,t,n,4,3.4028234663852886e38,-3.4028234663852886e38),C.write(e,t,n,r,23,4),n+4}function E(e,t,n,r,o){return o||b(e,t,n,8,1.7976931348623157e308,-1.7976931348623157e308),C.write(e,t,n,r,52,8),n+8}function S(e){for(e=A(e).replace(P,"");e.length%4!==0;)e+="=";return e}function A(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}function k(e){return N(e)||r.isBuffer(e)||e&&"object"==typeof e&&"number"==typeof e.length}function T(e){return 16>e?"0"+e.toString(16):e.toString(16)}function x(e){for(var t=[],n=0;n<e.length;n++){var r=e.charCodeAt(n);if(127>=r)t.push(r);else{var o=n;r>=55296&&57343>=r&&n++;for(var i=encodeURIComponent(e.slice(o,n+1)).substr(1).split("%"),s=0;s<i.length;s++)t.push(parseInt(i[s],16))}}return t}function I(e){for(var t=[],n=0;n<e.length;n++)t.push(255&e.charCodeAt(n));return t}function q(e){for(var t,n,r,o=[],i=0;i<e.length;i++)t=e.charCodeAt(i),n=t>>8,r=t%256,o.push(r),o.push(n);return o}function L(e){return D.toByteArray(e)}function R(e,t,n,r){for(var o=0;r>o&&!(o+n>=t.length||o>=e.length);o++)t[o+n]=e[o];return o}function O(e){try{return decodeURIComponent(e)}catch(t){return String.fromCharCode(65533)}}var D=e("base64-js"),C=e("ieee754"),N=e("is-array");n.Buffer=r,n.SlowBuffer=r,n.INSPECT_MAX_BYTES=50,r.poolSize=8192;var j=1073741823;r.TYPED_ARRAY_SUPPORT=function(){try{var e=new ArrayBuffer(0),t=new Uint8Array(e);return t.foo=function(){return 42},42===t.foo()&&"function"==typeof t.subarray&&0===new Uint8Array(1).subarray(1,1).byteLength}catch(n){return!1}}(),r.isBuffer=function(e){return!(null==e||!e._isBuffer)},r.compare=function(e,t){if(!r.isBuffer(e)||!r.isBuffer(t))throw new TypeError("Arguments must be Buffers");for(var n=e.length,o=t.length,i=0,s=Math.min(n,o);s>i&&e[i]===t[i];i++);return i!==s&&(n=e[i],o=t[i]),o>n?-1:n>o?1:0},r.isEncoding=function(e){switch(String(e).toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"raw":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return!0;default:return!1}},r.concat=function(e,t){if(!N(e))throw new TypeError("Usage: Buffer.concat(list[, length])");if(0===e.length)return new r(0);if(1===e.length)return e[0];var n;if(void 0===t)for(t=0,n=0;n<e.length;n++)t+=e[n].length;var o=new r(t),i=0;for(n=0;n<e.length;n++){var s=e[n];s.copy(o,i),i+=s.length}return o},r.byteLength=function(e,t){var n;switch(e+="",t||"utf8"){case"ascii":case"binary":case"raw":n=e.length;break;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":n=2*e.length;break;case"hex":n=e.length>>>1;break;case"utf8":case"utf-8":n=x(e).length;break;case"base64":n=L(e).length;break;default:n=e.length}return n},r.prototype.length=void 0,r.prototype.parent=void 0,r.prototype.toString=function(e,t,n){var r=!1;if(t>>>=0,n=void 0===n||1/0===n?this.length:n>>>0,e||(e="utf8"),0>t&&(t=0),n>this.length&&(n=this.length),t>=n)return"";for(;;)switch(e){case"hex":return p(this,t,n);case"utf8":case"utf-8":return l(this,t,n);case"ascii":return d(this,t,n);case"binary":return h(this,t,n);case"base64":return f(this,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return v(this,t,n);default:if(r)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),r=!0}},r.prototype.equals=function(e){if(!r.isBuffer(e))throw new TypeError("Argument must be a Buffer");return 0===r.compare(this,e)},r.prototype.inspect=function(){var e="",t=n.INSPECT_MAX_BYTES;return this.length>0&&(e=this.toString("hex",0,t).match(/.{2}/g).join(" "),this.length>t&&(e+=" ... ")),"<Buffer "+e+">"},r.prototype.compare=function(e){if(!r.isBuffer(e))throw new TypeError("Argument must be a Buffer");return r.compare(this,e)},r.prototype.get=function(e){return console.log(".get() is deprecated. Access using array indexes instead."),this.readUInt8(e)},r.prototype.set=function(e,t){return console.log(".set() is deprecated. Access using array indexes instead."),this.writeUInt8(e,t)},r.prototype.write=function(e,t,n,r){if(isFinite(t))isFinite(n)||(r=n,n=void 0);else{var f=r;r=t,t=n,n=f}t=Number(t)||0;var l=this.length-t;n?(n=Number(n),n>l&&(n=l)):n=l,r=String(r||"utf8").toLowerCase();var d;switch(r){case"hex":d=o(this,e,t,n);break;case"utf8":case"utf-8":d=i(this,e,t,n);break;case"ascii":d=s(this,e,t,n);break;case"binary":d=a(this,e,t,n);break;case"base64":d=u(this,e,t,n);break;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":d=c(this,e,t,n);break;default:throw new TypeError("Unknown encoding: "+r)}return d},r.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}},r.prototype.slice=function(e,t){var n=this.length;if(e=~~e,t=void 0===t?n:~~t,0>e?(e+=n,0>e&&(e=0)):e>n&&(e=n),0>t?(t+=n,0>t&&(t=0)):t>n&&(t=n),e>t&&(t=e),r.TYPED_ARRAY_SUPPORT)return r._augment(this.subarray(e,t));for(var o=t-e,i=new r(o,void 0,!0),s=0;o>s;s++)i[s]=this[s+e];return i},r.prototype.readUInt8=function(e,t){return t||g(e,1,this.length),this[e]},r.prototype.readUInt16LE=function(e,t){return t||g(e,2,this.length),this[e]|this[e+1]<<8},r.prototype.readUInt16BE=function(e,t){return t||g(e,2,this.length),this[e]<<8|this[e+1]},r.prototype.readUInt32LE=function(e,t){return t||g(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},r.prototype.readUInt32BE=function(e,t){return t||g(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},r.prototype.readInt8=function(e,t){return t||g(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},r.prototype.readInt16LE=function(e,t){t||g(e,2,this.length);var n=this[e]|this[e+1]<<8;return 32768&n?4294901760|n:n},r.prototype.readInt16BE=function(e,t){t||g(e,2,this.length);var n=this[e+1]|this[e]<<8;return 32768&n?4294901760|n:n},r.prototype.readInt32LE=function(e,t){return t||g(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},r.prototype.readInt32BE=function(e,t){return t||g(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},r.prototype.readFloatLE=function(e,t){return t||g(e,4,this.length),C.read(this,e,!0,23,4)},r.prototype.readFloatBE=function(e,t){return t||g(e,4,this.length),C.read(this,e,!1,23,4)},r.prototype.readDoubleLE=function(e,t){return t||g(e,8,this.length),C.read(this,e,!0,52,8)},r.prototype.readDoubleBE=function(e,t){return t||g(e,8,this.length),C.read(this,e,!1,52,8)},r.prototype.writeUInt8=function(e,t,n){return e=+e,t>>>=0,n||y(this,e,t,1,255,0),r.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=e,t+1},r.prototype.writeUInt16LE=function(e,t,n){return e=+e,t>>>=0,n||y(this,e,t,2,65535,0),r.TYPED_ARRAY_SUPPORT?(this[t]=e,this[t+1]=e>>>8):m(this,e,t,!0),t+2},r.prototype.writeUInt16BE=function(e,t,n){return e=+e,t>>>=0,n||y(this,e,t,2,65535,0),r.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=e):m(this,e,t,!1),t+2},r.prototype.writeUInt32LE=function(e,t,n){return e=+e,t>>>=0,n||y(this,e,t,4,4294967295,0),r.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=e):_(this,e,t,!0),t+4},r.prototype.writeUInt32BE=function(e,t,n){return e=+e,t>>>=0,n||y(this,e,t,4,4294967295,0),r.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=e):_(this,e,t,!1),t+4},r.prototype.writeInt8=function(e,t,n){return e=+e,t>>>=0,n||y(this,e,t,1,127,-128),r.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),0>e&&(e=255+e+1),this[t]=e,t+1},r.prototype.writeInt16LE=function(e,t,n){return e=+e,t>>>=0,n||y(this,e,t,2,32767,-32768),r.TYPED_ARRAY_SUPPORT?(this[t]=e,this[t+1]=e>>>8):m(this,e,t,!0),t+2},r.prototype.writeInt16BE=function(e,t,n){return e=+e,t>>>=0,n||y(this,e,t,2,32767,-32768),r.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=e):m(this,e,t,!1),t+2},r.prototype.writeInt32LE=function(e,t,n){return e=+e,t>>>=0,n||y(this,e,t,4,2147483647,-2147483648),r.TYPED_ARRAY_SUPPORT?(this[t]=e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):_(this,e,t,!0),t+4},r.prototype.writeInt32BE=function(e,t,n){return e=+e,t>>>=0,n||y(this,e,t,4,2147483647,-2147483648),0>e&&(e=4294967295+e+1),r.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=e):_(this,e,t,!1),t+4},r.prototype.writeFloatLE=function(e,t,n){return w(this,e,t,!0,n)},r.prototype.writeFloatBE=function(e,t,n){return w(this,e,t,!1,n)},r.prototype.writeDoubleLE=function(e,t,n){return E(this,e,t,!0,n)},r.prototype.writeDoubleBE=function(e,t,n){return E(this,e,t,!1,n)},r.prototype.copy=function(e,t,n,o){var i=this;if(n||(n=0),o||0===o||(o=this.length),t||(t=0),o!==n&&0!==e.length&&0!==i.length){if(n>o)throw new TypeError("sourceEnd < sourceStart");if(0>t||t>=e.length)throw new TypeError("targetStart out of bounds");if(0>n||n>=i.length)throw new TypeError("sourceStart out of bounds");if(0>o||o>i.length)throw new TypeError("sourceEnd out of bounds");o>this.length&&(o=this.length),e.length-t<o-n&&(o=e.length-t+n);var s=o-n;if(1e3>s||!r.TYPED_ARRAY_SUPPORT)for(var a=0;s>a;a++)e[a+t]=this[a+n];else e._set(this.subarray(n,n+s),t)}},r.prototype.fill=function(e,t,n){if(e||(e=0),t||(t=0),n||(n=this.length),t>n)throw new TypeError("end < start");if(n!==t&&0!==this.length){if(0>t||t>=this.length)throw new TypeError("start out of bounds");if(0>n||n>this.length)throw new TypeError("end out of bounds");var r;if("number"==typeof e)for(r=t;n>r;r++)this[r]=e;else{var o=x(e.toString()),i=o.length;for(r=t;n>r;r++)this[r]=o[r%i]}return this}},r.prototype.toArrayBuffer=function(){if("undefined"!=typeof Uint8Array){if(r.TYPED_ARRAY_SUPPORT)return new r(this).buffer;for(var e=new Uint8Array(this.length),t=0,n=e.length;n>t;t+=1)e[t]=this[t];return e.buffer}throw new TypeError("Buffer.toArrayBuffer not supported in this browser")};var B=r.prototype;r._augment=function(e){return e.constructor=r,e._isBuffer=!0,e._get=e.get,e._set=e.set,e.get=B.get,e.set=B.set,e.write=B.write,e.toString=B.toString,e.toLocaleString=B.toString,e.toJSON=B.toJSON,e.equals=B.equals,e.compare=B.compare,e.copy=B.copy,e.slice=B.slice,e.readUInt8=B.readUInt8,e.readUInt16LE=B.readUInt16LE,e.readUInt16BE=B.readUInt16BE,e.readUInt32LE=B.readUInt32LE,e.readUInt32BE=B.readUInt32BE,e.readInt8=B.readInt8,e.readInt16LE=B.readInt16LE,e.readInt16BE=B.readInt16BE,e.readInt32LE=B.readInt32LE,e.readInt32BE=B.readInt32BE,e.readFloatLE=B.readFloatLE,e.readFloatBE=B.readFloatBE,e.readDoubleLE=B.readDoubleLE,e.readDoubleBE=B.readDoubleBE,e.writeUInt8=B.writeUInt8,e.writeUInt16LE=B.writeUInt16LE,e.writeUInt16BE=B.writeUInt16BE,e.writeUInt32LE=B.writeUInt32LE,e.writeUInt32BE=B.writeUInt32BE,e.writeInt8=B.writeInt8,e.writeInt16LE=B.writeInt16LE,e.writeInt16BE=B.writeInt16BE,e.writeInt32LE=B.writeInt32LE,e.writeInt32BE=B.writeInt32BE,e.writeFloatLE=B.writeFloatLE,e.writeFloatBE=B.writeFloatBE,e.writeDoubleLE=B.writeDoubleLE,e.writeDoubleBE=B.writeDoubleBE,e.fill=B.fill,e.inspect=B.inspect,e.toArrayBuffer=B.toArrayBuffer,e};var P=/[^+\/0-9A-z]/g},{"base64-js":30,ieee754:31,"is-array":32}],30:[function(e,t,n){var r="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";!function(e){"use strict";function t(e){var t=e.charCodeAt(0);return t===s?62:t===a?63:u>t?-1:u+10>t?t-u+26+26:f+26>t?t-f:c+26>t?t-c+26:void 0}function n(e){function n(e){c[l++]=e}var r,o,s,a,u,c;if(e.length%4>0)throw new Error("Invalid string. Length must be a multiple of 4");var f=e.length;u="="===e.charAt(f-2)?2:"="===e.charAt(f-1)?1:0,c=new i(3*e.length/4-u),s=u>0?e.length-4:e.length;var l=0;for(r=0,o=0;s>r;r+=4,o+=3)a=t(e.charAt(r))<<18|t(e.charAt(r+1))<<12|t(e.charAt(r+2))<<6|t(e.charAt(r+3)),n((16711680&a)>>16),n((65280&a)>>8),n(255&a);return 2===u?(a=t(e.charAt(r))<<2|t(e.charAt(r+1))>>4,n(255&a)):1===u&&(a=t(e.charAt(r))<<10|t(e.charAt(r+1))<<4|t(e.charAt(r+2))>>2,n(a>>8&255),n(255&a)),c}function o(e){function t(e){return r.charAt(e)}function n(e){return t(e>>18&63)+t(e>>12&63)+t(e>>6&63)+t(63&e)}var o,i,s,a=e.length%3,u="";for(o=0,s=e.length-a;s>o;o+=3)i=(e[o]<<16)+(e[o+1]<<8)+e[o+2],u+=n(i);switch(a){case 1:i=e[e.length-1],u+=t(i>>2),u+=t(i<<4&63),u+="==";break;case 2:i=(e[e.length-2]<<8)+e[e.length-1],u+=t(i>>10),u+=t(i>>4&63),u+=t(i<<2&63),u+="="}return u}var i="undefined"!=typeof Uint8Array?Uint8Array:Array,s="+".charCodeAt(0),a="/".charCodeAt(0),u="0".charCodeAt(0),c="a".charCodeAt(0),f="A".charCodeAt(0);e.toByteArray=n,e.fromByteArray=o}("undefined"==typeof n?this.base64js={}:n)},{}],31:[function(e,t,n){n.read=function(e,t,n,r,o){var i,s,a=8*o-r-1,u=(1<<a)-1,c=u>>1,f=-7,l=n?o-1:0,d=n?-1:1,h=e[t+l];for(l+=d,i=h&(1<<-f)-1,h>>=-f,f+=a;f>0;i=256*i+e[t+l],l+=d,f-=8);for(s=i&(1<<-f)-1,i>>=-f,f+=r;f>0;s=256*s+e[t+l],l+=d,f-=8);if(0===i)i=1-c;else{if(i===u)return s?0/0:1/0*(h?-1:1);s+=Math.pow(2,r),i-=c}return(h?-1:1)*s*Math.pow(2,i-r)},n.write=function(e,t,n,r,o,i){var s,a,u,c=8*i-o-1,f=(1<<c)-1,l=f>>1,d=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,h=r?0:i-1,p=r?1:-1,v=0>t||0===t&&0>1/t?1:0;for(t=Math.abs(t),isNaN(t)||1/0===t?(a=isNaN(t)?1:0,s=f):(s=Math.floor(Math.log(t)/Math.LN2),t*(u=Math.pow(2,-s))<1&&(s--,u*=2),t+=s+l>=1?d/u:d*Math.pow(2,1-l),t*u>=2&&(s++,u/=2),s+l>=f?(a=0,s=f):s+l>=1?(a=(t*u-1)*Math.pow(2,o),s+=l):(a=t*Math.pow(2,l-1)*Math.pow(2,o),s=0));o>=8;e[n+h]=255&a,h+=p,a/=256,o-=8);for(s=s<<o|a,c+=o;c>0;e[n+h]=255&s,h+=p,s/=256,c-=8);e[n+h-p]|=128*v}},{}],32:[function(e,t){var n=Array.isArray,r=Object.prototype.toString;t.exports=n||function(e){return!!e&&"[object Array]"==r.call(e)}},{}],33:[function(e,t){function n(){this._events=this._events||{},this._maxListeners=this._maxListeners||void 0}function r(e){return"function"==typeof e}function o(e){return"number"==typeof e}function i(e){return"object"==typeof e&&null!==e}function s(e){return void 0===e}t.exports=n,n.EventEmitter=n,n.prototype._events=void 0,n.prototype._maxListeners=void 0,n.defaultMaxListeners=10,n.prototype.setMaxListeners=function(e){if(!o(e)||0>e||isNaN(e))throw TypeError("n must be a positive number");return this._maxListeners=e,this},n.prototype.emit=function(e){var t,n,o,a,u,c;if(this._events||(this._events={}),"error"===e&&(!this._events.error||i(this._events.error)&&!this._events.error.length)){if(t=arguments[1],t instanceof Error)throw t;throw TypeError('Uncaught, unspecified "error" event.')}if(n=this._events[e],s(n))return!1;if(r(n))switch(arguments.length){case 1:n.call(this);break;case 2:n.call(this,arguments[1]);break;case 3:n.call(this,arguments[1],arguments[2]);break;default:for(o=arguments.length,a=new Array(o-1),u=1;o>u;u++)a[u-1]=arguments[u];n.apply(this,a)}else if(i(n)){for(o=arguments.length,a=new Array(o-1),u=1;o>u;u++)a[u-1]=arguments[u];for(c=n.slice(),o=c.length,u=0;o>u;u++)c[u].apply(this,a)}return!0},n.prototype.addListener=function(e,t){var o;if(!r(t))throw TypeError("listener must be a function");if(this._events||(this._events={}),this._events.newListener&&this.emit("newListener",e,r(t.listener)?t.listener:t),this._events[e]?i(this._events[e])?this._events[e].push(t):this._events[e]=[this._events[e],t]:this._events[e]=t,i(this._events[e])&&!this._events[e].warned){var o;o=s(this._maxListeners)?n.defaultMaxListeners:this._maxListeners,o&&o>0&&this._events[e].length>o&&(this._events[e].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[e].length),"function"==typeof console.trace&&console.trace())}return this},n.prototype.on=n.prototype.addListener,n.prototype.once=function(e,t){function n(){this.removeListener(e,n),o||(o=!0,t.apply(this,arguments))}if(!r(t))throw TypeError("listener must be a function");var o=!1;return n.listener=t,this.on(e,n),this},n.prototype.removeListener=function(e,t){var n,o,s,a;if(!r(t))throw TypeError("listener must be a function");if(!this._events||!this._events[e])return this;if(n=this._events[e],s=n.length,o=-1,n===t||r(n.listener)&&n.listener===t)delete this._events[e],this._events.removeListener&&this.emit("removeListener",e,t);else if(i(n)){for(a=s;a-->0;)if(n[a]===t||n[a].listener&&n[a].listener===t){o=a;break}if(0>o)return this;1===n.length?(n.length=0,delete this._events[e]):n.splice(o,1),this._events.removeListener&&this.emit("removeListener",e,t)}return this},n.prototype.removeAllListeners=function(e){var t,n;if(!this._events)return this;if(!this._events.removeListener)return 0===arguments.length?this._events={}:this._events[e]&&delete this._events[e],this;if(0===arguments.length){for(t in this._events)"removeListener"!==t&&this.removeAllListeners(t);return this.removeAllListeners("removeListener"),this._events={},this}if(n=this._events[e],r(n))this.removeListener(e,n);else for(;n.length;)this.removeListener(e,n[n.length-1]);return delete this._events[e],this},n.prototype.listeners=function(e){var t;return t=this._events&&this._events[e]?r(this._events[e])?[this._events[e]]:this._events[e].slice():[]},n.listenerCount=function(e,t){var n;return n=e._events&&e._events[t]?r(e._events[t])?1:e._events[t].length:0}},{}],34:[function(e,t){function n(){}var r=t.exports={};r.nextTick=function(){var e="undefined"!=typeof window&&window.setImmediate,t="undefined"!=typeof window&&window.MutationObserver,n="undefined"!=typeof window&&window.postMessage&&window.addEventListener;if(e)return function(e){return window.setImmediate(e)};var r=[];if(t){var o=document.createElement("div"),i=new MutationObserver(function(){var e=r.slice();r.length=0,e.forEach(function(e){e()})});return i.observe(o,{attributes:!0}),function(e){r.length||o.setAttribute("yes","no"),r.push(e)}}return n?(window.addEventListener("message",function(e){var t=e.source;if((t===window||null===t)&&"process-tick"===e.data&&(e.stopPropagation(),r.length>0)){var n=r.shift();n()}},!0),function(e){r.push(e),window.postMessage("process-tick","*")}):function(e){setTimeout(e,0)}}(),r.title="browser",r.browser=!0,r.env={},r.argv=[],r.on=n,r.addListener=n,r.once=n,r.off=n,r.removeListener=n,r.removeAllListeners=n,r.emit=n,r.binding=function(){throw new Error("process.binding is not supported")},r.cwd=function(){return"/"},r.chdir=function(){throw new Error("process.chdir is not supported")}},{}],35:[function(e,t,n){function r(){return"WebkitAppearance"in document.documentElement.style||window.console&&(console.firebug||console.exception&&console.table)||navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)&&parseInt(RegExp.$1,10)>=31}function o(){var e=arguments,t=this.useColors;if(e[0]=(t?"%c":"")+this.namespace+(t?" %c":" ")+e[0]+(t?"%c ":" ")+"+"+n.humanize(this.diff),!t)return e;var r="color: "+this.color;e=[e[0],r,"color: inherit"].concat(Array.prototype.slice.call(e,1));var o=0,i=0;return e[0].replace(/%[a-z%]/g,function(e){"%"!==e&&(o++,"%c"===e&&(i=o))}),e.splice(i,0,r),e}function i(){return"object"==typeof console&&"function"==typeof console.log&&Function.prototype.apply.call(console.log,console,arguments)}function s(e){try{null==e?localStorage.removeItem("debug"):localStorage.debug=e}catch(t){}}function a(){var e;try{e=localStorage.debug}catch(t){}return e}n=t.exports=e("./debug"),n.log=i,n.formatArgs=o,n.save=s,n.load=a,n.useColors=r,n.colors=["lightseagreen","forestgreen","goldenrod","dodgerblue","darkorchid","crimson"],n.formatters.j=function(e){return JSON.stringify(e)},n.enable(a())},{"./debug":36}],36:[function(e,t,n){function r(){return n.colors[f++%n.colors.length]}function o(e){function t(){}function o(){var e=o,t=+new Date,i=t-(c||t);e.diff=i,e.prev=c,e.curr=t,c=t,null==e.useColors&&(e.useColors=n.useColors()),null==e.color&&e.useColors&&(e.color=r());var s=Array.prototype.slice.call(arguments);s[0]=n.coerce(s[0]),"string"!=typeof s[0]&&(s=["%o"].concat(s));var a=0;s[0]=s[0].replace(/%([a-z%])/g,function(t,r){if("%"===t)return t;a++;var o=n.formatters[r];if("function"==typeof o){var i=s[a];t=o.call(e,i),s.splice(a,1),a--}return t}),"function"==typeof n.formatArgs&&(s=n.formatArgs.apply(e,s));var u=o.log||n.log||console.log.bind(console);u.apply(e,s)}t.enabled=!1,o.enabled=!0;var i=n.enabled(e)?o:t;return i.namespace=e,i}function i(e){n.save(e);for(var t=(e||"").split(/[\s,]+/),r=t.length,o=0;r>o;o++)t[o]&&(e=t[o].replace(/\*/g,".*?"),"-"===e[0]?n.skips.push(new RegExp("^"+e.substr(1)+"$")):n.names.push(new RegExp("^"+e+"$")))}function s(){n.enable("")}function a(e){var t,r;for(t=0,r=n.skips.length;r>t;t++)if(n.skips[t].test(e))return!1;for(t=0,r=n.names.length;r>t;t++)if(n.names[t].test(e))return!0;return!1}function u(e){return e instanceof Error?e.stack||e.message:e}n=t.exports=o,n.coerce=u,n.disable=s,n.enable=i,n.enabled=a,n.humanize=e("ms"),n.names=[],n.skips=[],n.formatters={};var c,f=0},{ms:37}],37:[function(e,t){function n(e){var t=/^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(e);if(t){var n=parseFloat(t[1]),r=(t[2]||"ms").toLowerCase();switch(r){case"years":case"year":case"y":return n*f;case"days":case"day":case"d":return n*c;case"hours":case"hour":case"h":return n*u;case"minutes":case"minute":case"m":return n*a;case"seconds":case"second":case"s":return n*s;case"ms":return n}}}function r(e){return e>=c?Math.round(e/c)+"d":e>=u?Math.round(e/u)+"h":e>=a?Math.round(e/a)+"m":e>=s?Math.round(e/s)+"s":e+"ms"}function o(e){return i(e,c,"day")||i(e,u,"hour")||i(e,a,"minute")||i(e,s,"second")||e+" ms"}function i(e,t,n){return t>e?void 0:1.5*t>e?Math.floor(e/t)+" "+n:Math.ceil(e/t)+" "+n+"s"}var s=1e3,a=60*s,u=60*a,c=24*u,f=365.25*c;t.exports=function(e,t){return t=t||{},"string"==typeof e?n(e):t.long?o(e):r(e)}},{}],38:[function(e,t){t.exports="function"==typeof Object.create?function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:function(e,t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}},{}],39:[function(e,t){"use strict";function n(){}t.exports=n},{}],40:[function(e,t){"use strict";function n(e){function t(e,t){function r(e){c[t]=e,++f===n&!u&&(u=!0,a.resolve(d,c))}i(e).then(r,function(e){u||(u=!0,a.reject(d,e))})}if("[object Array]"!==Object.prototype.toString.call(e))return o(new TypeError("must be an array"));var n=e.length,u=!1;if(!n)return i([]);for(var c=new Array(n),f=0,l=-1,d=new r(s);++l<n;)t(e[l],l);return d}var r=e("./promise"),o=e("./reject"),i=e("./resolve"),s=e("./INTERNAL"),a=e("./handlers");t.exports=n},{"./INTERNAL":39,"./handlers":41,"./promise":43,"./reject":46,"./resolve":47}],41:[function(e,t,n){"use strict";function r(e){var t=e&&e.then;return e&&"object"==typeof e&&"function"==typeof t?function(){t.apply(e,arguments)}:void 0}var o=e("./tryCatch"),i=e("./resolveThenable"),s=e("./states");n.resolve=function(e,t){var a=o(r,t);if("error"===a.status)return n.reject(e,a.value);var u=a.value;if(u)i.safely(e,u);else{e.state=s.FULFILLED,e.outcome=t;for(var c=-1,f=e.queue.length;++c<f;)e.queue[c].callFulfilled(t)}return e},n.reject=function(e,t){e.state=s.REJECTED,e.outcome=t;for(var n=-1,r=e.queue.length;++n<r;)e.queue[n].callRejected(t);return e}},{"./resolveThenable":48,"./states":49,"./tryCatch":50}],42:[function(e,t,n){t.exports=n=e("./promise"),n.resolve=e("./resolve"),n.reject=e("./reject"),n.all=e("./all"),n.race=e("./race")},{"./all":40,"./promise":43,"./race":45,"./reject":46,"./resolve":47}],43:[function(e,t){"use strict";function n(e){if(!(this instanceof n))return new n(e);if("function"!=typeof e)throw new TypeError("reslover must be a function");this.state=s.PENDING,this.queue=[],this.outcome=void 0,e!==o&&i.safely(this,e)}var r=e("./unwrap"),o=e("./INTERNAL"),i=e("./resolveThenable"),s=e("./states"),a=e("./queueItem");t.exports=n,n.prototype["catch"]=function(e){return this.then(null,e)},n.prototype.then=function(e,t){if("function"!=typeof e&&this.state===s.FULFILLED||"function"!=typeof t&&this.state===s.REJECTED)return this;var i=new n(o);if(this.state!==s.PENDING){var u=this.state===s.FULFILLED?e:t;r(i,u,this.outcome)}else this.queue.push(new a(i,e,t));return i}},{"./INTERNAL":39,"./queueItem":44,"./resolveThenable":48,"./states":49,"./unwrap":51}],44:[function(e,t){"use strict";function n(e,t,n){this.promise=e,"function"==typeof t&&(this.onFulfilled=t,this.callFulfilled=this.otherCallFulfilled),"function"==typeof n&&(this.onRejected=n,this.callRejected=this.otherCallRejected)}var r=e("./handlers"),o=e("./unwrap");t.exports=n,n.prototype.callFulfilled=function(e){r.resolve(this.promise,e)},n.prototype.otherCallFulfilled=function(e){o(this.promise,this.onFulfilled,e)},n.prototype.callRejected=function(e){r.reject(this.promise,e)},n.prototype.otherCallRejected=function(e){o(this.promise,this.onRejected,e)}},{"./handlers":41,"./unwrap":51}],45:[function(e,t){"use strict";function n(e){function t(e){i(e).then(function(e){u||(u=!0,a.resolve(f,e))},function(e){u||(u=!0,a.reject(f,e))})}if("[object Array]"!==Object.prototype.toString.call(e))return o(new TypeError("must be an array"));var n=e.length,u=!1;if(!n)return i([]);for(var c=-1,f=new r(s);++c<n;)t(e[c]);return f}var r=e("./promise"),o=e("./reject"),i=e("./resolve"),s=e("./INTERNAL"),a=e("./handlers");t.exports=n},{"./INTERNAL":39,"./handlers":41,"./promise":43,"./reject":46,"./resolve":47}],46:[function(e,t){"use strict";function n(e){var t=new r(o);return i.reject(t,e)}var r=e("./promise"),o=e("./INTERNAL"),i=e("./handlers");t.exports=n},{"./INTERNAL":39,"./handlers":41,"./promise":43}],47:[function(e,t){"use strict";function n(e){if(e)return e instanceof r?e:i.resolve(new r(o),e);var t=typeof e;switch(t){case"boolean":return s;case"undefined":return u;case"object":return a;case"number":return c;case"string":return f}}var r=e("./promise"),o=e("./INTERNAL"),i=e("./handlers");t.exports=n;var s=i.resolve(new r(o),!1),a=i.resolve(new r(o),null),u=i.resolve(new r(o),void 0),c=i.resolve(new r(o),0),f=i.resolve(new r(o),"")},{"./INTERNAL":39,"./handlers":41,"./promise":43}],48:[function(e,t,n){"use strict";function r(e,t){function n(t){a||(a=!0,o.reject(e,t))}function r(t){a||(a=!0,o.resolve(e,t))}function s(){t(r,n)}var a=!1,u=i(s);"error"===u.status&&n(u.value)}var o=e("./handlers"),i=e("./tryCatch");n.safely=r},{"./handlers":41,"./tryCatch":50}],49:[function(e,t,n){n.REJECTED=["REJECTED"],n.FULFILLED=["FULFILLED"],n.PENDING=["PENDING"]},{}],50:[function(e,t){"use strict";function n(e,t){var n={};try{n.value=e(t),n.status="success"}catch(r){n.status="error",n.value=r}return n}t.exports=n},{}],51:[function(e,t){"use strict";function n(e,t,n){r(function(){var r;try{r=t(n)}catch(i){return o.reject(e,i)}r===e?o.reject(e,new TypeError("Cannot resolve promise with itself")):o.resolve(e,r)})}var r=e("immediate"),o=e("./handlers");t.exports=n},{"./handlers":41,immediate:52}],52:[function(e,t){"use strict";function n(){o=!0;for(var e,t,n=a.length;n;){for(t=a,a=[],e=-1;++e<n;)t[e]();n=a.length}o=!1}function r(e){1!==a.push(e)||o||i()}for(var o,i,s=[e("./nextTick"),e("./mutation.js"),e("./messageChannel"),e("./stateChange"),e("./timeout")],a=[],u=-1,c=s.length;++u<c;)if(s[u]&&s[u].test&&s[u].test()){i=s[u].install(n); +break}t.exports=r},{"./messageChannel":53,"./mutation.js":54,"./nextTick":28,"./stateChange":55,"./timeout":56}],53:[function(e,t,n){(function(e){"use strict";n.test=function(){return e.setImmediate?!1:"undefined"!=typeof e.MessageChannel},n.install=function(t){var n=new e.MessageChannel;return n.port1.onmessage=t,function(){n.port2.postMessage(0)}}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],54:[function(e,t,n){(function(e){"use strict";var t=e.MutationObserver||e.WebKitMutationObserver;n.test=function(){return t},n.install=function(n){var r=0,o=new t(n),i=e.document.createTextNode("");return o.observe(i,{characterData:!0}),function(){i.data=r=++r%2}}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],55:[function(e,t,n){(function(e){"use strict";n.test=function(){return"document"in e&&"onreadystatechange"in e.document.createElement("script")},n.install=function(t){return function(){var n=e.document.createElement("script");return n.onreadystatechange=function(){t(),n.onreadystatechange=null,n.parentNode.removeChild(n),n=null},e.document.documentElement.appendChild(n),t}}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],56:[function(e,t,n){"use strict";n.test=function(){return!0},n.install=function(e){return function(){setTimeout(e,0)}}},{}],57:[function(e,t){"use strict";function n(e){return null===e?String(e):"object"==typeof e||"function"==typeof e?u[d.call(e)]||"object":typeof e}function r(e){return null!==e&&e===e.window}function o(e){if(!e||"object"!==n(e)||e.nodeType||r(e))return!1;try{if(e.constructor&&!h.call(e,"constructor")&&!h.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(t){return!1}var o;for(o in e);return void 0===o||h.call(e,o)}function i(e){return"function"===n(e)}function s(){for(var e=[],t=-1,n=arguments.length,r=new Array(n);++t<n;)r[t]=arguments[t];var o={};e.push({args:r,result:{container:o,key:"key"}});for(var i;i=e.pop();)a(e,i.args,i.result);return o.key}function a(e,t,n){var r,s,a,u,c,f,l,d=t[0]||{},h=1,v=t.length,g=!1,y=/\d+/;for("boolean"==typeof d&&(g=d,d=t[1]||{},h=2),"object"==typeof d||i(d)||(d={}),v===h&&(d=this,--h);v>h;h++)if(null!=(r=t[h])){l=p(r);for(s in r)if(!(s in Object.prototype)){if(l&&!y.test(s))continue;if(a=d[s],u=r[s],d===u)continue;g&&u&&(o(u)||(c=p(u)))?(c?(c=!1,f=a&&p(a)?a:[]):f=a&&o(a)?a:{},e.push({args:[g,f,u],result:{container:d,key:s}})):void 0!==u&&(p(r)&&i(u)||(d[s]=u))}}n.container[n.key]=d}for(var u={},c=["Boolean","Number","String","Function","Array","Date","RegExp","Object","Error"],f=0;f<c.length;f++){var l=c[f];u["[object "+l+"]"]=l.toLowerCase()}var d=u.toString,h=u.hasOwnProperty,p=Array.isArray||function(e){return"array"===n(e)};t.exports=s},{}],58:[function(e,t){"use strict";var n=e("./upsert"),r=e("./utils"),o=r.Promise;t.exports=function(e){var t=e.db,i=e.viewName,s=e.map,a=e.reduce,u=e.temporary,c=s.toString()+(a&&a.toString())+"undefined";if(!u&&t._cachedViews){var f=t._cachedViews[c];if(f)return o.resolve(f)}return t.info().then(function(e){function o(e){e.views=e.views||{};var t=i;-1===t.indexOf("/")&&(t=i+"/"+i);var n=e.views[t]=e.views[t]||{};if(!n[f])return n[f]=!0,e}var f=e.db_name+"-mrview-"+(u?"temp":r.MD5(c));return n(t,"_local/mrviews",o).then(function(){return t.registerDependentDatabase(f).then(function(e){var n=e.db;n.auto_compaction=!0;var r={name:f,db:n,sourceDB:t,adapter:t.adapter,mapFun:s,reduceFun:a};return r.db.get("_local/lastSeq")["catch"](function(e){if(404!==e.status)throw e}).then(function(e){return r.seq=e?e.seq:0,u||(t._cachedViews=t._cachedViews||{},t._cachedViews[c]=r,r.db.on("destroyed",function(){delete t._cachedViews[c]})),r})})})})}},{"./upsert":64,"./utils":65}],59:[function(_dereq_,module,exports){"use strict";module.exports=function(func,emit,sum,log,isArray,toJSON){return eval("'use strict'; ("+func.replace(/;\s*$/,"")+");")}},{}],60:[function(e,t,n){(function(t){"use strict";function r(e){return-1===e.indexOf("/")?[e,e]:e.split("/")}function o(e,t,n){try{return{output:t.apply(null,n)}}catch(r){return e.emit("error",r),{error:r}}}function i(e,t){var n=A(e.key,t.key);return 0!==n?n:A(e.value,t.value)}function s(e,t,n){return n=n||0,"number"==typeof t?e.slice(n,t+n):n>0?e.slice(n):e}function a(e){var t=e.value,n=t&&"object"==typeof t&&t._id||e.id;return n}function u(e){var t=new Error("builtin "+e+" function requires map values to be numbers or number arrays");return t.name="invalid_value",t.status=500,t}function c(e){for(var t=0,n=0,r=e.length;r>n;n++){var o=e[n];if("number"!=typeof o){if(!Array.isArray(o))throw u("_sum");t="number"==typeof t?[t]:t;for(var i=0,s=o.length;s>i;i++){var a=o[i];if("number"!=typeof a)throw u("_sum");"undefined"==typeof t[i]?t.push(a):t[i]+=a}}else"number"==typeof t?t+=o:t[0]+=o}return t}function f(e,t,n,r){var o=t[e];"undefined"!=typeof o&&(r&&(o=encodeURIComponent(JSON.stringify(o))),n.push(e+"="+o))}function l(e,t){var n=e.descending?"endkey":"startkey",r=e.descending?"startkey":"endkey";if("undefined"!=typeof e[n]&&"undefined"!=typeof e[r]&&A(e[n],e[r])>0)throw new _("No rows can match your key range, reverse your start_key and end_key or set {descending : true}");if(t.reduce&&e.reduce!==!1){if(e.include_docs)throw new _("{include_docs:true} is invalid for reduce");if(e.keys&&e.keys.length>1&&!e.group&&!e.group_level)throw new _("Multi-key fetches for reduce views must use {group: true}")}if(e.group_level){if("number"!=typeof e.group_level)throw new _('Invalid value for integer: "'+e.group_level+'"');if(e.group_level<0)throw new _('Invalid value for positive integer: "'+e.group_level+'"')}}function d(e,t,n){var o,i=[],s="GET";if(f("reduce",n,i),f("include_docs",n,i),f("attachments",n,i),f("limit",n,i),f("descending",n,i),f("group",n,i),f("group_level",n,i),f("skip",n,i),f("stale",n,i),f("conflicts",n,i),f("startkey",n,i,!0),f("endkey",n,i,!0),f("inclusive_end",n,i),f("key",n,i,!0),i=i.join("&"),i=""===i?"":"?"+i,"undefined"!=typeof n.keys){var a=2e3,u="keys="+encodeURIComponent(JSON.stringify(n.keys));u.length+i.length+1<=a?i+=("?"===i[0]?"&":"?")+u:(s="POST","string"==typeof t?o=JSON.stringify({keys:n.keys}):t.keys=n.keys)}if("string"==typeof t){var c=r(t);return e.request({method:s,url:"_design/"+c[0]+"/_view/"+c[1]+i,body:o})}return o=o||{},Object.keys(t).forEach(function(e){o[e]=Array.isArray(t[e])?t[e]:t[e].toString()}),e.request({method:"POST",url:"_temp_view"+i,body:o})}function h(e){return function(t){if(404===t.status)return e;throw t}}function p(e,t,n){var r="_local/doc_"+e;return t.db.get(r)["catch"](h({_id:r,keys:[]})).then(function(r){return L.resolve().then(function(){return r.keys.length?t.db.allDocs({keys:r.keys,include_docs:!0}):{rows:[]}}).then(function(t){var o=t.rows.map(function(e){return e.doc}).filter(function(e){return e}),i=n[e],s={};o.forEach(function(e){if(s[e._id]=!0,e._deleted=!i[e._id],!e._deleted){var t=i[e._id];"value"in t&&(e.value=t.value)}});var a=Object.keys(i);return a.forEach(function(e){if(!s[e]){var t={_id:e},n=i[e];"value"in n&&(t.value=n.value),o.push(t)}}),r.keys=q.uniq(a.concat(r.keys)),o.splice(0,0,r),o})})}function v(e,t,n){var r="_local/lastSeq";return e.db.get(r)["catch"](h({_id:r,seq:0})).then(function(r){var o=Object.keys(t);return L.all(o.map(function(n){return p(n,e,t)})).then(function(t){var o=[];return t.forEach(function(e){o=o.concat(e)}),r.seq=n,o.push(r),e.db.bulkDocs({docs:o})})})}function g(e,t,n){0===n.group_level&&delete n.group_level;var r,i=n.group||n.group_level;r=C[e.reduceFun]?C[e.reduceFun]:I(e.reduceFun.toString(),null,c,w,Array.isArray,JSON.parse);var a=[],u=n.group_level;t.forEach(function(e){var t=a[a.length-1],n=i?e.key:null;return i&&Array.isArray(n)&&"number"==typeof u&&(n=n.length>u?n.slice(0,u):n),t&&0===A(t.key[0][0],n)?(t.key.push([n,e.id]),void t.value.push(e.value)):void a.push({key:[[n,e.id]],value:[e.value]})});for(var f=0,l=a.length;l>f;f++){var d=a[f],h=o(e.sourceDB,r,[d.key,d.value,!1]);d.value=h.error?null:h.output,d.key=d.key[0][0]}return{rows:s(a,n.limit,n.skip)}}function y(e){return e.request({method:"POST",url:"_view_cleanup"})}function m(e,n,o){if("http"===e.type())return d(e,n,o);if("string"!=typeof n){l(o,n);var i={db:e,viewName:"temp_view/temp_view",map:n.map,reduce:n.reduce,temporary:!0};return O.add(function(){return x(i).then(function(e){function t(){return e.db.destroy()}return q.fin(N(e).then(function(){return j(e,o)}),t)})}),O.finish()}var s=n,a=r(s),u=a[0],c=a[1];return e.get("_design/"+u).then(function(n){var r=n.views&&n.views[c];if(!r||"string"!=typeof r.map)throw new b("ddoc "+u+" has no view named "+c);l(o,r);var i={db:e,viewName:s,map:r.map,reduce:r.reduce};return x(i).then(function(e){return"ok"===o.stale||"update_after"===o.stale?("update_after"===o.stale&&t.nextTick(function(){N(e)}),j(e,o)):N(e).then(function(){return j(e,o)})})})}function _(e){this.status=400,this.name="query_parse_error",this.message=e,this.error=!0;try{Error.captureStackTrace(this,_)}catch(t){}}function b(e){this.status=404,this.name="not_found",this.message=e,this.error=!0;try{Error.captureStackTrace(this,b)}catch(t){}}var w,E=e("pouchdb-collate"),S=e("./taskqueue"),A=E.collate,k=E.toIndexableString,T=E.normalizeKey,x=e("./create-view"),I=e("./evalfunc");w="undefined"!=typeof console&&"function"==typeof console.log?Function.prototype.bind.call(console.log,console):function(){};var q=e("./utils"),L=q.Promise,R=new S,O=new S,D=50,C={_sum:function(e,t){return c(t)},_count:function(e,t){return t.length},_stats:function(e,t){function n(e){for(var t=0,n=0,r=e.length;r>n;n++){var o=e[n];t+=o*o}return t}return{sum:c(t),min:Math.min.apply(null,t),max:Math.max.apply(null,t),count:t.length,sumsqr:n(t)}}},N=q.sequentialize(R,function(e){function t(e,t){var n={id:s._id,key:T(e)};"undefined"!=typeof t&&null!==t&&(n.value=T(t)),r.push(n)}function n(t,n){return function(){return v(e,t,n)}}var r,s,a;if("function"==typeof e.mapFun&&2===e.mapFun.length){var u=e.mapFun;a=function(e){return u(e,t)}}else a=I(e.mapFun.toString(),t,c,w,Array.isArray,JSON.parse);var f=e.seq||0,l=new S;return new L(function(t,u){function c(){l.finish().then(function(){e.seq=f,t()})}function d(){function t(e){u(e)}e.sourceDB.changes({conflicts:!0,include_docs:!0,since:f,limit:D}).on("complete",function(t){var u=t.results;if(!u.length)return c();for(var h={},p=0,v=u.length;v>p;p++){var g=u[p];if("_"!==g.doc._id[0]){r=[],s=g.doc,s._deleted||o(e.sourceDB,a,[s]),r.sort(i);for(var y,m={},_=0,b=r.length;b>_;_++){var w=r[_],E=[w.key,w.id];w.key===y&&E.push(_);var S=k(E);m[S]=w,y=w.key}h[g.doc._id]=m}f=g.seq}return l.add(n(h,f)),u.length<D?c():d()}).on("error",t)}d()})}),j=q.sequentialize(R,function(e,t){function n(t){return t.include_docs=!0,e.db.allDocs(t).then(function(e){return o=e.total_rows,e.rows.map(function(e){if("value"in e.doc&&"object"==typeof e.doc.value&&null!==e.doc.value){var t=Object.keys(e.doc.value).sort(),n=["id","key","value"];if(!(n>t||t>n))return e.doc.value}var r=E.parseIndexableString(e.doc._id);return{key:r[0],id:r[1],value:"value"in e.doc?e.doc.value:null}})})}function r(n){var r;if(r=i?g(e,n,t):{total_rows:o,offset:s,rows:n},t.include_docs){var u=q.uniq(n.map(a));return e.sourceDB.allDocs({keys:u,include_docs:!0,conflicts:t.conflicts,attachments:t.attachments}).then(function(e){var t={};return e.rows.forEach(function(e){e.doc&&(t["$"+e.id]=e.doc)}),n.forEach(function(e){var n=a(e),r=t["$"+n];r&&(e.doc=r)}),r})}return r}var o,i=e.reduceFun&&t.reduce!==!1,s=t.skip||0;"undefined"==typeof t.keys||t.keys.length||(t.limit=0,delete t.keys);var u=function(e){return e.reduce(function(e,t){return e.concat(t)})};if("undefined"!=typeof t.keys){var c=t.keys,f=c.map(function(e){var t={startkey:k([e]),endkey:k([e,{}])};return n(t)});return L.all(f).then(u).then(r)}var l={descending:t.descending};if("undefined"!=typeof t.startkey&&(l.startkey=k(t.descending?[t.startkey,{}]:[t.startkey])),"undefined"!=typeof t.endkey){var d=t.inclusive_end!==!1;t.descending&&(d=!d),l.endkey=k(d?[t.endkey,{}]:[t.endkey])}if("undefined"!=typeof t.key){var h=k([t.key]),p=k([t.key,{}]);l.descending?(l.endkey=h,l.startkey=p):(l.startkey=h,l.endkey=p)}return i||("number"==typeof t.limit&&(l.limit=t.limit),l.skip=s),n(l).then(r)}),B=q.sequentialize(R,function(e){return e.get("_local/mrviews").then(function(t){var n={};Object.keys(t.views).forEach(function(e){var t=r(e),o="_design/"+t[0],i=t[1];n[o]=n[o]||{},n[o][i]=!0});var o={keys:Object.keys(n),include_docs:!0};return e.allDocs(o).then(function(r){var o={};r.rows.forEach(function(e){var r=e.key.substring(8);Object.keys(n[e.key]).forEach(function(n){var i=r+"/"+n;t.views[i]||(i=n);var s=Object.keys(t.views[i]),a=e.doc&&e.doc.views&&e.doc.views[n];s.forEach(function(e){o[e]=o[e]||a})})});var i=Object.keys(o).filter(function(e){return!o[e]}),s=i.map(function(t){return e.constructor.destroy(t,{adapter:e.adapter})});return L.all(s).then(function(){return{ok:!0}})})},h({ok:!0}))});n.viewCleanup=q.callbackify(function(){var e=this;return"http"===e.type()?y(e):B(e)}),n.query=function(e,t,n){"function"==typeof t&&(n=t,t={}),t=q.extend(!0,{},t),"function"==typeof e&&(e={map:e});var r=this,o=L.resolve().then(function(){return m(r,e,t)});return q.promisedCallback(o,n),o},q.inherits(_,Error),q.inherits(b,Error)}).call(this,e("_process"))},{"./create-view":58,"./evalfunc":59,"./taskqueue":63,"./utils":65,_process:34,"pouchdb-collate":61}],61:[function(e,t,n){"use strict";function r(e){if(null!==e)switch(typeof e){case"boolean":return e?1:0;case"number":return f(e);case"string":return e.replace(/\u0002/g,"").replace(/\u0001/g,"").replace(/\u0000/g,"");case"object":var t=Array.isArray(e),r=t?e:Object.keys(e),o=-1,i=r.length,s="";if(t)for(;++o<i;)s+=n.toIndexableString(r[o]);else for(;++o<i;){var a=r[o];s+=n.toIndexableString(a)+n.toIndexableString(e[a])}return s}return""}function o(e,t){var n,r=t,o="1"===e[t];if(o)n=0,t++;else{var i="0"===e[t];t++;var s="",a=e.substring(t,t+d),u=parseInt(a,10)+l;for(i&&(u=-u),t+=d;;){var c=e[t];if("\x00"===c)break;s+=c,t++}s=s.split("."),n=1===s.length?parseInt(s,10):parseFloat(s[0]+"."+s[1]),i&&(n-=10),0!==u&&(n=parseFloat(n+"e"+u))}return{num:n,length:t-r}}function i(e,t){var n=e.pop();if(t.length){var r=t[t.length-1];n===r.element&&(t.pop(),r=t[t.length-1]);var o=r.element,i=r.index;if(Array.isArray(o))o.push(n);else if(i===e.length-2){var s=e.pop();o[s]=n}else e.push(n)}}function s(e,t){for(var r=Math.min(e.length,t.length),o=0;r>o;o++){var i=n.collate(e[o],t[o]);if(0!==i)return i}return e.length===t.length?0:e.length>t.length?1:-1}function a(e,t){return e===t?0:e>t?1:-1}function u(e,t){for(var r=Object.keys(e),o=Object.keys(t),i=Math.min(r.length,o.length),s=0;i>s;s++){var a=n.collate(r[s],o[s]);if(0!==a)return a;if(a=n.collate(e[r[s]],t[o[s]]),0!==a)return a}return r.length===o.length?0:r.length>o.length?1:-1}function c(e){var t=["boolean","number","string","object"],n=t.indexOf(typeof e);return~n?null===e?1:Array.isArray(e)?5:3>n?n+2:n+3:Array.isArray(e)?5:void 0}function f(e){if(0===e)return"1";var t=e.toExponential().split(/e\+?/),n=parseInt(t[1],10),r=0>e,o=r?"0":"2",i=(r?-n:n)-l,s=p.padLeft(i.toString(),"0",d);o+=h+s;var a=Math.abs(parseFloat(t[0]));r&&(a=10-a);var u=a.toFixed(20);return u=u.replace(/\.?0+$/,""),o+=h+u}var l=-324,d=3,h="",p=e("./utils");n.collate=function(e,t){if(e===t)return 0;e=n.normalizeKey(e),t=n.normalizeKey(t);var r=c(e),o=c(t);if(r-o!==0)return r-o;if(null===e)return 0;switch(typeof e){case"number":return e-t;case"boolean":return e===t?0:t>e?-1:1;case"string":return a(e,t)}return Array.isArray(e)?s(e,t):u(e,t)},n.normalizeKey=function(e){switch(typeof e){case"undefined":return null;case"number":return 1/0===e||e===-1/0||isNaN(e)?null:e;case"object":var t=e;if(Array.isArray(e)){var r=e.length;e=new Array(r);for(var o=0;r>o;o++)e[o]=n.normalizeKey(t[o])}else{if(e instanceof Date)return e.toJSON();if(null!==e){e={};for(var i in t)if(t.hasOwnProperty(i)){var s=t[i];"undefined"!=typeof s&&(e[i]=n.normalizeKey(s))}}}}return e},n.toIndexableString=function(e){var t="\x00";return e=n.normalizeKey(e),c(e)+h+r(e)+t},n.parseIndexableString=function(e){for(var t=[],n=[],r=0;;){var s=e[r++];if("\x00"!==s)switch(s){case"1":t.push(null);break;case"2":t.push("1"===e[r]),r++;break;case"3":var a=o(e,r);t.push(a.num),r+=a.length;break;case"4":for(var u="";;){var c=e[r];if("\x00"===c)break;u+=c,r++}u=u.replace(/\u0001\u0001/g,"\x00").replace(/\u0001\u0002/g,"").replace(/\u0002\u0002/g,""),t.push(u);break;case"5":var f={element:[],index:t.length};t.push(f.element),n.push(f);break;case"6":var l={element:{},index:t.length};t.push(l.element),n.push(l);break;default:throw new Error("bad collationIndex or unexpectedly reached end of input: "+s)}else{if(1===t.length)return t.pop();i(t,n)}}}},{"./utils":62}],62:[function(e,t,n){"use strict";function r(e,t,n){for(var r="",o=n-e.length;r.length<o;)r+=t;return r}n.padLeft=function(e,t,n){var o=r(e,t,n);return o+e},n.padRight=function(e,t,n){var o=r(e,t,n);return e+o},n.stringLexCompare=function(e,t){var n,r=e.length,o=t.length;for(n=0;r>n;n++){if(n===o)return 1;var i=e.charAt(n),s=t.charAt(n);if(i!==s)return s>i?-1:1}return o>r?-1:0},n.intToDecimalForm=function(e){var t=0>e,n="";do{var r=t?-Math.ceil(e%10):Math.floor(e%10);n=r+n,e=t?Math.ceil(e/10):Math.floor(e/10)}while(e);return t&&"0"!==n&&(n="-"+n),n}},{}],63:[function(e,t){"use strict";function n(){this.promise=new r(function(e){e()})}var r=e("./utils").Promise;n.prototype.add=function(e){return this.promise=this.promise["catch"](function(){}).then(function(){return e()}),this.promise},n.prototype.finish=function(){return this.promise},t.exports=n},{"./utils":65}],64:[function(e,t){"use strict";function n(e,t,n){return new o(function(o,i){return t&&"object"==typeof t&&(t=t._id),"string"!=typeof t?i(new Error("doc id is required")):void e.get(t,function(s,a){if(s)return 404!==s.status?i(s):o(r(e,n({_id:t}),n));var u=n(a);return u?void o(r(e,u,n)):o(a)})})}function r(e,t,r){return e.put(t)["catch"](function(o){if(409!==o.status)throw o;return n(e,t,r)})}var o=e("./utils").Promise;t.exports=n},{"./utils":65}],65:[function(e,t,n){(function(t,r){"use strict";n.Promise="function"==typeof r.Promise?r.Promise:e("lie"),n.inherits=e("inherits"),n.extend=e("pouchdb-extend");var o=e("argsarray");n.promisedCallback=function(e,n){return n&&e.then(function(e){t.nextTick(function(){n(null,e)})},function(e){t.nextTick(function(){n(e)})}),e},n.callbackify=function(e){return o(function(t){var r=t.pop(),o=e.apply(this,t);return"function"==typeof r&&n.promisedCallback(o,r),o})},n.fin=function(e,t){return e.then(function(e){var n=t();return"function"==typeof n.then?n.then(function(){return e}):e},function(e){var n=t();if("function"==typeof n.then)return n.then(function(){throw e});throw e})},n.sequentialize=function(e,t){return function(){var n=arguments,r=this;return e.add(function(){return t.apply(r,n)})}},n.uniq=function(e){for(var t={},n=0,r=e.length;r>n;n++)t["$"+e[n]]=!0;var o=Object.keys(t),i=new Array(o.length);for(n=0,r=o.length;r>n;n++)i[n]=o[n].substring(1);return i};var i=e("crypto"),s=e("spark-md5");n.MD5=function(e){return t.browser?s.hash(e):i.createHash("md5").update(e).digest("hex")}}).call(this,e("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{_process:34,argsarray:27,crypto:28,inherits:38,lie:42,"pouchdb-extend":57,"spark-md5":66}],66:[function(e,t,n){!function(e){if("object"==typeof n)t.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var r;try{r=window}catch(o){r=self}r.SparkMD5=e()}}(function(){"use strict";var e=function(e,t){return e+t&4294967295},t=function(t,n,r,o,i,s){return n=e(e(n,t),e(o,s)),e(n<<i|n>>>32-i,r)},n=function(e,n,r,o,i,s,a){return t(n&r|~n&o,e,n,i,s,a)},r=function(e,n,r,o,i,s,a){return t(n&o|r&~o,e,n,i,s,a)},o=function(e,n,r,o,i,s,a){return t(n^r^o,e,n,i,s,a)},i=function(e,n,r,o,i,s,a){return t(r^(n|~o),e,n,i,s,a)},s=function(t,s){var a=t[0],u=t[1],c=t[2],f=t[3];a=n(a,u,c,f,s[0],7,-680876936),f=n(f,a,u,c,s[1],12,-389564586),c=n(c,f,a,u,s[2],17,606105819),u=n(u,c,f,a,s[3],22,-1044525330),a=n(a,u,c,f,s[4],7,-176418897),f=n(f,a,u,c,s[5],12,1200080426),c=n(c,f,a,u,s[6],17,-1473231341),u=n(u,c,f,a,s[7],22,-45705983),a=n(a,u,c,f,s[8],7,1770035416),f=n(f,a,u,c,s[9],12,-1958414417),c=n(c,f,a,u,s[10],17,-42063),u=n(u,c,f,a,s[11],22,-1990404162),a=n(a,u,c,f,s[12],7,1804603682),f=n(f,a,u,c,s[13],12,-40341101),c=n(c,f,a,u,s[14],17,-1502002290),u=n(u,c,f,a,s[15],22,1236535329),a=r(a,u,c,f,s[1],5,-165796510),f=r(f,a,u,c,s[6],9,-1069501632),c=r(c,f,a,u,s[11],14,643717713),u=r(u,c,f,a,s[0],20,-373897302),a=r(a,u,c,f,s[5],5,-701558691),f=r(f,a,u,c,s[10],9,38016083),c=r(c,f,a,u,s[15],14,-660478335),u=r(u,c,f,a,s[4],20,-405537848),a=r(a,u,c,f,s[9],5,568446438),f=r(f,a,u,c,s[14],9,-1019803690),c=r(c,f,a,u,s[3],14,-187363961),u=r(u,c,f,a,s[8],20,1163531501),a=r(a,u,c,f,s[13],5,-1444681467),f=r(f,a,u,c,s[2],9,-51403784),c=r(c,f,a,u,s[7],14,1735328473),u=r(u,c,f,a,s[12],20,-1926607734),a=o(a,u,c,f,s[5],4,-378558),f=o(f,a,u,c,s[8],11,-2022574463),c=o(c,f,a,u,s[11],16,1839030562),u=o(u,c,f,a,s[14],23,-35309556),a=o(a,u,c,f,s[1],4,-1530992060),f=o(f,a,u,c,s[4],11,1272893353),c=o(c,f,a,u,s[7],16,-155497632),u=o(u,c,f,a,s[10],23,-1094730640),a=o(a,u,c,f,s[13],4,681279174),f=o(f,a,u,c,s[0],11,-358537222),c=o(c,f,a,u,s[3],16,-722521979),u=o(u,c,f,a,s[6],23,76029189),a=o(a,u,c,f,s[9],4,-640364487),f=o(f,a,u,c,s[12],11,-421815835),c=o(c,f,a,u,s[15],16,530742520),u=o(u,c,f,a,s[2],23,-995338651),a=i(a,u,c,f,s[0],6,-198630844),f=i(f,a,u,c,s[7],10,1126891415),c=i(c,f,a,u,s[14],15,-1416354905),u=i(u,c,f,a,s[5],21,-57434055),a=i(a,u,c,f,s[12],6,1700485571),f=i(f,a,u,c,s[3],10,-1894986606),c=i(c,f,a,u,s[10],15,-1051523),u=i(u,c,f,a,s[1],21,-2054922799),a=i(a,u,c,f,s[8],6,1873313359),f=i(f,a,u,c,s[15],10,-30611744),c=i(c,f,a,u,s[6],15,-1560198380),u=i(u,c,f,a,s[13],21,1309151649),a=i(a,u,c,f,s[4],6,-145523070),f=i(f,a,u,c,s[11],10,-1120210379),c=i(c,f,a,u,s[2],15,718787259),u=i(u,c,f,a,s[9],21,-343485551),t[0]=e(a,t[0]),t[1]=e(u,t[1]),t[2]=e(c,t[2]),t[3]=e(f,t[3])},a=function(e){var t,n=[];for(t=0;64>t;t+=4)n[t>>2]=e.charCodeAt(t)+(e.charCodeAt(t+1)<<8)+(e.charCodeAt(t+2)<<16)+(e.charCodeAt(t+3)<<24);return n},u=function(e){var t,n=[];for(t=0;64>t;t+=4)n[t>>2]=e[t]+(e[t+1]<<8)+(e[t+2]<<16)+(e[t+3]<<24);return n},c=function(e){var t,n,r,o,i,u,c=e.length,f=[1732584193,-271733879,-1732584194,271733878];for(t=64;c>=t;t+=64)s(f,a(e.substring(t-64,t)));for(e=e.substring(t-64),n=e.length,r=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],t=0;n>t;t+=1)r[t>>2]|=e.charCodeAt(t)<<(t%4<<3);if(r[t>>2]|=128<<(t%4<<3),t>55)for(s(f,r),t=0;16>t;t+=1)r[t]=0;return o=8*c,o=o.toString(16).match(/(.*?)(.{0,8})$/),i=parseInt(o[2],16),u=parseInt(o[1],16)||0,r[14]=i,r[15]=u,s(f,r),f},f=function(e){var t,n,r,o,i,a,c=e.length,f=[1732584193,-271733879,-1732584194,271733878];for(t=64;c>=t;t+=64)s(f,u(e.subarray(t-64,t)));for(e=c>t-64?e.subarray(t-64):new Uint8Array(0),n=e.length,r=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],t=0;n>t;t+=1)r[t>>2]|=e[t]<<(t%4<<3);if(r[t>>2]|=128<<(t%4<<3),t>55)for(s(f,r),t=0;16>t;t+=1)r[t]=0;return o=8*c,o=o.toString(16).match(/(.*?)(.{0,8})$/),i=parseInt(o[2],16),a=parseInt(o[1],16)||0,r[14]=i,r[15]=a,s(f,r),f},l=["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"],d=function(e){var t,n="";for(t=0;4>t;t+=1)n+=l[e>>8*t+4&15]+l[e>>8*t&15];return n},h=function(e){var t;for(t=0;t<e.length;t+=1)e[t]=d(e[t]);return e.join("")},p=function(e){return h(c(e))},v=function(){this.reset()};return"5d41402abc4b2a76b9719d911017c592"!==p("hello")&&(e=function(e,t){var n=(65535&e)+(65535&t),r=(e>>16)+(t>>16)+(n>>16);return r<<16|65535&n}),v.prototype.append=function(e){return/[\u0080-\uFFFF]/.test(e)&&(e=unescape(encodeURIComponent(e))),this.appendBinary(e),this},v.prototype.appendBinary=function(e){this._buff+=e,this._length+=e.length;var t,n=this._buff.length;for(t=64;n>=t;t+=64)s(this._state,a(this._buff.substring(t-64,t)));return this._buff=this._buff.substr(t-64),this},v.prototype.end=function(e){var t,n,r=this._buff,o=r.length,i=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];for(t=0;o>t;t+=1)i[t>>2]|=r.charCodeAt(t)<<(t%4<<3);return this._finish(i,o),n=e?this._state:h(this._state),this.reset(),n},v.prototype._finish=function(e,t){var n,r,o,i=t;if(e[i>>2]|=128<<(i%4<<3),i>55)for(s(this._state,e),i=0;16>i;i+=1)e[i]=0;n=8*this._length,n=n.toString(16).match(/(.*?)(.{0,8})$/),r=parseInt(n[2],16),o=parseInt(n[1],16)||0,e[14]=r,e[15]=o,s(this._state,e)},v.prototype.reset=function(){return this._buff="",this._length=0,this._state=[1732584193,-271733879,-1732584194,271733878],this},v.prototype.destroy=function(){delete this._state,delete this._buff,delete this._length},v.hash=function(e,t){/[\u0080-\uFFFF]/.test(e)&&(e=unescape(encodeURIComponent(e)));var n=c(e);return t?n:h(n)},v.hashBinary=function(e,t){var n=c(e);return t?n:h(n)},v.ArrayBuffer=function(){this.reset()},v.ArrayBuffer.prototype.append=function(e){var t,n=this._concatArrayBuffer(this._buff,e),r=n.length;for(this._length+=e.byteLength,t=64;r>=t;t+=64)s(this._state,u(n.subarray(t-64,t)));return this._buff=r>t-64?n.subarray(t-64):new Uint8Array(0),this},v.ArrayBuffer.prototype.end=function(e){var t,n,r=this._buff,o=r.length,i=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];for(t=0;o>t;t+=1)i[t>>2]|=r[t]<<(t%4<<3);return this._finish(i,o),n=e?this._state:h(this._state),this.reset(),n},v.ArrayBuffer.prototype._finish=v.prototype._finish,v.ArrayBuffer.prototype.reset=function(){return this._buff=new Uint8Array(0),this._length=0,this._state=[1732584193,-271733879,-1732584194,271733878],this},v.ArrayBuffer.prototype.destroy=v.prototype.destroy,v.ArrayBuffer.prototype._concatArrayBuffer=function(e,t){var n=e.length,r=new Uint8Array(n+t.byteLength);return r.set(e),r.set(new Uint8Array(t),n),r},v.ArrayBuffer.hash=function(e,t){var n=f(new Uint8Array(e));return t?n:h(n)},v})},{}],67:[function(e,t,n){"use strict";function r(e,t,n){var r=n[n.length-1];e===r.element&&(n.pop(),r=n[n.length-1]);var o=r.element,i=r.index;if(Array.isArray(o))o.push(e);else if(i===t.length-2){var s=t.pop();o[s]=e}else t.push(e)}n.stringify=function(e){var t=[];t.push({obj:e});for(var n,r,o,i,s,a,u,c,f,l,d,h="";n=t.pop();)if(r=n.obj,o=n.prefix||"",i=n.val||"",h+=o,i)h+=i;else if("object"!=typeof r)h+="undefined"==typeof r?null:JSON.stringify(r);else if(null===r)h+="null";else if(Array.isArray(r)){for(t.push({val:"]"}),s=r.length-1;s>=0;s--)a=0===s?"":",",t.push({obj:r[s],prefix:a});t.push({val:"["})}else{u=[];for(c in r)r.hasOwnProperty(c)&&u.push(c);for(t.push({val:"}"}),s=u.length-1;s>=0;s--)f=u[s],l=r[f],d=s>0?",":"",d+=JSON.stringify(f)+":",t.push({obj:l,prefix:d});t.push({val:"{"})}return h},n.parse=function(e){for(var t,n,o,i,s,a,u,c,f,l=[],d=[],h=0;;)if(t=e[h++],"}"!==t&&"]"!==t&&"undefined"!=typeof t)switch(t){case" ":case" ":case"\n":case":":case",":break;case"n":h+=3,r(null,l,d);break;case"t":h+=3,r(!0,l,d);break;case"f":h+=4,r(!1,l,d);break;case"0":case"1":case"2":case"3":case"4":case"5":case"6":case"7":case"8":case"9":case"-":for(n="",h--;;){if(o=e[h++],!/[\d\.\-e\+]/.test(o)){h--;break}n+=o}r(parseFloat(n),l,d);break;case'"':for(i="",s=void 0,a=0;;){if(u=e[h++],'"'===u&&("\\"!==s||a%2!==1))break;i+=u,s=u,"\\"===s?a++:a=0}r(JSON.parse('"'+i+'"'),l,d);break;case"[":c={element:[],index:l.length},l.push(c.element),d.push(c);break;case"{":f={element:{},index:l.length},l.push(f.element),d.push(f);break;default:throw new Error("unexpectedly reached end of input: "+t)}else{if(1===l.length)return l.pop();r(l.pop(),l,d)}}},{}],68:[function(e,t){(function(n){"use strict";var r=e("./setup");t.exports=r,r.ajax=e("./deps/ajax"),r.extend=e("pouchdb-extend"),r.utils=e("./utils"),r.Errors=e("./deps/errors"),r.replicate=e("./replicate").replicate,r.sync=e("./sync"),r.version=e("./version");var o=e("./adapters/http");if(r.adapter("http",o),r.adapter("https",o),r.adapter("idb",e("./adapters/idb")),r.adapter("websql",e("./adapters/websql")),r.plugin(e("pouchdb-mapreduce")),!n.browser){var i=e("./adapters/leveldb");r.adapter("ldb",i),r.adapter("leveldb",i)}}).call(this,e("_process"))},{"./adapters/http":2,"./adapters/idb":3,"./adapters/leveldb":28,"./adapters/websql":5,"./deps/ajax":9,"./deps/errors":12,"./replicate":21,"./setup":22,"./sync":23,"./utils":25,"./version":26,_process:34,"pouchdb-extend":57,"pouchdb-mapreduce":60}]},{},[68])(68)}); \ No newline at end of file
diff --git a/docs/_config.yml b/docs/_config.yml deleted file mode 100644 index edc7a52..0000000 --- a/docs/_config.yml +++ /dev/null
@@ -1,9 +0,0 @@ -highlighter: pygments -markdown: redcarpet -baseurl: -version: 3.1.0 -paginate: 5 -paginate_path: "blog/page:num" -collections: - guides: - output: true
diff --git a/docs/_data/authors.yml b/docs/_data/authors.yml deleted file mode 100644 index ddf0184..0000000 --- a/docs/_data/authors.yml +++ /dev/null
@@ -1,23 +0,0 @@ -- name: Nick Colley - twitter: nickcolley - github: nickcolley - www: http://nickcolley.co.uk - gravatar: d83613912d1a2511a784b99c703bdcf6 - -- name: Nolan Lawson - twitter: nolanlawson - github: nolanlawson - www: http://nolanlawson.com - gravatar: c436dec61b906e27c963518d0ef1d972 - -- name: Dale Harvey - twitter: daleharvey - github: daleharvey - www: http://arandomurl.com - gravatar: 030451d8cfc268d666bae9a7fe8d10ec - -- name: Calvin Metcalf - twitter: CWMma - github: calvinmetcalf - www: http://calvinmetcalf.com/ - gravatar: e8153037a068f1c32e546f82729a64a5
diff --git a/docs/_guides/async-code.md b/docs/_guides/async-code.md deleted file mode 100644 index 37d038c..0000000 --- a/docs/_guides/async-code.md +++ /dev/null
@@ -1,227 +0,0 @@ ---- -index: 6 -layout: guide -title: Asynchronous code -sidebar: guides_nav.html ---- - -PouchDB provides a fully **asynchronous** API. This ensures that when you talk to PouchDB, the UI doesn't stutter, because the DOM is not being blocked by database operations. - -However, working with asynchronous code can be very complex, especially if you're only accustomed to synchronous APIs. So it's worth going over some of the basics. - -I promise to call you back... ------- - -To make things as flexible as possible for PouchDB users, the API is provided in both **callback** format and **promise** format. - -The **callback** format looks like this: - -```js -db.get('mittens', function (error, doc) { - if (error) { - // oh noes! we got an error - } else { - // okay, doc contains our document - } -}); -``` - -The **promise** format looks like this: - -```js -db.get('mittens').then(function (doc) { - // okay, doc contains our document -}).catch(function (err) { - // oh noes! we got an error -}); -``` - -Basically, if you include a callback as the last argument in a function, then PouchDB assumes you want the callback style. Otherwise it assumes you want the promise style. - -Let's talk about promises -------- - -For this guide, we will use the **promise** format for a few reasons: - -1. Callbacks easily lead to spaghetti code, or to the [pyramid of doom](https://medium.com/@wavded/managing-node-js-callback-hell-1fe03ba8baf). -2. Promises generally lead to better code organization, although they do have a steep learning curve. - -If you already understand promises, you can [skip to the next section](updating-deleting.html). - -Understanding promises ---------- - -If you have the time, you are strongly encouraged to watch [this 50-minute video: "Redemption from Callback Hell"](http://youtu.be/hf1T_AONQJU). The rest of this chapter basically summarizes that video. - -The best way to think of promises is that they bring keywords like `return` and `try/catch` to asynchronous code. - -Synchronous code: - -```js -function returnSomething() { - try { - doSomething(); - doSomethingElse(); - return true; - } catch (err) { - console.log(err); - } -} -``` - -Asynchronous code: - -```js -function returnSomething() { - return doSomething().then(function () { - return doSomethingElse(); - }).then(function () { - return true; - }).catch(function (err) { - console.log(err); - }); -} -``` - -Use `catch()` to catch errors --------- - -The big advantage of working with Promises in asynchronous code is that you can always attach a `catch` function to the end of a big promise chain, and any errors that occur along the way will show up at the end. - -This avoids endless `if (err) {}` checking in the callback world: - -```js -doSomething(function (err, result) { - if (err) { - // handle error - } - doSomethingElse(function (err, result) { - if (err) { - // handle error again... - } - doSomethingYetAgain(function (err, result) { - if (err) { - // seriously? okay, handle error again... - } - }); - }); -}); -``` - -Instead, in the promise world, you can have a long chain of asynchronous operations with a single `catch` at the end. To use PouchDB as an example: - -```js -db.put({_id: 'charlie', age: 21}).then(function () { - return db.get('charlie'); -}).then(function (charlie) { - // increment Charlie's age - charlie.age++; - return db.put(charlie); -}).then(function () { - return db.get('charlie'); -}).then(function (charlie) { - // increment Charlie's age again - charlie.age++; - return db.put(charlie); -}).then(function () { - return db.get('charlie'); -}).then(function (charlie) { - console.log(charlie); -}).catch(function (err) { - console.log(err); -}); -``` - -You should see: - -```js -{"age":23,"_id":"charlie","_rev":"3-e794618b4e39ed566cc68b56f5426e8e"} -``` - -You can see **[a live example](http://bl.ocks.org/nolanlawson/612f95cbbb69eaafc2d5)** of this code. - -In this example, we put/get a document 3 times in a row. At the very end, there is a `catch()` statement to catch any errors along the way. - -What kind of errors might we run into? Well, let's imagine that we accidentally misspell the id `'charlie'` at some point. In this case, we will gracefully catch the error. Here's another **[live example](http://bl.ocks.org/nolanlawson/0f1c815cb5fe74cff5fc)**. - -You should see: - -```js -{"status":404,"name":"not_found","message":"missing"} -``` - -This is really nice! No matter where the misspelling is, the error can be handled within a single function. That's much nicer than having to do `if (err){}` an endless number of times! - -An alternate way of catching errors -------- - -If you've been doing promises for awhile, you might have seen this instead: - -```js -db.get('charlie').then(function (charlie) { - // we got the charlie doc -}, function (err) { - // we got an error -}) -``` - -This is equivalent to: - -```js -db.get('charlie').then(function (charlie) { - // we got the charlie doc -}).catch(function (err) { - // we got an error -}) -``` - -The `catch()` method is just syntactic sugar. You can use either format. - -Promises 101 ------- - -The `then()` method takes a function. What can you do within this function? Three things: - -* Return another promise -* Throw an error -* Return a non-promise object (or `undefined`) - -Another way to think of it is this: - -```js -db.get('charlie').then(function (charlie) { - // Within this function, you can do - // try/catch/return like you normally would, - // and it will be handled asynchronously! -}).then(function (result) { - // If the previous function returned something - // (or returned undefined), it will show up here - // as "result". -}).catch(function (err) { - // If the previous function threw an error, - // it will show up here as "err". -}); -``` - -Promises in PouchDB -------- - -Promises are supported natively in [some browsers](http://caniuse.com/#feat=promises). But since they're not universally supported, we use [lie](https://github.com/calvinmetcalf/lie) in browsers that don't support them. In Node.js we use [bluebird](https://github.com/petkaantonov/bluebird). - -You are free to integrate any Promise library you like with PouchDB, as long as it is compliant with [the Promises A+ spec](http://promisesaplus.com/). Some libraries that fit the bill: - -<ul> -<li><a href="https://github.com/petkaantonov/bluebird">bluebird</a></li> -<li><a href="https://github.com/calvinmetcalf/lie">lie</a></li> -<li><a href="https://github.com/kriskowal/q">Q</a></li> -<li><a href="https://github.com/tildeio/rsvp.js">RSVP</a></li> -<li><a href="https://github.com/then/promise">then/promise</a></li> -<li><a href="https://github.com/cujojs/when">when</a></li> -</ul> - -If you use one of these libraries, then you will have access to some advanced Promise features. Read that library's documentation for details. - -Next ------- - -Now that you have a grasp on promises, let's learn about updating and deleting documents. \ No newline at end of file
diff --git a/docs/_guides/attachments.md b/docs/_guides/attachments.md deleted file mode 100644 index d5efce3..0000000 --- a/docs/_guides/attachments.md +++ /dev/null
@@ -1,196 +0,0 @@ ---- -index: 9 -layout: guide -title: Working with attachments -sidebar: guides_nav.html ---- - -Attachments are where PouchDB can get really fun. - -The big difference between storage engines like WebSQL/IndexedDB and the older localStorage API is that you can stuff [a lot more data](http://www.html5rocks.com/en/tutorials/offline/quota-research/) in it. - -PouchDB attachments allow you to use that to full advantage to store images, MP3s, zip files, or whatever you want. - -How attachments are stored ----------- - -As their name implies, attachments are *attached* to documents. You can work with attachments either in base64-encoded format, or as a [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob). - -For example, here is a very simple document with a plain text attachment, stored as base64. - -```js -db.put({ - _id: 'mydoc', - _attachments: { - 'myattachment.txt': { - content_type: 'text/plain', - data: 'aGVsbG8gd29ybGQ=' - } - } -}); -``` - -Our document has the usual `_id` field, but it also has a special `_attachments` field that holds the attachments. Documents can have as many attachments as you want. - -{% include alert_start.html variant="info" %} - -When you create an attachment, you need to specify its <code>content_type</code>, otherwise known as the <a href='https://en.wikipedia.org/wiki/MIME'>MIME type</a>. Common MIME types include <code>'text/plain'</code> for plain text, <code>'image/png'</code> for PNG images, and <code>'image/jpeg'</code> for JPG images. - -{% include alert_end.html %} - -As it turns out, `'aGVsbG8gd29ybGQ='` is just the string `'hello world'` encoded in base64. You can use the `atob()` and `btoa()` methods in your browser to verify. - -```js -btoa('hello world') // "aGVsbG8gd29ybGQ=" -atob('aGVsbG8gd29ybGQ=') // "hello world" -``` - -Let's see what happens after we store this document. If you try to `get()` it normally, you may be surprised to see that the attachment data itself isn't returned: - -```js -db.get('mydoc').then(function (doc) { - console.log(doc); -}); -``` - -The returned document will look like this: - -```js -{ - "_attachments": { - "myattachment.txt": { - "content_type": "text/plain", - "digest": "md5-XrY7u+Ae7tCTyyK7j1rNww==", - "stub": true - } - }, - "_id": "mydoc", - "_rev": "1-e8a84187bb4e671f27ec11bdf7320aaa" -} -``` - -You can see **[a live example](http://bl.ocks.org/nolanlawson/0a4b1267d3a5b5edd7b1)** of this code. - -By default, PouchDB will only give you an attachment **stub**, which contains a `digest`, i.e. the MD5 sum of the binary attachment. - -To get the full attachments when using `get()` or `allDocs()`, you need to specify `{attachments: true}`: - -```js -db.get('mydoc', {attachments: true}).then(function (doc) { - console.log(doc); -}); -``` - -Then you'll get back the full attachment, base64-encoded: - -```js -{ - "_attachments": { - "myattachment.txt": { - "content_type": "text/plain", - "digest": "md5-XrY7u+Ae7tCTyyK7j1rNww==", - "data": "aGVsbG8gd29ybGQ=" - } - }, - "_id": "mydoc", - "_rev": "1-e8a84187bb4e671f27ec11bdf7320aaa" -} -``` - -You can see **[a live example](http://bl.ocks.org/nolanlawson/b6d6164035f1fa0d38a8)** of this code. - -Image attachments --------- - -Plaintext is cool and all, but you know what would be *really* awesome? Storing images. - -So let's do it! In this example, we'll put a document with a small icon attachment, represented as a base64-encoded string. Then we'll fetch it and display the icon as a normal `<img>` tag: - -```js -db.put({ - _id: 'meowth', - _attachments: { - 'meowth.png': { - content_type: 'image/png', - data: 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAkCAIAAAB0Xu9BAAAABGdBTUEAALGPC/xhBQAAAuNJREFUWEetmD1WHDEQhDdxRMYlnBFyBIccgdQhKVcgJeQMpE5JSTd2uqnvIGpVUqmm9TPrffD0eLMzUn+qVnXPwiFd/PP6eLh47v7EaazbmxsOxjhTT88z9hV7GoNF1cUCvN7TTPv/gf/+uQPm862MWTL6fff4HfDx4S79/oVAlAUwqOmYR0rnazuFnhfOy/ErMKkcBFOr1vOjUi2MFn4nuMil6OPh5eGANLhW3y6u3aH7ijEDCxgCvzFmimvc95TekZLyMSeJC68Bkw0kqUy1K87FlpGZqsGFCyqEtQNDdFUtFctTiuhnPKNysid/WFEFLE2O102XJdEE+8IgeuGsjeJyGHm/xHvQ3JtKVsGGp85g9rK6xMHtvHO9+WACYjk5vkVM6XQ6OZubCJvTfPicYPeHO2AKFl5NuF5UK1VDUbeLxh2BcRGKTQE3irHm3+vPj6cfCod50Eqv5QxtwBQUGhZhbrGVuRia1B4MNp6edwBxld2sl1splfHCwfsvCZfrCQyWmX10djjOlWJSSy3VQlS6LmfrgNvaieRWx1LZ6s9co+P0DLsy3OdLU3lWRclQsVcHJBcUQ0k9/WVVrmpRzYQzpgAdQcAXxZzUnFX3proannrYH+Vq6KkLi+UkarH09mC8YPr2RMWOlEqFkQClsykGEv7CqCUbXcG8+SaGvJ4a8d4y6epND+pEhxoN0vWUu5ntXlFb5/JT7JfJJqoTdy9u9qc7ax3xJRHqJLADWEl23cFWl4K9fvoaCJ2BHpmJ3s3z+O0U/DmzdMjB9alWZtg4e3yxzPa7lUR7nkvxLHO9+tvJX3mtSDpwX8GajB283I8R8a7D2MhUZr1iNWdny256yYLd52DwRYBtRMvE7rsmtxIUE+zLKQCDO4jlxB6CZ8M17GhuY+XTE8vNhQiIiSE82ZsGwk1pht4ZSpT0YVpon6EvevOXXH8JxVR78QzNuamupW/7UB7wO/+7sG5V4ekXb4cL5Lyv+4IAAAAASUVORK5CYII=' - } - } -}).then(function () { - return db.getAttachment('meowth', 'meowth.png'); -}).then(function (blob) { - var url = URL.createObjectURL(blob); - var img = document.createElement('img'); - img.src = url; - document.body.appendChild(img); -}).catch(function (err) { - console.log(err); -}); -``` - -You can see **[a live example](http://bl.ocks.org/nolanlawson/2a5f98a66c9fe3ae3532)** of this code. - -You should be unsurprised to see a cat smiling back at you. If the kitten theme bothers you, then you haven't been on the Internet very long. - -How does this code work? First off, we are making use of the `URL.createObjectURL()` method, which is a standard HTML5 method that converts a `Blob` to a URL that we can easily use as the `src` of an `img`. - -Second off, we are using the `getAttachment()` API, which returns a `Blob` rather than a base64-encoded string. To be clear: we can always convert between base64 and `Blob`s, but in this case, `getAttachment()` is just more convenient. - -Directly storing binary data -------------- - -Up to now, we've been supplying our attachments as base64-encoded strings. But we can also create the Blobs ourselves and store those directly in PouchDB. - -Another shortcut we can use is the `putAttachment()` API, which simply modifies the existing document to hold a new attachment. Or, if the document does not exist, it will create an empty one. - -{% include alert_start.html variant="info" %} - -<strong>Node.js</strong>: in Node.js, PouchDB uses <a href='http://nodejs.org/api/buffer.html'>Buffers</a> instead of Blobs. Otherwise, the same rules apply. - -{% include alert_end.html %} - -For instance, we can read the image data from an `<img>` tag using a `canvas` element, and then directly write that Blob to PouchDB: - -```js -function convertImgToBlob(img, callback) { - var canvas = document.createElement('canvas'); - var context = canvas.getContext('2d'); - context.drawImage(img, 0, 0); - - // Warning: toBlob() isn't supported by every browser. - // You may want to use blob-util. - canvas.toBlob(callback, 'image/png'); -} - -var catImage = document.getElementById('cat'); -convertImgToBlob(catImage, function (blob) { - db.putAttachment('meowth', 'meowth.png', blob, 'image/png').then(function () { - return db.get('meowth', {attachments: true}); - }).then(function (doc) { - console.log(doc); - }); -}); -``` - -You can see **[a live example](http://bl.ocks.org/nolanlawson/edaf09b84185418a55d9)** of this code. - -This stores exactly the same image content as in the other example, which you can confirm by checking the base64-encoded output. - -Whather you supply attachments as base64-encoded strings or as Blobs/Buffers, under the hood PouchDB will try to store them in [the most efficient way](/faq.html#data_types). All of the "write" APIs – `putAttachment()`, `put()`, `bulkDocs()`, and `post()` – accept either base64 strings or Blobs/Buffers. - -{% include alert_start.html variant="warning" %} - -Blobs can be tricky to work with, especially when it comes to cross-browser support. You may find <a href='https://github.com/nolanlawson/blob-util'>blob-util</a> to be a useful addition to the attachment API. For instance, it has an <code>imgSrcToBlob()</code> method that will work cross-browser. - -{% include alert_end.html %} - -Related API documentation --------- - -* [putAttachment()](/api.html#save_attachment) -* [getAttachment()](/api.html#get_attachment) -* [removeAttachment()](/api.html#delete_attachment) - -Next ----- - -Now that you can attach cat pictures to all your documents (and why wouldn't you?), let's talk about replication. \ No newline at end of file
diff --git a/docs/_guides/bulk-operations.md b/docs/_guides/bulk-operations.md deleted file mode 100644 index 4e9f8c0..0000000 --- a/docs/_guides/bulk-operations.md +++ /dev/null
@@ -1,138 +0,0 @@ ---- -index: 8 -layout: guide -title: Bulk operations -sidebar: guides_nav.html ---- - -You can `get()`, `put()`, and `remove()` single documents to your heart's content, but a database isn't a database unless it can handle many operations at once! - -PouchDB provides two methods for bulk operations - `bulkDocs()` for bulk writes, and `allDocs()` for bulk reads. - -Use `bulkDocs()` to write many docs ----- - -The `bulkDocs()` API is very simple. It just takes a list of documents that you want to `put()` into the database: - -```js -db.bulkDocs([ - { - _id: 'mittens', - occupation: 'kitten', - cuteness: 9.0 - }, - { - _id: 'katie', - occupation: 'kitten', - cuteness: 7.0 - }, - { - _id: 'felix', - occupation: 'kitten', - cuteness: 8.0 - } -]); -``` - -You can see **[a live example](http://bl.ocks.org/nolanlawson/038a45134341f3b7235b)** of this code. - -This code is equivalent to `put()`ing each document separately: - -```js -db.put({ - _id: 'mittens', - occupation: 'kitten', - cuteness: 9.0 -}).then(function () { - return db.put({ - _id: 'katie', - occupation: 'kitten', - cuteness: 7.0 - }); -}).then(function () { - return db.put({ - _id: 'felix', - occupation: 'kitten', - cuteness: 8.0 - }); -]); -``` - -Why bulk up with `bulkDocs()`? ----- - -Bulk operations tend to be faster than individual operations, because they can be combined into a single transaction (in a local IndexedDB/WebSQL) or a single HTTP request (in a remote CouchDB). - -You can also update or delete multiple documents this way. You just need to include the `_rev` and `_deleted` values as previously discussed. The same rules as for `put()` apply to each individual document. - -{% include alert_start.html variant="warning" %} - -Neither <code>bulkDocs()</code> nor <code>allDocs()</code> constitutes a transaction in the traditional sense. That means that, if a single <code>put()</code> fails, you should not assume that the others will fail. -<p/> -<p/> -By design, CouchDB and PouchDB do not support transactions. A document is the smallest unit of operations. -{% include alert_end.html %} - -Use `allDocs()` to read many docs --------- - -Likewise, `allDocs()` is a method that allows you to read many documents at once. - -Most crucially, when you read from `allDocs()`, the documents are returned *sorted by order of `_id`*. This makes the `_id` a very powerful field that you can use for more than just uniquely identifying your documents. - -For instance, if you refer back to [the live example](http://bl.ocks.org/nolanlawson/038a45134341f3b7235b) above, you'll notice that the kittens are sorted by their name, because their names are used as their `_id`s. - -Another common way to take advantage of this is to use `new Date().toJSON()` as your document `_id`s. In this way, all your documents will be sorted by date. - -For instance, let's save three kittens with three different dates, and then fetch them sorted by date: - -```js -db.put({ - _id: new Date().toJSON(), - name: 'Mittens', - occupation: 'kitten', - cuteness: 9.0 -}).then(function () { - return db.put({ - _id: new Date().toJSON(), - name: 'Katie', - occupation: 'kitten', - cuteness: 7.0 - }); -}).then(function () { - return db.put({ - _id: new Date().toJSON(), - name: 'Felix', - occupation: 'kitten', - cuteness: 8.0 - }); -]).then(function () { - return db.allDocs({include_docs: true}); -}).then(function (response) { - console.log(response); -}).catch(function (err) { - console.log(err); -}); -``` - -You can see **[a live example](http://bl.ocks.org/nolanlawson/8f58dbc360348a4c95f6)** to confirm that the kittens are sorted by the order they were put into the database. - -Please use `allDocs()`. Seriously. -------- - -`allDocs()` is the unsung star of the PouchDB world. It not only returns documents in order – it also allows you to reverse the order, filter by `_id`, slice and dice using "greater than" and "less than" operations on the `_id`, and much more. - -Far too many developers overlook this valuable API, because they misunderstand it. When a developer says "my PouchDB app is slow!", it is usually because they are using the slow `query()` API when they should be using the fast `allDocs()` API. - -For details on how to effectively use `allDocs()`, you are strongly recommended to read ["Pagination strategies with PouchDB"](http://pouchdb.com/2014/04/14/pagination-strategies-with-pouchdb.html). For 99% of your applications, you should be able to use `allDocs()` for all the pagination/sorting/searching functionality that you need. - -Related API documentation --------- - -* [bulkDocs()](/api.html#batch_create) -* [allDocs()](/api.html#batch_fetch) - -Next ------- - -Now that you've fallen helplessly in love with `bulkDocs()` and `allDocs()`, let's turn our wandering gaze to attachments. \ No newline at end of file
diff --git a/docs/_guides/changes.md b/docs/_guides/changes.md deleted file mode 100644 index 83d2ada..0000000 --- a/docs/_guides/changes.md +++ /dev/null
@@ -1,104 +0,0 @@ ---- -index: 12 -layout: guide -title: Changes feed -sidebar: guides_nav.html ---- - -One of the brilliant things about CouchDB replication is that it makes it easy to learn about changes made to the database over time. CouchDB allows you to easily answer questions like: - -* What changes occurred to the database since a given time? -* What changes occurred to this document? -* What did this database look like a few days ago? - -For all of these and related questions, there's the `changes()` API. - -Basic changes usage ---------- - -If you want to simply fetch all changes since the beginning of time, you can do: - -```js -db.changes({ - since: 0 -}).then(function (changes) { - -}).catch(function (err) { - // handle errors -}); -``` - -You can see a **[live example](http://bl.ocks.org/nolanlawson/7c32861af5d31a8fac4a)** of this code. - -Then you will have a list of all changes made to the database, in the order that they were made. - -One thing you will notice about the changes feed is that it actually omits non-leaf revisions to documents. For instance, in the live example, we skip from `seq` 1 immediately to `seq` 3. - -This is by design – the changes feed only tells us about leaf revisions. However, the order of those leaf revisions is determined by the order they were put in the database. So you may notice that `'firstDoc'` still appears before `'secondDoc'`, which appears before `'thirdDoc'`. - -Changes pagination ------- - -If you expect this to be a very large number of changess, you can also use the `limit` option to do pagination: - -```js -var pageSize = 10; -var lastSeq = 0; -function fetchNextPage() { - return db.changes({ - since: lastSeq, - limit: pageSize - }).then(function (changes) { - if (changes.results.length < pageSize) { - // done! - } else { - lastSeq = changes.results[changes.results.length - 1].seq; - return fetchNextPage(); - } - }); -} - -fetchNextPage().catch(function (err) { - // handle errors -}); -``` - -You can see a **[live example](http://bl.ocks.org/nolanlawson/dcdeae555b31c2a6d332)** of this code. - -`seq` versus `_rev` ---------- - -The changes feed lists each change with a corresponding `seq` integer. `seq` always starts with 0, and beyond that it increases monotonically. (In Cloudant, these are strings rather than integers.) - -`seq` can be thought of as a version number for the entire database. Basically it answers the question of "How many total changes have been made to all documents in this database?" This sets it apart from the revision hash `_rev`, which marks the changes made to a single document. - -However, the `seq` between two databases is not guaranteed to be kept in sync. CouchDB and PouchDB have slightly different ways of increasing their `seq` values, so really `seq` is only meaningful within a single database. - -Live changes feed -------- - -Just like replication, you can also listen to a live changes feed. The way this works is very similar to the replication API: - -```js -db.changes({ - since: 'now' -}).on('change', function (change) { - // received a change -}).on('error', function (err) { - // handle errors -}); -``` - -In the above example, we've also taken advantage of the quasi-magical `'now'` option for `since`, which will give us all changes from the moment we start listening. - -This can be very useful for scenarios where you want to update the UI whenever something in the database changes, such as for a real-time chat application. - -Related API documentation --------- - -* [changes()](/api.html#changes) - -Next ------ - -Now that we know how to hook our data spigot to the changes feed, let's look into using the very powerful `query()` API. \ No newline at end of file
diff --git a/docs/_guides/compact-and-destroy.md b/docs/_guides/compact-and-destroy.md deleted file mode 100644 index 97a690d..0000000 --- a/docs/_guides/compact-and-destroy.md +++ /dev/null
@@ -1,109 +0,0 @@ ---- -index: 14 -layout: guide -title: Compacting and destroying -sidebar: guides_nav.html ---- - -By default, PouchDB and CouchDB are designed to store all document revisions forever. This is very similar to how Git works, and it helps ensure that two databases can consistently replicate with each other. - -However, if you allow your database to grow without bounds, it can end up taking up much more space than you need. This can especially be a problem in [browsers with storage quotas](http://localhost:4000/faq.html#data_limits). - -To mitigate this problem, PouchDB offers two recourses: compaction and destruction. - -Compacting a database ------- - -When you compact a database, you tell PouchDB to optimize its current storage usage. CouchDB will do the same thing: - -```js -return db.compact().then(function (info) { - // compaction complete -}).catch(function (err) { - // handle errors -}); -``` - -From the API perspective, nothing should be different about the database after compaction, *except* that non-leaf revisions will no longer be available. - -```js -db.put({_id: 'foo', version: 1}).then(function () { - return db.get('foo'); -}).then(function (doc) { - doc.version = 2; - return db.put(doc); -}).then(function () { ) - return db.compact(); -}).then(function () { - // DANGER! - // From now on, revision 1 is no longer available. -}).catch(function (err) { - // handle errors -}); -``` - -You can see a **[live example](http://bl.ocks.org/nolanlawson/ff6eb521793e3a199864)** of this code. - -Compaction is a great feature, but it may not be what you desire if you want to retain a document's history from the beginning of time. - -However, if that's not a concern, then compaction is a harmless operation. In fact, since leaf revisions are retained, this means that you can still do [conflict resolution](/guides/conflicts.html) after compaction! - -Auto-compaction ------- - -If you really want to go all-in on compaction, then you can even put your database in `auto_compaction` mode. This means that it will automatically perform a `compact()` operation after every write. - -```js -var db = new PouchDB('mydb', {auto_compaction: true}); -db.put({_id: 'foo', version: 1}).then(function () { - return db.get('foo'); -}).then(function (doc) { - doc.version = 2; - return db.put(doc); -}).then(function () { - // Revision 1 is already unavailable! -}).catch(function (err) { - // handle errors -}); -``` - -You can see a **[live example](http://bl.ocks.org/nolanlawson/b88f46d7cbaef8d93cba)** of this code. - -This feature is only available in local databases, not remote ones. On remote databases, the `auto_compaction` option will do nothing. - -Destroying a database ----- - -We all love our databases, but sometimes good things must come to an end, and you need to snub out a database completely. - -So if you want to give your database to a nice farm family upstate, then the `destroy()` API is for you. It's very simple: - -```js -new PouchDB('mydb').destroy().then(function () { - // database destroyed -}).catch(function (err) { - // error occurred -}) -``` - -Or: - -```js -PouchDB.destroy('mydb').then(function () { - // database destroyed -}).catch(function (err) { - // error occurred -}) -``` - -These two methods are equivalent. - -Note that destroying a database does not mean that replicated databases will also be destroyed. Destruction has nothing to do with the normal `put()`/`remove()` operations on documents, so it has no impact on replication. - -Also note that in Web SQL, the database will not really be destroyed – it will just have its tables dropped. This is because Web SQL does not support true database deletion. - -Related API documentation --------- - -* [compact()](/api.html#compaction) -* [destroy()](/api.html#delete_database) \ No newline at end of file
diff --git a/docs/_guides/conflicts.md b/docs/_guides/conflicts.md deleted file mode 100644 index 2eaaeff..0000000 --- a/docs/_guides/conflicts.md +++ /dev/null
@@ -1,168 +0,0 @@ ---- -index: 11 -layout: guide -title: Conflicts -sidebar: guides_nav.html ---- - -Conflicts are an unfortunate reality when dealing with distributed systems. And make no mistake: client-server *is* a distributed system. - -CouchDB and PouchDB differ from many other sync solutions, because they bring the issue of conflicts front-and-center. With PouchDB, how you handle conflicts is entirely under your control. - -Two types of conflicts -------- - -In CouchDB, conflicts can occur in two places: immediately, when you try to commit a new revision, or later, when two peers have committed changes to the same document. - -### Immediate conflicts - -**Immediate conflicts** can occur with any API that can take a `rev` or a document with a `_rev` as input – `put()`, `post()`, `remove()`, `bulkDocs()`, and `putAttachment()`. They manifest as a `409` (conflict) error: - -```js -var myDoc = { - _id: 'someid', - _rev: '1-somerev' -}; -db.put(myDoc).then(function () { - // success -}).catch(function (err) { - if (err.status === 409) { - // conflict! - } else { - // some other error - } -}); -``` - -In your code, *you should always be handling conflicts*. No matter how unlikely it may seem, 409s can and do occur. - -For instance, if you are doing live replication, a document may be modified by somebody else while the user is working on it. If the remote changes are replicated to the local database before the user tries to commit their changes, then they will receive the above 409 error. - -#### Upsert - -In many cases, the most practical solution to the 409 problem is to simply re-try the `put()` until it works. If the user's intended change can be expressed as a **delta**, i.e. a change that doesn't depend on the current revision, then this is very easy to achieve. Borrowing a phrase from MongoDB, we can call this an **upsert**, and implement it like so: - -```js -function upsert(db, docId, deltaFunc) { - return db.get(docId).catch(function (err) { - if (err.status !== 404) { - // some error other than "not found" - throw err; - } - return {_id : docId}; // default doc - }).then(function (doc) { - return tryAndPut(db, deltaFunc(doc), deltaFunc); - }); -} - -function tryAndPut(db, doc, deltaFunc) { - return db.put(doc).catch(function (err) { - if (err.status !== 409) { - // some error other than "conflict" - throw err; - } - return upsert(db, doc, deltaFunc); - }); -} -``` - -This `upsert()` function takes a `db`, a `docId`, and `deltaFunc`, where the `deltaFunc` is just a function that takes a document as input and outputs a new document. - -For instance, imagine your `upsert` just increments some counter: - -```js -function delta(doc) { - doc.counter = doc.counter || 0; - doc.counter++; - return doc; -} - -upsert(db, 'my_id', delta).then(function () { - // success! -}).catch(function (err) { - // error (not a 404 or 409) -}); -``` - -This code is simple and easy to use. - -### Non-immediate conflicts - -Imagine two PouchDB databases that have both gone offline. The two separate users each make modifications to the same document, and then come back online at the same time. They have both successfuly committed changes to the same document, and their local databases did not throw 409 errors. What happens then? - -This the classic "conflict" scenario, and CouchDB handles it very elegantly. By default, a winning revision will be chosen arbitrarily, so unfortunately one user will lose their data. However, since the replication history is stored, you can always go back in time and respond to the conflict. - -To detect if a document is in conflict, you use the `{conflicts: true}` option when you `get()` it. - -```js -db.get('docid', {conflicts: true}).then(function (doc) { - // do something with the doc -}).catch(function (err) { - // handle any errors -}); -``` - -If the document has conflicts, then the `doc` will be returned with a `_conflicts` attribute, which may contain the IDs of conflicting revisions. - -For instance, imagine the `doc` returned is the following: - -```js -{ - "_id": "docid", - "_rev": "2-f3d4c66dcd7596419c76b2498b3ba21f", - "_conflicts": ["2-c1592ce7b31cc26e91d2f2029c57e621"] -} -``` - -Here we have a conflict introduced from another database, and that database's revision has arbitrarily won. This document's current revision starts with 2-, and the conflicting version also starts with 2-, indicating that they're both at the same level of the revision tree. (Recall that revision hashes start with `1-`, `2-`, `3-`, etc.) - -Both databases will see the same conflict, assuming replication has completed. In fact, all databases in the network will see the exact same revision history – much like Git. - -To fetch the losing revision, you simply `get()` it using the `rev` option: - -```js -db.get('docid', {rev: '2-f3d4c66dcd7596419c76b2498b3ba21f'}).then(function (doc) { - // do something with the doc -}).catch(function (err) { - // handle any errors -}); -``` - -At this point, you can present both versions to the user, or resolve the conflict automatically using your preferred conflict resolution strategy: last write wins, first write wins, [RCS](https://www.gnu.org/software/rcs/), etc. - -To mark a conflict as resolved, all you need to do is `remove()` the unwanted revisions. So for instance, to remove `'2-f3d4c66dcd7596419c76b2498b3ba21f'`, you would do: - -```js -db.remove('docid', '2-f3d4c66dcd7596419c76b2498b3ba21f').then(function (doc) { - // yay, we're done -}).catch(function (err) { - // handle any errors -}); -``` - -If you want to resolve the conflict by creating a new revision, you simply `put()` a new document on top of the current winner. - - -Accountants don't use erasers -------- - -Another conflict resolution strategy is to design your database so that conflicts are impossible. In practice, this means that you never update or remove existing documents – you only create new documents. - -This strategy has been called the "every doc is a delta" strategy. A classic use-case for this would be a checkbook app, where every document is simply an operation that increases or decreases the account balance: - -```js -{_id: new Date().toJSON(), change: 100} // balance increased by $100 -{_id: new Date().toJSON(), change: -50} // balance decreased by $50 -{_id: new Date().toJSON(), change: 200} // balance increased by $200 -``` - -In this system, it is impossible for two documents to conflict, because the document `_id`s are just timestamps. Ledger transactions are recorded in the order they were made, and at the end of the day, you only need to do an `allDocs()` or `query()` operation to sum the result. - -The wisdom of this strategy can be expressed by the maxim: ["Accountants don't use erasers"](http://blogs.msdn.com/b/pathelland/archive/2007/06/14/accountants-don-t-use-erasers.aspx). Like a diligent accountant, your app can just add new documents when you want to make a change, rather than going back and scrubbing out previous changes. - -There is also a PouchDB plugin that implements this strategy: [delta-pouch](https://github.com/redgeoff/delta-pouch). - -Next -------- - -Now that we've settled our conflicts, let's take a look at the changes feed.
diff --git a/docs/_guides/databases.md b/docs/_guides/databases.md deleted file mode 100644 index d0cb2c2..0000000 --- a/docs/_guides/databases.md +++ /dev/null
@@ -1,157 +0,0 @@ ---- -index: 4 -layout: guide -title: Working with databases -sidebar: guides_nav.html ---- - -PouchDB databases come in two flavors: local and remote. - -Local databases --------- - -To create a local database, you simply call `new PouchDB` and give it a name: - -```js -var db = new PouchDB('kittens'); -``` - -You can see a **[live example](http://bl.ocks.org/nolanlawson/bddac54b92c2d8d39241)** of this code. - -{% include alert_start.html variant="info" %} - -<strong>Protip:</strong> whenever you see a live example in this guide, you can download it to follow along at home! For example, to run this example, just enter the following commands in your command prompt: -<p/> -<code> -<br/>git clone https://gist.github.com/bddac54b92c2d8d39241.git kittens -<br/>cd kittens -<br/>python -m SimpleHTTPServer -</code> -<p/> -Now the site is up and running at <a href='http://localhost:8000'>http://localhost:8000</a>. To find the correct <code>gist.github.com</code> URL, just click the "block" number at the top of the page. - -{% include alert_end.html %} - -Remote databases --------- - -To create a remote database, you call `new PouchDB` and give it a path to a database in CouchDB. - -```js -var db = new PouchDB('http://localhost:5984/kittens'); -``` - -The structure of a CouchDB URL is very simple: - -``` -http:// localhost:5984 /kittens -⌞_____⌟ ⌞____________⌟ ⌞_____⌟ - | | | -Protocol Where CouchDB database -(https if itself is name -Cloudant) hosted - -``` - -If the remote database doesn't exist, then PouchDB will create it for you. - -You can verify that your database is working by visiting the URL [http://localhost:5984/kittens](http://localhost:5984/kittens). You should see something like this: - -```js -{"db_name":"kittens","doc_count":0,"doc_del_count":0,"update_seq":0,"purge_seq":0,"compact_running":false,"disk_size":79,"data_size":0,"instance_start_time":"1410722558431975","disk_format_version":6,"committed_update_seq":0} -``` - -If instead you see: - -```js -{"error":"not_found","reason":"no_db_file"} -``` - -Then check to make sure that your remote PouchDB has started up correctly. Common errors (such as CORS) are [listed here](/errors.html). - -Get basic info about the database ---------- - -You can see basic information about the database by using the `info()` method. - -```js -db.info().then(function (info) { - console.log(info); -}) -``` - -The local database should show something like: - -```js -{"doc_count":0,"update_seq":0,"db_name":"kittens"} -``` - -The remote database may have a bit more information: - -```js -{"db_name":"kittens","doc_count":0,"doc_del_count":0,"update_seq":0,"purge_seq":0,"compact_running":false,"disk_size":79,"data_size":0,"instance_start_time":"1410722558431975","disk_format_version":6,"committed_update_seq":0} -``` - -The most important bits of information are: - -* `doc_count`: the number of undeleted documents in the database -* `db_name`: the name of the database - -Debugging your local database ---------- - -When you create a local PouchDB, you can use the developer tools to see what the database looks like under the hood. - -In Chrome, just choose *Overflow icon* ☰ → *Tools* → *Developer Tools*. Then click the *Resources* tab, then *IndexedDB*, and you should see the following: - -<img src="/static/img/dev_tools.png" alt="Chrome Developer Tools" style="width:100%"/> - -This is the raw IndexedDB representation of your PouchDB, so it may be a little fine-grained compared to what PouchDB shows. However, it's great for quick debugging. - -In Safari, the `kittens` database will be under *WebSQL* instead of *IndexedDB*. - -### Debug mode - -You can also enable debug logging by doing: - -```js -PouchDB.debug.enable('*'); -``` - -And then disable it by doing: - -```js -PouchDB.debug.disable(); -``` - - -Deleting your local database ----------------- - -During development, it's often useful to destroy the local database, so you can see what your users will experience when they visit your site for the first time. A page refresh is not enough, because the data will still be there! - -In Chrome, you can use the [ClearBrowserData extension](https://chrome.google.com/webstore/detail/clearbrowserdata/apehfighfmpoieeniallefdeibodgmmb), which will add a trashcan icon to your toolbar, which you can click to delete all local data (IndexedDB, WebSQL, LocalStorage, cookies, etc.). - -In Firefox, you can use the [Clear Recent History+ add-on](https://addons.mozilla.org/en-US/firefox/addon/clear-recent-history/), so when you right-click a page you can quickly clear all data. - -In Safari, you can simply click *Safari* → *Clear History and Website Data*. - -Differences between the local and remote databases -------- - -When you create a local PouchDB database, it uses whatever underlying datastore is available - IndexedDB in most browsers, WebSQL in older browsers, and LevelDB in Node.js. - -When you create a remote PouchDB database, it communicates directly with the remote database – CouchDB, Cloudant, Couchbase, etc. - -The goal of PouchDB is to allow you to seamlessly communicate with one or the other. You should not notice many differences between the two, except that of course the local one is much faster! - -Related API documentation --------- - -* [new PouchDB() (constructor)](/api.html#create_database) -* [Debug mode](/api.html#debug_mode) - -Next -------- - -Now that you've created some databases, let's put some documents in 'em! \ No newline at end of file
diff --git a/docs/_guides/documents.md b/docs/_guides/documents.md deleted file mode 100644 index 3649567..0000000 --- a/docs/_guides/documents.md +++ /dev/null
@@ -1,197 +0,0 @@ ---- -index: 5 -layout: guide -title: Working with documents -sidebar: guides_nav.html ---- - -What's a document? -------- - -PouchDB is a NoSQL database, meaning that you store unstructured *documents* rather than explicitly specifying a schema with rows, tables, and all that jazz. - -A document might look like this: - -```js -{ - "_id": "mittens", - "name": "Mittens", - "occupation": "kitten", - "age": 3, - "hobbies": [ - "playing with balls of yarn", - "chasing laser pointers", - "lookin' hella cute" - ] -} -``` - -If you come from a SQL background, this handy conversion chart may help: - -<div class="table-responsive"> -<table class="table"> -<tr> - <th>SQL concept</th> - <th>PouchDB concept</th> -</tr> -<tr> - <td>table</td> - <td><em>no equivalent</em></td> -</tr> -<tr> - <td>row</td> - <td>document</td> -</tr> - -<tr> - <td>column</td> - <td>field</td> -</tr> -<tr> - <td>primary key</td> - <td>primary key (<code>_id</code>)</td> -</tr> -<tr> - <td>index</td> - <td>view</td> -</tr> -</table> -</div> - -We'll discuss these concepts later on. - -Storing a document -------------- - -To store a document, you simply `put` it: - -```js -var doc = { - "_id": "mittens", - "name": "Mittens", - "occupation": "kitten", - "age": 3, - "hobbies": [ - "playing with balls of yarn", - "chasing laser pointers", - "lookin' hella cute" - ] -}; -db.put(doc); -``` - -Whenever you `put()` a document, it must have an `_id` field so that you can retrieve it later. - -So now let's `get()` the document by using its `_id`: - -```js -db.get('mittens').then(function (doc) { - console.log(doc); -}); -``` - -You should see: - -```js -{ - "name": "Mittens", - "occupation": "kitten", - "age": 3, - "hobbies": [ - "playing with balls of yarn", - "chasing laser pointers", - "lookin' hella cute" - ], - "_id": "mittens", - "_rev": "1-bea5fa18e06522d12026f4aee6b15ee4" -} -``` - -You can see a **[live example](http://bl.ocks.org/nolanlawson/c02bba75247012afb1bf)** of this code. - -The document looks exactly the same as when we put it, except... aha! What is this? There is a new field, `_rev`, that contains what looks like garbage. PouchDB gots some 'splainin' to do. - -Understanding revisions (`_rev`) ------- - -The new field, `_rev` is the *revision marker*. It is a randomly-generated ID that changes whenever a document is created or updated. - -Unlike most other databases, whenever you update a document in PouchDB or CouchDB, you must present the *entire document* along with its current *revision marker*. - -For instance, to increment Mittens' age to 4, we would do: - -```js -doc.age = 4; -doc._rev = "1-bea5fa18e06522d12026f4aee6b15ee4"; -db.put(doc); -``` - -If you fail to include the correct `_rev`, you will get the following sad error: - -```js -{ - "status": 409, - "name": "conflict", - "message": "Document update conflict" -} -``` - -`HTTP 409` is a standard HTTP error message that indicates a conflict. - -Updating documents correctly ------------ - -So to update Mittens' age, we will first need to fetch Mittens from the database, to ensure that we have the correct `_rev` before we put him back. - -```js -// fetch mittens -db.get('mittens').then(function (doc) { - // update his age - doc.age = 4; - // put him back - return db.put(doc); -}).then(function () { - // fetch mittens again - return db.get('mittens'); -}).then(function (doc) { - console.log(doc); -}); -``` - -You can see a **[live example](http://bl.ocks.org/nolanlawson/d6daa02ca3875d1222dd)** of this code. - -{% include alert_start.html variant="info" %} - -Don't worry if the structure of this code seems strange! It's using <strong>promises</strong>, which will be discussed in the next chapter. - -{% include alert_end.html %} - -Now you should see the following: - -```js -{ - "name": "Mittens", - "occupation": "kitten", - "age": 4, - "hobbies": [ - "playing with balls of yarn", - "chasing laser pointers", - "lookin' hella cute" - ], - "_id": "mittens", - "_rev": "2-3e3fd988b331193beeeea2d4221b57e7" -} -``` - -As you can see, we have successfully updated Mittens' age to 4 (they grow up so fast!), and his revision marker has also changed to `"2-3e3fd988b331193beeeea2d4221b57e7"`. If we wanted to increment his age to 5, we would need to supply this new revision marker. - -Related API documentation --------- - -* [get()](/api.html#fetch_document) -* [put()](/api.html#create_document) - -Next ----- - -Now that you understand a bit about how to create and update documents, let's take a small detour to talk about asynchronous code. \ No newline at end of file
diff --git a/docs/_guides/index.md b/docs/_guides/index.md deleted file mode 100644 index 6438651..0000000 --- a/docs/_guides/index.md +++ /dev/null
@@ -1,62 +0,0 @@ ---- -index: 1 -layout: guide -nav: Intro -title: Introduction to PouchDB -sidebar: guides_nav.html ---- - -Welcome to the PouchDB guide! Consider this your starting point for anything and everything related to the world of PouchDB and CouchDB. - -For a quicker TodoMVC-based tutorial, you can also check out the ["Getting Started" guide](/getting-started.html). - -Feel free to skip ahead using the sidebar at any time. - -What is PouchDB? ------- - -**PouchDB** is a JavaScript implementation of [CouchDB](http://couchdb.com). Its goal is to emulate the CouchDB API with near-perfect fidelity, while running in the browser or in Node.js. - -What is CouchDB? ---------- - -**CouchDB** is a NoSQL database created in 2005 by Damien Katz, and now maintained by the Apache Software Foundation. If you are a JavaScript developer, you probably use CouchDB every day, because it's the core technology that powers [npm](https://www.npmjs.org/). - -Couchbase, CouchDB, Couch-wha? ----------- - -Today there are two major database companies that -can trace their lineage back to CouchDB: [**Couchbase**](http://couchbase.com) and [**Cloudant**](http://cloudant.com). Both of them are separate products compared to CouchDB. - -However, all three of these databases share the same **CouchDB sync protocol**. This means that PouchDB can sync with either one of them, and you can always swap out one database for another. You're never locked in. - -In a sense, these databases are like competiting phone companies, and the CouchDB sync protocol is the underlying telephony infrastructure. - -CouchDB's one-two punch: HTTP and sync ----------- - -With so many SQL and NoSQL databases out there – MongoDB, PostgreSQL, MySQL, etc. – you may wonder why we chose to implement CouchDB instead of the others. - -We have two very good answers to that question: **HTTP** and **sync**. - -HTTP: the little protocol that could ------ -When working with databases, we're often accustomed to writing some kind of conversion layer between the database and our client-side applications. This means, however, that we are just translating database queries into RESTful HTTP calls, over and over. For every app we write. - -CouchDB throws this out the window by daring us to talk to the database directly, from our client-side apps. And it does so by using HTTP as its primary means of communication. No special protocol, no special drivers: just REST and HTTP. You can communicate with CouchDB entirely through your browser, `curl`, or a REST client like [Postman](https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm). - -In this way, CouchDB truly is a "database for the web." - -Sync: CouchDB's killer feature ------ - -Another unique feature of CouchDB is that it was designed from the bottom-up to enable easy synchronization between different databases. - -For example, if you are worried about latency in your client-side applications, you can simply set up one CouchDB in Europe, another in North America, and another in Asia. After enabling continuous two-way replication between these databases, your clients can simply talk to whichever one is closer. - -PouchDB takes this one step further by putting the database inside your browser. - -Next ------ - -Now that you understand the basics of the PouchDB/CouchDB universe, let's set up CouchDB! \ No newline at end of file
diff --git a/docs/_guides/queries.md b/docs/_guides/queries.md deleted file mode 100644 index c148fe3..0000000 --- a/docs/_guides/queries.md +++ /dev/null
@@ -1,207 +0,0 @@ ---- -index: 13 -layout: guide -title: Map/reduce queries -sidebar: guides_nav.html ---- - -Map/reduce queries, also known as *secondary indexes*, are one of the most powerful features in PouchDB. However, they can be quite tricky to use, so this guide is designed to dispell some of the mysteries around them. - - {% include alert_start.html variant="warning" %} - -Many developers make the mistake of using the <code>query()</code> API when the more performant <code>allDocs()</code> API, would be a better fit. -<p/> <p/> -Before you solve a problem with secondary indexes, you should ask yourself: can I solve this with the <em>primary index</em> (<code>_id</code>) instead? - -{% include alert_end.html %} - -Mappin' and reducin' -------- - -The PouchDB `query()` API (which corresponds to the `_view` API in CouchDB) has two modes: temporary queries and persistent queries. - -### Temporary queries - -**Temporary queries** are very slow, and we only recommend them for quick debugging during development. To use a temporary query, you simply pass in a `map` function: - -```js -db(function (doc) { - emit(doc.name); -}, {key: 'foo'}).then(function (result) { - // found docs with name === 'foo' -}).catch(function (err) { - // handle any errors -}); -``` - -In the above example, the `result` object will contain all documents where the `name` attribute is equal to `'foo'`. - -{% include alert_start.html variant="info" %} - -The <code>emit</code> pattern is part of the standard <a href='http://couchdb.readthedocs.org/en/latest/couchapp/views/intro.html'>CouchDB map/reduce API</a>. What the function basically says is, "for each document, emit <code>doc.name</code> as a key." - -{% include alert_end.html %} - -### Persistent queries - -**Persistent queries** are much faster, and are the intended way to use the `query()` API in your production apps. To use persistent queries, there are two steps. - -First, you create a **design document**, which describes the `map` function you would like to use: - -```js -// document that tells PouchDB/CouchDB -// to build up an index on doc.name -var myIndex = { - _id: '_design/my_index', - views: { - 'my_index': { - map: function (doc) { emit(doc.name); }.toString() - } - } -}; -// save it -pouch.put(myIndex).then(function () { - // success! -}).catch(function (err) { - // some error (maybe a 409, because it already exists?) -}); -``` - -Then you actually query it, by using the name you gave the design document when you saved it: - -```js -db.query('my_index').then(function (res) { - // got the query results -}).catch(function (err) { - // some error -}); -``` - -More about map/reduce ------ - -That was a fairly whirlwind tour of the `query()` API, so let's get into more detail about how to write your map/reduce functions. - -#### Indexes in SQL databases - -Quick refresher on how indexes work: in relational databases like MySQL and PostgreSQL, you can usually query whatever field you want: - -```sql -SELECT * FROM pokemon WHERE name = 'Pikachu'; -``` - -But if you don't want your performance to be terrible, you first add an index: - -```sql -ALTER TABLE pokemon ADD INDEX myIndex ON (name); -``` - -The job of the index is to ensure the field is stored in a B-tree within the database, so your queries run in _O(log(n))_ time instead of _O(n)_ time. - -#### Indexes in NoSQL databases - -All of the above is also true in document stores like CouchDB and MongoDB, but conceptually it's a little different. By default, documents are assumed to be schemaless blobs with one primary key (called `_id` in both Mongo and Couch), and any other keys need to be specified separately. The concepts are largely the same; it's mostly just the vocabulary that's different. - -In CouchDB, queries are called _map/reduce functions_. This is because, like most NoSQL databases, CouchDB is designed to scale well across multiple computers, and to perform efficient query operations in parallel. Basically, the idea is that you divide your query into a _map_ function and a _reduce_ function, each of which may be executed in parallel in a multi-node cluster. - -#### Map functions - -It may sound daunting at first, but in the simplest (and most common) case, you only need the _map_ function. A basic map function might look like this: - -```js -function myMapFunction(doc) { - emit(doc.name); -} -``` - -This is functionally equivalent to the SQL index given above. What it essentially says is: "for each document in the database, emit its name as a key." - -And since it's just JavaScript, you're allowed to get as fancy as you want here: - -```js -function myMapFunction(doc) { - if (doc.type === 'pokemon') { - if (doc.name === 'Pikachu') { - emit('Pika pi!'); - } else { - emit(doc.name); - } - } -} -``` - -Then you can query it: - -```js -// find pokemon with name === 'Pika pi!' -pouch.query(myMapFunction, { - key : 'Pika pi!', - include_docs : true -}).then(function (result) { - // handle result -}).catch(function (err) { - // handle errors -}); - -// find the first 5 pokemon whose name starts with 'P' -pouch.query(myMapFunction, { - startkey : 'P', - endkey : 'P\uffff', - limit : 5, - include_docs : true -}).then(function (result) { - // handle result -}).catch(function (err) { - // handle errors -}); -``` - -{% include alert_start.html variant="info"%} - -The pagination options for <code>query()</code> – i.e., <code>startkey</code>/<code>endkey</code>/<code>key</code>/<code>keys</code>/<code>skip</code>/<code>limit</code>/<code>descending</code> – are exactly the same as with <code>allDocs()</code>. For a guide to pagination, read the <a href="/guides/bulk-operations.html">Bulk operations guide</a> or <a href='http://pouchdb.com/2014/04/14/pagination-strategies-with-pouchdb.html'>Pagination strategies with PouchDB</a>. - -{% include alert_end.html %} - -#### Reduce functions - -As for _reduce_ functions, there are a few handy built-ins that do aggregate operations (`'_sum'`, `'_count'`, and `'_stats'`), and you can typically steer clear of trying to write your own: - -```js -// emit the first letter of each pokemon's name -var myMapReduceFun = { - map: function (doc) { - emit(doc.name.charAt(0)); - }, - reduce: '_count' -}; -// count the pokemon whose names start with 'P' -pouch.query(myMapReduceFun, { - key: 'P', reduce: true, group: true -}).then(function (result) { - // handle result -}).catch(function (err) { - // handle errors -}); -``` - -If you're adventurous, though, you should check out the [CouchDB documentation](http://couchdb.readthedocs.org/en/latest/couchapp/views/intro.html) or the [PouchDB documentation](http://pouchdb.com/api.html#query_database) for details on reduce functions. - -More about map/reduce -------- - -The map/reduce API is complex. Part of this problem will be resolved when the more developer-friendly [Cloudant query language](http://docs.cloudant.com/api/cloudant-query.html) is merged into CouchDB 2.0 (and eventually, PouchDB). In the meantime, there are a few tricks you can use to avoid unnecessarily complicating your codebase: - -1. Avoid the `query()` API altogether if you can. You'd be amazed how much you can do with just `allDocs()`. (In fact, under the hood, the `query()` API is simply implemented on top of `allDocs()`!) -2. If your data is highly relational, try the [relational-pouch](https://github.com/nolanlawson/relational-pouch) plugin. -1. Read the [12 tips for better code with PouchDB](/2014/06/17/12-pro-tips-for-better-code-with-pouchdb.html). - -Related API documentation --------- - -* [query()](/api.html#query_database) -* [viewCleanup()](/api.html#view_cleanup) - -Next ------ - -Now that we've learned how to map reduce, map reuse, and map recycle, let's move on to `destroy()` and `compact()`.
diff --git a/docs/_guides/replication.md b/docs/_guides/replication.md deleted file mode 100644 index 4ff8fad..0000000 --- a/docs/_guides/replication.md +++ /dev/null
@@ -1,152 +0,0 @@ ---- -index: 10 -layout: guide -title: Replication -sidebar: guides_nav.html ---- - -PouchDB is modeled after CouchDB. And CouchDB was designed with one main purpose in mind – **sync**. Jason Smith has [a great quote](http://nodeup.com/thirtyseven) about this: - -> The way I like to think about CouchDB is this: CouchDB is bad at everything, *except syncing*. And it turns out that's the most important feature you could ever ask for, for many types of software." - -When you first start using CouchDB, you may become frustrated because it doesn't operate quite like other databases. Unlike many other databases, CouchDB requires you to explicitly manage document revisions (`_rev`), which can be tedious. - -However, CouchDB was designed with sync in mind, and this is exactly what it excels at. Many of the rough edges of the API serve this larger purpose. For instance, managing your document revisions pays off in the future, when you eventually need to start dealing with conflicts. - -CouchDB sync ------- - -CouchDB sync (aka replication) has a unique design. Rather than relying on a master/slave architecture, CouchDB -supports a **multi-master** architecture. You can think of this as a system where any node can be written to or read from, and where you don't have to care which one is the "master" and which one is the "slave." In CouchDB's egalitarian world, every citizen is as worthy as another. - -When you write web applications with PouchDB, or when you write mobile apps using the Couchbase/Cloudant mobile libraries for iOS and Android, you -don't have to worry which database is the "single source of truth." They all are. According to the CAP theorem, CouchDB is an AP database, meaning that it's **P**artitioned, -every node is **A**vailable, and it's only eventually **C**onsistent. - -To illustrate, imagine a multi-node architecture with CouchDB servers spread across several continents. As long as you're willing to wait, the data will eventually flow -from Australia to Europe to North America to wherever. Users around the world running PouchDB in their browsers or the Couchbase/Cloudant mobile libraries smartphones experience the -same privileges. The data won't show up instantaneously, but depending on the Internet connection speed, it's usually close enough to real-time. - -In cases of conflict, CouchDB will choose an arbitrary winner that every node can agree upon deterministically. However, conflicts are still stored in the **revision tree** (similar to a Git history tree), which means that app developers can either surface the conflicts to the user, or just ignore them. - -In this way, CouchDB replication "just works." - -Setting up sync ------------ - -As you already know, you can create either local PouchDBs: - -```js -var localDB = new PouchDB('mylocaldb') -``` - -or remote PouchDBs: - -```js -var remoteDB = new PouchDB('http://localhost:5984/myremotedb') -``` - -This pattern comes in handy when you want to share data between the two. - -The simplest case is **unidirectional replication**, meaning you just want one database to mirror its changes to a second one. Writes to the second database, however, will not propagate back to the master database. - -To perform unidirectional replication, you simply do: - -```js -localDB.replicate.to(remoteDB).on('complete', function () { - // yay, we're done! -}).on('error', function (err) { - // boo, something went wrong! -}); -``` - -Congratulations, all changes from the `localDB` have been replicated to the `remoteDB`. - -However, what if you want **bidirectional replication**? (Kinky!) You could do: - -```js -localDB.replicate.to(remoteDB); -localDB.replicate.from(remoteDB); -``` - -However, to make things easier for your poor tired fingers, we have created a shortcut API: - -```js -localDB.sync(remoteDB); -``` - -These two code blocks above are equivalent. And the `sync` API supports all the same events as the `replicate` API: - -```js -localDB.sync(remoteDB).on('complete', function () { - // yay, we're in sync! -}).on('error', function (err) { - // boo, we hit an error! -}); -``` - -Live replication ---------- - -Live replication (or "continuous" replication) is a separate mode where changes are propagated between the two databases as the changes occur. In other words, normal replication happens once, whereas live replication happens in real time. - -To enable live replication, you simply specify `{live: true}`: - -```js -localDB.sync(remoteDB, {live: true}); -``` - -However, there is one little gotcha with live replication: what if the user goes offline? In those cases, an error will be thrown, and you'll want to restart the replication process. - -Luckily. PouchDB provides a way to do this: - -```js -localDB.sync(remoteDB, {live: true}).on('change', function (change) { - // yo, something changed! -}).on('error', function (err) { - // yo, we got an error! -}))); -``` - -When that `'error'` function is invoked, it's usually because of a network error. That means you can easily set up an infinite retry mechanism: - -```js -function retryReplication() { - localDB.sync(remoteDB, {live: true}).on('change', function (change) { - // yo, something changed! - }).on('error', function (err) { - setTimeout(retryReplication, 5000); - }))); -} -``` - -A slightly more sophisicated technique is to do an [exponential backoff](https://en.wikipedia.org/wiki/Exponential_backoff). This will try to reconnect less and less frequently, until the user goes back online, at which point it resets. - -```js -var timeout = 5000; -var backoff = 2; -function retryReplication() { - localDB.sync.to(remoteDB, {live: true}).on('change', function (change) { - // yo, something changed! - timeout = 5000; // reset - }).on('error', function (err) { - setTimeout(function () { - timeout *= backoff; - retryReplication(); - }, timeout); - }))); -} -``` - -This is ideal for scenarios where the user may be flitting in and out of connectivity, such as on mobile devices. - -Related API documentation --------- - -* [replication()](/api.html#replication) -* [sync()](/api.html#sync) - -Next -------- - -Now that we have a grasp on replication, let's talk about an unpleasant but unavoidable fact – conflicts. \ No newline at end of file
diff --git a/docs/_guides/setup-couchdb.md b/docs/_guides/setup-couchdb.md deleted file mode 100644 index a893ced..0000000 --- a/docs/_guides/setup-couchdb.md +++ /dev/null
@@ -1,94 +0,0 @@ ---- -index: 2 -layout: guide -title: Setting up CouchDB -sidebar: guides_nav.html ---- - -CouchDB: PouchDB's big brother --------- - -One of the main benefits of learning PouchDB is that it's exactly the same as CouchDB. In fact, PouchDB is a shameless plagiarist: all of the API methods are the same, with only slight modifications to make it more JavaScript-y. - -For instance, in CouchDB you would fetch all documents using: - - /db/_all_docs?include_docs=true - -In PouchDB this becomes: - -```js -db.allDocs({include_docs: true}) -``` - -The APIs are the same, and the semantics are the same. - -In the following examples, we will set up CouchDB and talk to it using a tool you're already familiar with: your browser. - -Installing CouchDB ----------- - -If you are on a Debian flavor of Linux (Ubuntu, Mint, etc.), you can install CouchDB with: - -``` -$ sudo apt-get install couchdb -``` - -On a Mac you can do: - -``` -$ brew install couchdb -``` - -On Windows, you should install from [the CouchDB web site](https://couchdb.apache.org/#download). - -#### A CouchDB alternative: PouchDB Server - -If you have trouble installing CouchDB, you can also install PouchDB Server, which is a drop-in replacement for CouchDB that uses PouchDB under the hood: - -``` -$ npm install -g pouchdb-server -$ pouchdb-server --port 5984 -``` - -PouchDB Server is currently experimental, and we do not recommend it for production environments. - -Verify your installation ---------- - -Once CouchDB is installed, it should be running at `localhost:5984`. To verify, you can open up your terminal and type - -``` -$ curl localhost:5984 -``` - -You should see something like: - -```js -{"couchdb":"Welcome","version":"1.5.1",...} -``` - -Next, open up [http://localhost:5984/_utils/fauxton/](http://localhost:5984/_utils/fauxton/) in your browser. (Or [http://localhost:5984/_utils/](http://localhost:5984/_utils/) if you installed PouchDB Server.) - -If you see a screen like the following, then you are ready to rock and roll with CouchDB: - -<img src="/static/img/fauxton.png" alt="Fauxton interface" style="width:100%;"/> - -Set up CORS ------ - -[CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) is a web technology that allows web sites to use resources from another domain. You will want to enable this in your CouchDB before continuing, because otherwise PouchDB will not work unless it's served from exactly the same domain as CouchDB. - -Enabling CORS is easy. Just install this handy script: - - $ npm install -g add-cors-to-couchdb - -And run it: - - $ add-cors-to-couchdb - -If you installed PouchDB Server, CORS is enabled by default, and this step is not necessary. - -Next -------- - -Now that you have CouchDB installed, let's install PouchDB. \ No newline at end of file
diff --git a/docs/_guides/setup-pouchdb.md b/docs/_guides/setup-pouchdb.md deleted file mode 100644 index ae21fc3..0000000 --- a/docs/_guides/setup-pouchdb.md +++ /dev/null
@@ -1,77 +0,0 @@ ---- -index: 3 -layout: guide -title: Setting up PouchDB -sidebar: guides_nav.html ---- - - -Installing PouchDB is easy. There are a few different ways to do it: - -Direct download ------- - -Download the latest **pouchdb-{{site.version}}.min.js** from the big green button above. Then in your `index.html`: - -```html -<script src="pouchdb-{{site.version}}.min.js"></script> -``` - -Bower -------- - -Run this on the command line: - -``` -$ bower install pouchdb -``` - -Then in your `index.html`: - -```html -<script src="bower_components/pouchdb/dist/pouchdb.min.js"></script> -``` - -npm ------- - -Run this on the command line: - -``` -$ npm install pouchdb -``` - -Then in your `index.html`: - -```html -<script src="node_modules/pouchdb/dist/pouchdb.min.js"></script> -``` - -jsdelivr CDN ------- - -Add this to your `index.html`: - -```html -<script src="//cdn.jsdelivr.net/pouchdb/{{site.version}}/pouchdb.min.js"></script> -``` - -Node.js -------- - -Run this on the command line: - -``` -$ npm install pouchdb -``` - -Then in your JavaScript: - -```js -var PouchDB = require('pouchdb'); -``` - -Next -------- - -Now that you have PouchDB installed, let's start working with databases. \ No newline at end of file
diff --git a/docs/_guides/updating-deleting.md b/docs/_guides/updating-deleting.md deleted file mode 100644 index ae92203..0000000 --- a/docs/_guides/updating-deleting.md +++ /dev/null
@@ -1,150 +0,0 @@ ---- -index: 7 -layout: guide -nav: Updating/deleting documents -title: Updating and deleting documents -sidebar: guides_nav.html ---- - -As we saw in the past two chapters, working with PouchDB documents can be tricky, because you have to manage the revision identifier `_rev`. - -Now that we understand promises, though, there are few techniques we can use to make our code more elegant and readable. - -Creating a default document ------- - -Often in our code, we'll want to `get()` a document, and if it doesn't exist, we want to create some default. - -For instance, let's say we have a configuration object. We want to provide some reasonable defaults for our config: - -```js -{ - _id: 'config', - background: 'blue', - foreground: 'white', - sparkly: 'false' -} -``` - -This is a pretty good default setting! So let's write the code to set it as our default. - -Thankfully, promises makes this rather easy: - -```js -db.get('config').catch(function (err) { - if (err.status === 404) { // not found! - return { - _id: 'config', - background: 'blue', - foreground: 'white', - sparkly: 'false' - }; - } else { // hm, some other error - throw err; - } -}).then(function (configDoc) { - // sweet, here is our configDoc -}).catch(function (err) { - // handle any errors -}); -``` - -This code is doing the following: - -* Try to `get()` a doc with `_id` equal to `'config'` -* If it doesn't find it, return the default doc -* Otherwise, you'll just get back the existing document - -You can see **[a live example](http://bl.ocks.org/nolanlawson/0a01d466b2d331cf7e25)** of this code. - -Why must we dance this dance? --------- - -A common question from new PouchDB/CouchDB users is: why do we have to deal with `_rev` at all? Why can't I just `put()` the document without providing a `_rev`? - -The answer is: because this is what enables sync to work so well. PouchDB asks for a little pain up-front with managing document revisions, so that later on down the line, syncing is effortless. - -In fact, you are probably already familiar with a system that forces you to go through a similar dance. This system is called [Git](http://www.git-scm.com/). - -PouchDB and CouchDB's document revision structure is very similar to Git's. In fact, each document's revision history is stored as a tree (exactly like Git), which allows you to handle conflicts in case any two databases get out of sync. - -``` -rev 3-a rev 3-b - \___/ - | - rev 2 - | - rev 1 -``` - -Conflicts will be discussed later in this guide. For now, you can think of revisions as being a single lineage: - -``` - rev 4 - | - rev 3 - | - rev 2 - | - rev 1 -``` - -Deleting documents -------- - -Deleting documents is actually very simple. The document is not really deleted; it just gets a `_deleted` attribute added to it. - -That is, the database saves a tombstone at the end of the revision tree. - -``` -{_id: 'foo', _rev: '4-z', _deleted: true} - | -{_id: 'foo', _rev: '3-y'} - | -{_id: 'foo', _rev: '2-x'} - | -{_id: 'foo', _rev: '1-w'} -``` - -There are three ways of deleting a document, which are all equivalent: - -1) You can call `db.remove(doc)`: - -```js -db.get('mydoc').then(function (doc) { - return db.remove(doc); -}); -``` - -2) You can call `db.remove(doc._id, doc._rev)`: - -```js -db.get('mydoc').then(function (doc) { - return db.remove(doc._id, doc._rev); -}); -``` - -3) You can call `db.put(doc)` with `_deleted` set to `true`: - -```js -db.get('mydoc').then(function (doc) { - doc._deleted = true; - return db.put(doc); -}); -``` - -Of course, you will want to add `catch()` to the end of all these, unless you like to live dangerously. - -You can see **[a live example](http://bl.ocks.org/nolanlawson/b2049ad69308e92f15bc)** of this code. - -Related API documentation --------- - -* [get()](/api.html#fetch_document) -* [put()](/api.html#create_document) -* [remove()](/api.html#delete_document) - -Next --------- - -Now that we understand how to update and delete documents, let's do it in bulk. \ No newline at end of file
diff --git a/docs/_includes/alert_end.html b/docs/_includes/alert_end.html deleted file mode 100644 index 50b9e11..0000000 --- a/docs/_includes/alert_end.html +++ /dev/null
@@ -1,2 +0,0 @@ -</div> -</div> \ No newline at end of file
diff --git a/docs/_includes/alert_start.html b/docs/_includes/alert_start.html deleted file mode 100644 index 458faa5..0000000 --- a/docs/_includes/alert_start.html +++ /dev/null
@@ -1,11 +0,0 @@ -{% if include.variant == "success" %} -<div class="alert alert-success"> -{% elsif include.variant == "warning" %} -<div class="alert alert-warning"> -{% elsif include.variant == "danger" %} -<div class="alert alert-danger"> -{% else %} -<div class="alert alert-info"> -{% endif %} - -<div class="alert-text">
diff --git a/docs/_includes/anchor.html b/docs/_includes/anchor.html deleted file mode 100644 index c9e7643..0000000 --- a/docs/_includes/anchor.html +++ /dev/null
@@ -1,7 +0,0 @@ -{% if include.class %} - {% assign class = include.class %} -{% else %} - {% assign class = 'h2' %} -{% endif %} -<div id='{{ include.hash }}'></div> -<a class='{{ class }} anchor' href='#{{ include.hash }}' name='{{ include.hash }}'>{{ include.title }}</a>
diff --git a/docs/_includes/api.html b/docs/_includes/api.html deleted file mode 100644 index fb1722d..0000000 --- a/docs/_includes/api.html +++ /dev/null
@@ -1,22 +0,0 @@ -<li><a href="#create_database">Create database</a></li> -<li><a href="#delete_database">Delete database</a></li> -<li><a href="#create_document">Create/update doc</a></li> -<li><a href="#fetch_document">Fetch doc</a></li> -<li><a href="#delete_document">Delete doc</a></li> -<li><a href="#batch_create">Batch create</a></li> -<li><a href="#batch_fetch">Batch fetch</a></li> -<li><a href="#changes">Changes</a></li> -<li><a href="#replication">Replication</a></li> -<li><a href="#sync">Sync</a></li> -<li><a href="#save_attachment">Save attachment</a></li> -<li><a href="#get_attachment">Get attachment</a></li> -<li><a href="#delete_attachment">Delete attachment</a></li> -<li><a href="#query_database">Query database</a></li> -<li><a href="#view_cleanup">View cleanup</a></li> -<li><a href="#database_information">Database info</a></li> -<li><a href="#compaction">Compaction</a></li> -<li><a href="#revisions_diff">Revision diff</a></li> -<li><a href="#events">Events</a></li> -<li><a href="#defaults">Default settings</a></li> -<li><a href="#plugins">Plugins</a></li> -<li><a href="#debug_mode">Debug mode</a></li>
diff --git a/docs/_includes/guides_nav.html b/docs/_includes/guides_nav.html deleted file mode 100644 index d37e091..0000000 --- a/docs/_includes/guides_nav.html +++ /dev/null
@@ -1,8 +0,0 @@ -{% assign guides = (site.guides | sort: 'index') %} -{% for guide in guides %} - {% assign title = guide.title %} - {% if guide.nav %} - {% assign title = guide.nav %} - {% endif %} - {% include nav_item.html path=guide.url text=title %} -{% endfor %}
diff --git a/docs/_includes/iframe.html b/docs/_includes/iframe.html deleted file mode 100644 index 3afca77..0000000 --- a/docs/_includes/iframe.html +++ /dev/null
@@ -1 +0,0 @@ -<div class="iframe-responsive"><iframe src="{{ include.src }}" allowfullscreen></iframe></div>
diff --git a/docs/_includes/nav.html b/docs/_includes/nav.html deleted file mode 100644 index 88138a9..0000000 --- a/docs/_includes/nav.html +++ /dev/null
@@ -1,7 +0,0 @@ -{% include nav_item.html path="/learn.html" text="About PouchDB" %} -{% include nav_item.html path="/getting-started.html" text="Get Started Guide" %} -{% include nav_item.html path="/api.html" text="API" %} -{% include nav_item.html path="/adapters.html" text="Adapters" %} -{% include nav_item.html path="/external.html" text="Plugins" %} -{% include nav_item.html path="/faq.html" text="FAQ" %} -{% include nav_item.html path="/errors.html" text="Common Errors" %}
diff --git a/docs/_includes/nav_item.html b/docs/_includes/nav_item.html deleted file mode 100644 index c857389..0000000 --- a/docs/_includes/nav_item.html +++ /dev/null
@@ -1,3 +0,0 @@ -<li {% if page.url == include.path %} class="active" {% endif %}> - <a href="{{ site.baseurl }}{{ include.path | replace:'index.html','' }}">{{ include.text }}</a> -</li>
diff --git a/docs/_includes/post_details.html b/docs/_includes/post_details.html deleted file mode 100644 index c05ce66..0000000 --- a/docs/_includes/post_details.html +++ /dev/null
@@ -1,40 +0,0 @@ -{% unless post %} - {% assign post = page %} -{% endunless %} - -{% assign post_author = post.author %} -{% assign post_gravatar = 'http://www.fillmurray.com/82/82' %} -{% assign modified_date = '' %} - -{% for author in site.data.authors %} - {% if author.name == post.author %} - {% if author.twitter %} - {% capture post_author %}<a href="https://twitter.com/{{author.twitter}}">{{ post.author }}</a>{% endcapture %} - {% endif %} - {% if author.gravatar %} - {% capture post_gravatar %}https://gravatar.com/avatar/{{ author.gravatar }}{% endcapture %} - {% endif %} - {% endif %} -{% endfor %} - -{% if post.modified_date %} - {% capture modified_date %}<strong>Updated:</strong> {{ post.modified_date | date_to_long_string }}<br>{% endcapture %} -{% endif %} - -<div class="post"> - <div class="media"> - <a class="pull-left" href="#"> - <img class="media-object img-circle img-responsive" src='{{ post_gravatar }}' alt='{{ post.author }}'> - </a> - <div class="media-body"> - <p> - <strong>By:</strong> {{ post_author }}<br> - <strong>Published:</strong> {{ post.date | date_to_long_string }}<br> - {% if page.url == "/blog/index.html" or page.url contains "/blog/page" or page.url == "/index.html" %} - {{ post.excerpt | strip_html | truncatewords: 30, '' }} - <a href='{{ site.baseurl }}{{ post.url }}'>[...]</a> - {% endif %} - </p> - </div> - </div> -</div>
diff --git a/docs/_includes/social.html b/docs/_includes/social.html deleted file mode 100644 index 4025e6e..0000000 --- a/docs/_includes/social.html +++ /dev/null
@@ -1,7 +0,0 @@ -{% for author in site.data.authors %} - {% if author.name == page.author %} - {% capture author_twitter %}@{{ author.twitter }}{% endcapture %} - {% endif %} -{% endfor %} -<a class='btn btn-github' href='https://github.com/daleharvey/pouchdb/tree/master/docs/{{ page.path }}'>View on GitHub</a> -<a class='btn btn-twitter' href="https://twitter.com/intent/tweet?text={{ page.title }}: {{ site.host }}{{ site.baseurl }}{{ page.url }} -- @pouchdb {{ author_twitter }}">Tweet this article</a> \ No newline at end of file
diff --git a/docs/_layouts/2ColLeft.html b/docs/_layouts/2ColLeft.html deleted file mode 100644 index 7805d18..0000000 --- a/docs/_layouts/2ColLeft.html +++ /dev/null
@@ -1,24 +0,0 @@ ---- -layout: default ---- - -<article> - <div class="container"> - <div class="row"> - <div id="sidebar" class="col-sm-3"> - <div data-spy="affix" data-offset-top="214" data-offset-bottom="450"> - <ul class="nav nav-silent nav-sidebar"> - {% include {{page.sidebar}} %} - </ul> - </div> - </div> - - <div class="col-sm-9"> - {{content}} - <div> - - </div> - - </div> - -</article>
diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html deleted file mode 100644 index 9658625..0000000 --- a/docs/_layouts/default.html +++ /dev/null
@@ -1,174 +0,0 @@ -<!DOCTYPE html> -<html lang="en" manifest="/manifest.appcache"> - - <head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>{{ page.title }}</title> - <link rel="stylesheet" href="{{ site.baseurl }}/static/css/pouchdb.css" /> - <script type="text/javascript"> - var _gaq = _gaq || []; - _gaq.push(['_setAccount', 'UA-42479701-1']); - _gaq.push(['_trackPageview']); - - (function() { - var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; - ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; - var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); - })(); - </script> - <link href='http://fonts.googleapis.com/css?family=Lato:400,700|Open+Sans:400,700' rel='stylesheet' type='text/css'> - <link rel="icon" href="/static/favicon.ico" type="image/x-icon"/> - </head> - - <body data-spy="scroll" data-target="#sidebar"> - - <header> - - <a href="https://github.com/pouchdb/pouchdb" target="_blank"> - <div class="ribbon">GitHub</div> - </a> - - <div class="container"> - - <a class="logo" href="{{ site.baseurl }}/"> - <div class="logo-img"></div> - <span class='logo-type'>PouchDB</span> - </a> - - <ul class='nav nav-header nav-pills'> - <li> - <a class='btn btn-link btn-lg' href="{{ site.baseurl }}/blog/">Blog</a> - </li> - <li> - <a class='btn btn-link btn-lg' href="{{ site.baseurl }}/guides/">Guides</a> - </li> - <li> - <a class='btn btn-link btn-lg' href="{{ site.baseurl }}/api.html">API</a> - </li> - <li> - <a class='btn btn-link btn-lg' href="{{ site.baseurl }}/learn.html">Learn</a> - </li> - <li> - <a - class='btn btn-primary btn-lg' - href="https://github.com/daleharvey/pouchdb/releases/download/{{ site.version }}/pouchdb-{{ site.version }}.min.js" - > - Download <strong>v{{ site.version }}</strong> - </a> - </li> - </ul> - - </div> - - </header> - {% if page.url != "/index.html" %} - <div class="page-head"> - - <div class="container"> - - <h1>{{ page.title }}</h1> - {% if page.sub_title %} - <h4>{{ page.sub_title}}</h4> - {% endif %} - - </div> - - </div> - {% endif %} - - - {{ content }} - - <div class="icons"> - - <div class="container"> - - <div class="row"> - - <div class='col-xs-4 col-md-offset-0 col-md-2'> - <a href='https://twitter.com/pouchdb' target='_blank'> - <div class="icon icon-twitter"></div> - </a> - </div> - - <div class='col-xs-4 col-md-2'> - <a href='https://github.com/rvagg/node-levelup' target='_blank'> - <div class="icon icon-leveldb"></div> - </a> - </div> - - <div class='col-xs-4 col-md-2'> - <a href='https://github.com/pouchdb/pouchdb' target='_blank'> - <div class="icon icon-github"></div> - </a> - </div> - - <div class='col-xs-4 col-md-offset-0 col-md-2'> - <a href='https://travis-ci.org/pouchdb/pouchdb' target='_blank'> - <div class="icon icon-travis"></div> - </a> - </div> - - <div class='col-xs-4 col-md-2'> - <a href='http://couchdb.apache.org/' target='_blank'> - <div class="icon icon-couchdb"></div> - </a> - </div> - - <div class='col-xs-4 col-md-2'> - <a href='https://saucelabs.com' target='_blank'> - <div class="icon icon-saucelabs"></div> - </a> - </div> - - </div> - - </div> - - </div> - - <footer class="footer"> - - <div class="container"> - - <div class="row"> - - <div class='col-sm-3'> - <h3 class="nav-head">Learn</h3> - <ul class='nav nav-silent'> - <li><a href="{{ site.baseurl }}/getting-started.html">Getting Started</a></li> - <li><a href="{{ site.baseurl }}/api.html">API Guide</a></li> - <li><a href="https://github.com/daleharvey/pouchdb/wiki">Wiki</a></li> - </ul> - </div> - - <div class='col-sm-3'> - <h3 class="nav-head">Discuss</h3> - <ul class='nav nav-silent'> - <li><a href="https://groups.google.com/forum/#!forum/pouchdb">Mailing List</a></li> - <li><a href="irc://freenode.net/#pouchdb">IRC</a></li> - <li><a href="http://twitter.com/pouchdb">Twitter</a></li> - <li><a href="http://stackoverflow.com/questions/tagged/pouchdb">StackOverflow</a></li> - </ul> - </div> - - <div class='col-sm-3'> - <h3 class="nav-head">Contribute</h3> - <ul class='nav nav-silent'> - <li><a href="https://github.com/daleharvey/pouchdb/blob/master/CONTRIBUTING.md">Contributing</a></li> - <li><a href="https://github.com/daleharvey/pouchdb">Source</a></li> - <li><a href="https://github.com/daleharvey/pouchdb/issues">Issues</a></li> - <li><a href="https://github.com/daleharvey/pouchdb/blob/master/LICENSE">Apache License</a></li> - </ul> - </div> - - </div> - - </div> - - </footer> - <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script> - <script type="text/javascript" src="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script> - </body> -</html>
diff --git a/docs/_layouts/guide.html b/docs/_layouts/guide.html deleted file mode 100644 index bee6fb2..0000000 --- a/docs/_layouts/guide.html +++ /dev/null
@@ -1,25 +0,0 @@ ---- -layout: 2ColLeft ---- -{{ content }} - -{% assign guides = (site.guides | sort: 'index') %} -{% for guide in guides %} - {% if page.title == guide.title %} - {% assign prev = guide.index | minus: 2 %} - {% assign next = guide.index %} - - <ul class="pager"> - {% unless prev == -1 %} - <li class="previous"> - <a href="{{ guides[prev].url }}">← {{ guides[prev].title }}</a> - </li> - {% endunless %} - {% if guides[next] %} - <li class="next"> - <a href="{{ guides[next].url }}">{{ guides[next].title }} →</a> - </li> - {% endif %} - </ul> - {% endif %} -{% endfor %}
diff --git a/docs/_layouts/post.html b/docs/_layouts/post.html deleted file mode 100644 index b7e8bae..0000000 --- a/docs/_layouts/post.html +++ /dev/null
@@ -1,12 +0,0 @@ ---- -layout: default ---- -<article class='container'> - <div class='row'> - <div class='col-md-offset-1 col-md-10'> - {% include post_details.html %} - - {{ content }} - </div> - </div> -</article>
diff --git a/docs/_posts/2014-04-01-pouchdb-2.1.0.md b/docs/_posts/2014-04-01-pouchdb-2.1.0.md deleted file mode 100644 index 0dfccba..0000000 --- a/docs/_posts/2014-04-01-pouchdb-2.1.0.md +++ /dev/null
@@ -1,31 +0,0 @@ ---- -layout: post - -title: PouchDB 2.1.0 - -author: Dale Harvey - ---- - -[PouchDB 2.1.0](https://github.com/daleharvey/pouchdb/releases/tag/2.1.0) is now released! Please [file issues](https://github.com/daleharvey/pouchdb/issues) or [tell us what you think](https://github.com/daleharvey/pouchdb/blob/master/CONTRIBUTING.md#get-in-touch). We would also like to give a huge thanks to our [new and existing contributors](https://github.com/daleharvey/pouchdb/graphs/contributors?from=2014-03-01&to=2014-04-01). - -{% include alert_start.html variant="warning"%} -This release contains a database migration, which means that once you upgrade you will no longer be able to use previous versions of PouchDB on the same databases. -{% include alert_end.html %} - -### Major Changes: - - * Website redesign and a new blog ([#1539](http://github.com/daleharvey/pouchdb/issues/1539), [#893](https://github.com/daleharvey/pouchdb/issues/893)) - * Support optional LevelDOWN builds ([#44](http://github.com/daleharvey/pouchdb/issues/44)) - * Replication performance improvements ([#1732](http://github.com/daleharvey/pouchdb/issues/1732)) - * Performance improvements for skip / limit ([#1649](http://github.com/daleharvey/pouchdb/issues/1649)) - * Cache WebSQL databases, fully passing tests in Safari ([#1068](http://github.com/daleharvey/pouchdb/issues/1068)) - * Fix support for unicode in doc ids (WebSQL) ([#1733](http://github.com/daleharvey/pouchdb/issues/1733)) - * Fix for localStorage detection in Chrome Apps ([#1727](http://github.com/daleharvey/pouchdb/issues/1727)) - * Allow overriding of http functions ([#1602](http://github.com/daleharvey/pouchdb/issues/1602)) - * Improve error reporting from replicator ([#1714](http://github.com/daleharvey/pouchdb/issues/1714)) - * Switch to readAsArrayBuffer for IE binary support ([#1667](http://github.com/daleharvey/pouchdb/issues/1667)) - * Add `npm run shell` for quick shell experimenting ([#1610](http://github.com/daleharvey/pouchdb/issues/1610)) - * Ensure we dont lose data when browsers upgrade from WebSQL to IDB ([#1289](http://github.com/daleharvey/pouchdb/issues/1289)) - -###### [Complete list of changes](https://github.com/daleharvey/pouchdb/compare/2.0.1...2.1.0)
diff --git a/docs/_posts/2014-04-01-welcome-to-the-pouchdb-blog.md b/docs/_posts/2014-04-01-welcome-to-the-pouchdb-blog.md deleted file mode 100644 index b3df50b..0000000 --- a/docs/_posts/2014-04-01-welcome-to-the-pouchdb-blog.md +++ /dev/null
@@ -1,18 +0,0 @@ ---- -layout: post - -title: Welcome to the PouchDB blog - -author: Dale Harvey - ---- - -Hello World! Welcome to the newly formed PouchDB blog. PouchDB has been an active community for over 2 years now, with almost everything being run via IRC and Github. As the project grows, we wanted a way to communicate with users about the current state of the PouchDB world. - -We will obviously be posting updates and releases notes for PouchDB releases, but as well as that, we will also be blogging about related projects and technologies within the PouchDB world, such as Service Workers, CouchDB, etc. - -As with the PouchDB source, we would love to invite everyone to contribute. We have [documented the instructions](https://github.com/daleharvey/pouchdb/blob/master/CONTRIBUTING.md#writing-a-pouchdb-blog-post), so please get involved. - -Over the last 4 years PouchDB has had 89 [awesome contributors](https://github.com/daleharvey/pouchdb/graphs/contributors). I would like to give a shout-out to the people who worked together to get this site up and running in such a short time: [nickcolley](https://twitter.com/NickColley), [misosoup](https://twitter.com/misosoup), [zaccolley](https://twitter.com/zaccolley), [nolanlawson](https://twitter.com/nolanlawson) and [virgie](https://github.com/virgie) in particular. - -Happy Pouching.
diff --git a/docs/_posts/2014-04-14-pagination-strategies-with-pouchdb.md b/docs/_posts/2014-04-14-pagination-strategies-with-pouchdb.md deleted file mode 100644 index ae20de0..0000000 --- a/docs/_posts/2014-04-14-pagination-strategies-with-pouchdb.md +++ /dev/null
@@ -1,426 +0,0 @@ ---- -layout: post - -title: Pagination strategies with PouchDB - -excerpt: PouchDB, like CouchDB, was designed to store large amounts of data. However, once you're dealing with hundreds, thousands, or even millions of documents in a single database… - -author: Nolan Lawson - ---- - -PouchDB, like CouchDB, was designed to store large amounts of data. However, once you're dealing with hundreds, thousands, or even millions of documents in a single database, proper pagination becomes crucial if you want to offer anything manageable to your users. Nobody likes scrolling through a mile-high web page to try to find what they want. - -## A basic example - -Let's pretend we're storing 20 documents in PouchDB: - -```javascript -var pouch = new PouchDB('numbers'); -var docs = [ - {_id : 'doc01', name : 'uno'}, {_id : 'doc02', name : 'dos'}, - {_id : 'doc03', name : 'tres'}, {_id : 'doc04', name : 'cuatro'}, - {_id : 'doc05', name : 'cinco'}, {_id : 'doc06', name : 'seis'}, - {_id : 'doc07', name : 'siete'}, {_id : 'doc08', name : 'ocho'}, - {_id : 'doc09', name : 'nueve'}, {_id : 'doc10', name : 'diez'}, - {_id : 'doc11', name : 'once'}, {_id : 'doc12', name : 'doce'}, - {_id : 'doc13', name : 'trece'}, {_id : 'doc14', name : 'catorce'}, - {_id : 'doc15', name : 'quince'}, {_id : 'doc16', name : 'dieciseis'}, - {_id : 'doc17', name : 'diecisiete'}, {_id : 'doc18', name : 'dieciocho'}, - {_id : 'doc19', name : 'diecinueve'}, {_id : 'doc20', name : 'veinte'}, -]; -pouch.bulkDocs({docs : docs}, function (err, response) { - // handle err or response -}); -``` - -Now, the simplest kind of Pouch query, called [`allDocs()`](http://pouchdb.com/api.html#batch_fetch), doesn't do any pagination by default. As the name implies, it just returns all the docs: - -```javascript -pouch.allDocs(function (err, response) { - // handle err or response -}); -``` - -Here's the response: - -```javascript -{ - "total_rows": 20, - "offset": 0, - "rows": [ - { - "id": "doc01", - "key": "doc01", - "value": { "rev": "1-8e483b9e178a8e58e3f1a4690b3d6e9a"} - }, - { - "id": "doc02", - "key": "doc02", - "value": {"rev": "1-f6fee051188e84ac3d22c645c819a5d2"} - }, - /* etc. */ - { - "id": "doc20", - "key": "doc20", - "value": {"rev": "1-f6fee051188e84ac3d22c645c819a5d2"} - } - ] -} -``` - -{% include alert_start.html variant="warning"%} - -<strong>Potential gotcha!</strong> Somewhat unintuitively, <code>allDocs()</code> doesn't return the full document data by default. It only returns the document <code>id</code> and revision hash <code>rev</code>, unless you pass in the option <code>{include_docs : true}</code>. - -{% include alert_end.html %} - -All 20 documents are returned, no pagination involved. We can visualize it graphically like this: - -``` -First doc returned Last doc returned - ↓ ↓ -[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] -``` - -Now obviously, returning all 20 docs is nice, but we're here to paginate! So let's see what we can pass to the `allDocs()` method to slice and dice our data. - -## Learning the pagination lingo - -`allDocs()` is a pretty flexible API, and we have a lot of parameters to choose from. Since PouchDB is modeled after CouchDB, we can learn about these parameters by directly consulting [the Couch docs][couch-query-api], but here's a basic rundown: - -* `startkey`: the `_id` of the first doc we'd like to fetch -* `endkey`: the `_id` of the last doc we'd like to fetch -* `limit`: maximum number of docs to return -* `skip`: number of docs to skip -* `descending`: `true` if we want reverse ordering - -These parameters are simply passed as the first argument to `allDocs()`, e.g. - -```javascript -pouch.allDocs({startkey : 'doc05', endkey : 'doc06'}, function (err, response) { - // handle err or response -}); -``` - -Here's the response: - -```javascript -{ - "total_rows": 20, - "offset": 0, - "rows": [ - { - "id": "doc05", - "key": "doc05", - "value": {"rev": "1-15397f81e784ee1a05d3ab6da07afe8d"} - }, - { - "id": "doc06", - "key": "doc06", - "value": {"rev": "1-5b35abcf7cc48e2cea63e64281f271ca"} - } - ] -} -``` - -Now, let's go through each of these parameters in detail. - -### startkey and endkey - -`startkey` simply tells PouchDB where you'd like to start in the stream. For instance, the options `{startkey : 'doc5'}` would return these docs: - -``` - First doc returned Last doc returned - ↓ ↓ -[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] -``` - -Similarly, `endkey` tells PouchDB where to stop reading. `{endkey : 'doc15'}` would give us: - -``` -First doc returned Last doc returned - ↓ ↓ -[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] -``` - -These two options can be used together! `{startkey : 'doc5', endkey: 'doc15'}` gives us: - -``` - First doc returned Last doc returned - ↓ ↓ -[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] -``` - -Notice that both `startkey` and `endkey` are *inclusive* — i.e., the matching value itself is included in the results. - -However, the value doesn't actually need to be present. So for example, if you have the documents ```['A', 'B', 'X', 'Y']```, calling `{startkey : 'C', endkey : 'Z'}` would return `['X', 'Y']`. - -### skip and limit - -`skip` tells PouchDB how many documents to skip from its normal starting point. E.g. `{skip : 5}` gives us: - -``` - First doc returned Last doc returned - ↓ ↓ -[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] -``` - -Whereas `limit` does the opposite: it cuts off documents from the end. `{limit : 15}` only gives us the first 15 docs: - -``` -First doc returned Last doc returned - ↓ ↓ -[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] -``` - -When `skip` and `limit` are used together, `limit` applies after `skip`. So e.g. `{skip : 5, limit : 10}` would slice your documents like this: - -``` - First doc returned Last doc returned - ↓ ↓ -[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] -``` - - -### Skipping into a trap - -If you come from a SQL background, you might recognize `skip` and `limit` as our old friends from SQL: `OFFSET` and `LIMIT`. You might also imagine that these parameters are the only ones you need for proper pagination. But this is a trap! - -#### Dumb method (do not use!) - -```javascript -var pageSize = 5; -var offset = 0; -function fetchNextPage() { - pouch.allDocs({limit : pageSize, skip : offset}, function (err, response) { - offset += pageSize; - // handle err or response - }); -} -``` - -This method is intuitive, but once `skip` grows to a large number, your performance will start to degrade pretty drastically. That's because those documents must literally be *skipped* over with each query, and the database will still read into memory every document that it's skipping. This can be really bad for performance, especially on mobile devices with constrained memory. - -Just repeat to yourself: `skip` really means "skip"! - -#### Smart method (please use!) - -```javascript -var options = {limit : 5}; -function fetchNextPage() { - pouch.allDocs(options, function (err, response) { - if (response && response.rows.length > 0) { - options.startkey = response.rows[response.rows.length - 1]; - options.skip = 1; - } - // handle err or response - }); -} -``` - -This method takes a bit more time to grok, but what it's essentially doing is leveraging `startkey`, instead of relying on the performance-killer `skip`. - -In our initial query, we simply tell PouchDB to give us the first 5 documents (or 10, or whatever your page size is). In our subsequent queries, we tell it to start with the last doc from the previous page, and to `skip` that one doc. - -Of course, you could also fetch `pageSize + 1` docs each time, and simply omit the last document when you display the results to the user. The choice is yours, but either method is preferable to using `skip` and `limit` alone. - -{% include alert_start.html variant="info"%} - -<strong>Aside</strong>: To be fair, WebSQL and CouchDB (since <a href='https://issues.apache -.org/jira/browse/COUCHDB-977'>version 1.1.1</a>) do not -suffer from this problem, due to their ability to efficiently count SQLite rows/B-tree offsets. -However, since IndexedDB and LevelDB (and other backends modeled on <a href='https://github -.com/rvagg/node-leveldown/'>LevelDOWN</a>) are -traditional key-value stores, they don't have a good way to count offsets. Also, some <a href='http://danielwertheim.se/2014/04/01/couchdb-pagination-is-skip-and-limit-enough/ -'>experimental data</a> suggests that CouchDB 1.5 is still faster with the <code>startkey</code> pattern. So you're better off just using <code>startkey</code> everywhere. - -{% include alert_end.html %} - -## Paginating in backwards land - -When `descending` is set to `true`, the normal document order is reversed. Simply passing `{descending : true}` would give us: - -``` -First doc returned Last doc returned - ↓ ↓ -[20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1] -``` - -Additionally, all the other parameters suddenly work backwards from their normal behavior! For instance, if we want to fetch the documents from `'doc01'` to `'doc10'`, we'd normally do: - -```javascript -pouch.allDocs({startkey : 'doc01', endkey : 'doc10'}, function (err, response) { - // handle err or response -}); -``` - -This would give us 10 results, as expected: - -``` -First doc returned Last doc returned - ↓ ↓ -[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] -``` - -If we set `descending` to `true`, though, we're in backwards land! So that same query will give us zero results: - -``` - Last doc??? First doc??? - ↓ ↓ -[20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1] -``` - -Here's the actual JavaScript `response` object: - -```javascript -{ - "total_rows": 20, - "offset": 0, - "rows": [] -} -``` - -Whenever `descending` is set to `true`, we need to switch the `startkey` and `endkey` to get the results we want: - -```javascript -pouch.allDocs({startkey : 'doc10', endkey : 'doc01', descending : true}, function (err, response) { - // handle err or response -}); -``` - -This gives us what we expect: - -``` - First doc returned Last doc returned - ↓ ↓ -[20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1] -``` - -### Skip and limit in backwards land - -Similarly, for `skip` and `limit`, the operations are performed on the reversed list. Setting `skip` to `5` will skip the "first" 5 documents, so `{skip : 5, descending : true}` returns: - -``` - First doc returned Last doc returned - ↓ ↓ -[20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1] -``` - -And setting `limit` to `15` will give us the "first" 15 documents, so `{limit : 15, descending : true}` gives us: - -``` -First doc returned Last doc returned - ↓ ↓ -[20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1] -``` - -Of course, you're free to go nuts and combine these parameters together. For example, the somewhat bloated options: - -```javascript -{ - skip : 1, - limit : 5, - startkey : 'doc10', - descending : true -} -``` - -would give us: - - -``` - First doc returned Last doc returned - ↓ ↓ -[20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1] -``` - -## Keeping your strings in order - -In the examples up to now, I've been careful to name my documents `'doc01'`, `'doc02'`, etc. Astute readers might wonder if that's because PouchDB uses standard [JavaScript string ordering][js-string-ordering]. And those smarty-pants readers would be correct! Since `doc2` comes after `doc10` in lexicographical ASCII order, I pad the single digits with zeroes. - -This can be a very useful trick for document sorting. Normally, PouchDB will generate a random doc ID if you don't specify one (e.g. `'36483B8A-DF4A-4AEB-B946-096BA0FA8813'`), but if you provide your own IDs, you can make sorting incredibly easy for a variety of applications. - -### Example: sort by date - -Let's imagine we want to sort our documents by date. For the doc IDs, we'll use timestamps in [standard ISO-8601 format][iso8601], given by `new Date().toJSON()`. This guarantees proper lexicographical ordering: - - [iso8601]: http://www.w3.org/TR/NOTE-datetime - -```javascript -var partyLikeIts = new Date(915148800000); // 1999 -var now = new Date(1394841840000); // 2014 - -partyLikeIts.toJSON() // "1999-01-01T00:00:00.000Z" -now.toJSON() // "2014-03-15T00:04:00.000Z" - -// Party on! -partyLikeIts.toJSON() < now.toJSON(); // true -``` - -{% include alert_start.html variant="warning" %} - -<strong>Note:</strong> If you're worried about ID collisions, you could also use <code>new Date().toJSON() + Math.random()</code>. - -{% include alert_end.html %} - -Now we can fetch the 10 most recent docs: - -```javascript -{ - limit : 10, - descending : true -} -``` - -Or the first 10 docs published after January 1st, 2000: - -```javascript -{ - limit : 10, - startkey : '2000-01-01T00:00:00.000Z' -} -``` - - -And if you need fancier sorting, or more than one index, try the Map/Reduce-powered [`query()` API][query-api], which boasts [complex key collation](http://docs.couchdb.org/en/latest/couchapp/views/collation.html#collation-specification). - -## total_rows is totally awesome - -When we call `allDocs()`, a typical response object looks like this: - -```javascript -{ - "total_rows": 20, - "offset": 0, - "rows": [/* results go here */] -} -``` - -`offset` simply tells us how many documents were `skip`ped, but `total_rows` tells us the total number of docs in our database. This can be very useful if you want to calculate how many documents are left to be read in, or if you just want to quickly fetch the database size. - -For instance, calling `allDocs()` with `{limit : 0}` will simply return an empty list: - -```javascript -{ - "total_rows": 20, - "offset": 0, - "rows": [] -} -``` - -If you're a SQL jockey, you can think of this as your `COUNT(*)`. - - -## Putting it all together - -PouchDB and CouchDB handle pagination like it ain't no thing. There are more advanced topics, like how to page through Map/Reduce views with the `query()` API, but if you understand `allDocs()`, you're already 75% of the way there. - -So congratulations, you're now a [Page Master]! Try to use your newfound powers for good. - - [couch-query-api]: https://wiki.apache.org/couchdb/HTTP_view_API#Querying_Options - [js-string-ordering]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#Comparing_strings - [collation-specification]: http://docs.couchdb.org/en/latest/couchapp/views/collation.html#collation-specification - [query-api]: http://pouchdb.com/api.html#query_database - [page master]: https://en.wikipedia.org/wiki/Pagemaster - [remove]: http://pouchdb.com/api.html#delete_document \ No newline at end of file
diff --git a/docs/_posts/2014-05-01-pouchdb-2.2.0.md b/docs/_posts/2014-05-01-pouchdb-2.2.0.md deleted file mode 100644 index cc98f7e..0000000 --- a/docs/_posts/2014-05-01-pouchdb-2.2.0.md +++ /dev/null
@@ -1,29 +0,0 @@ ---- -layout: post - -title: PouchDB 2.2.0 - -author: Dale Harvey - ---- - -[PouchDB 2.2.0](https://github.com/daleharvey/pouchdb/releases/tag/2.2.0) is now released! Please [file issues](https://github.com/daleharvey/pouchdb/issues) or [tell us what you think](https://github.com/daleharvey/pouchdb/blob/master/CONTRIBUTING.md#get-in-touch). We would also like to give a huge thanks to our [new and existing contributors](https://github.com/daleharvey/pouchdb/graphs/contributors?from=2014-04-01&to=2014-05-01). - -{% include alert_start.html variant="warning"%} -We have removed the ES5 shims from PouchDB. If you require support for older browsers, it can be included from <a href='https://github.com/es-shims/es5-shim'>https://github.com/es-shims/es5-shim</a>. -{% include alert_end.html %} - -### Major Changes: - - * Fix replication for large databases ([#1954](https://github.com/pouchdb/pouchdb/issues/1954)) - * Persistent map/reduce ([#1658](https://github.com/pouchdb/pouchdb/issues/1658)) - * Fix experimental `.sync()` API ([#1696](https://github.com/pouchdb/pouchdb/issues/1696)) - * `.replication()` API switched to an `EventEmitter` ([#1916](https://github.com/pouchdb/pouchdb/issues/1916)) - * `.changes()` API switched to an `EventEmitter` ([#1768](http://github.com/daleharvey/pouchdb/issues/1768)) - * Experimental LevelDB-based LocalStorage adapter ([#44](http://github.com/daleharvey/pouchdb/issues/44)) - * Performance improvements ([#1869](http://github.com/daleharvey/pouchdb/issues/1869), [#1871](http://github.com/daleharvey/pouchdb/issues/1871), [#1889](https://github.com/pouchdb/pouchdb/pull/1889), [#1897](https://github.com/pouchdb/pouchdb/pull/1897), [#1990](https://github.com/pouchdb/pouchdb/issues/1990)) - * Remove ES5 shims ([#1753](http://github.com/daleharvey/pouchdb/issues/1753)) - * Performance tests ([#113](http://github.com/daleharvey/pouchdb/issues/113)) - - -###### [Complete list of changes](https://github.com/daleharvey/pouchdb/compare/2.1.0...2.2.0)
diff --git a/docs/_posts/2014-05-01-secondary-indexes-have-landed-in-pouchdb.md b/docs/_posts/2014-05-01-secondary-indexes-have-landed-in-pouchdb.md deleted file mode 100644 index ac122ea..0000000 --- a/docs/_posts/2014-05-01-secondary-indexes-have-landed-in-pouchdb.md +++ /dev/null
@@ -1,496 +0,0 @@ ---- -layout: post - -title: Secondary indexes have landed in PouchDB - -author: Nolan Lawson - ---- - -With the release of PouchDB 2.2.0, we're happy to introduce a feature that's been cooking on the slow simmer for some time: secondary indexes, a.k.a. persistent map/reduce. - -This is a powerful new tool for developers, since it allows you to index anything in your JSON documents – not just the doc IDs. Starting in 2.2.0, your data is sortable and searchable in ways that just weren't feasible before, thanks to a new cross-platform indexing engine we've built to work with every supported backend - IndexedDB, WebSQL, and LevelDB (and soon: LocalStorage!). - -As usual with PouchDB, the new API is modeled after CouchDB's. So developers who are already familiar with the [CouchDB map/reduce API](https://wiki.apache.org/couchdb/HTTP_view_API) will be up and running in no time. - -And did I mention? It's fast. Our [performance tests](https://gist.github.com/nolanlawson/11100235) show that the new persistent map/reduce API could give you orders of magnitude improvements over the old on-the-fly `query()` method. In a database containing 1,000 documents, we found queries in PouchDB 2.2.0 to be between 10 and 100 times faster than in PouchDB 2.1.2. - -Show me the code! ------ - -Here's the old way to query: - -```js -var pouch = new PouchDB('mydb'); - -// temporary view, each doc is processed in-memory (slow) -pouch.query(function (doc) { - emit(doc.name); -}, {key: 'foo'}).then(function (result) { - // found docs with name === 'foo' -}); -``` - -{% include alert_start.html variant="info" %} - -The <code>emit</code> pattern is part of the standard <a href='http://couchdb.readthedocs.org/en/latest/couchapp/views/intro.html'>CouchDB map/reduce API</a>. What the function basically says is, "for each document, emit <code>doc.name</code> as a key." - -{% include alert_end.html %} - -And here's the new way: - -```js -// document that tells PouchDB/CouchDB -// to build up an index on doc.name -var myIndex = { - _id: '_design/my_index', - views: { - 'my_index': { - map: function (doc) { emit(doc.name); }.toString() - } - } -}; -// save it -pouch.put(myIndex).then(function () { - // kick off an initial build, return immediately - return pouch.query('my_index', {stale: 'update_after'}); -}).then(function () { - // query the index (much faster now!) - return pouch.query('my_index', {key: 'foo'}); -}).then(function (result) { - // found docs with name === 'foo' -}); -``` - -Ew, you put map/reduce in my JavaScript? ------------- - -First, let's define what map/reduce is, so you can understand why you might want it. - -#### Indexes in SQL databases - -Quick refresher on how indexes work: in relational databases like MySQL and PostgreSQL, you can usually query whatever field you want: - -```sql -SELECT * FROM pokemon WHERE name = 'Pikachu'; -``` - -But if you don't want your performance to be terrible, you first add an index: - -```sql -ALTER TABLE pokemon ADD INDEX myIndex ON (name); -``` - -The job of the index is to ensure the field is stored in a B-tree within the database, so your queries run in _O(log(n))_ time instead of _O(n)_ time. - -#### Indexes in NoSQL databases - -All of the above is also true in document stores like CouchDB and MongoDB, but conceptually it's a little different. By default, documents are assumed to be schemaless blobs with one primary key (called `_id` in both Mongo and Couch), and any other keys need to be specified separately. The concepts are largely the same; it's mostly just the vocabulary that's different. - -In CouchDB, queries are called _map/reduce functions_. This is because, like most NoSQL databases, CouchDB is designed to scale well across multiple computers, and to perform efficient query operations in parallel. Basically, the idea is that you divide your query into a _map_ function and a _reduce_ function, each of which may be executed in parallel in a multi-node cluster. - -#### Map functions - -It may sound daunting at first, but in the simplest (and most common) case, you only need the _map_ function. A basic map function might look like this: - -```js -function myMapFunction(doc) { - emit(doc.name); -} -``` - -This is functionally equivalent to the SQL index given above. What it essentially says is: "for each document in the database, emit its name as a key." - -And since it's just JavaScript, you're allowed to get as fancy as you want here: - -```js -function myMapFunction(doc) { - if (doc.type === 'pokemon') { - if (doc.name === 'Pikachu') { - emit('Pika pi!'); - } else { - emit(name); - } - } -} -``` - -Then you can query it: - -```js -// find pokemon with name === 'Pika pi!' -pouch.query(myMapFunction, {key: 'Pika pi!', include_docs: true}).then(function (result) { - // handle result -}); - -// find the first 5 pokemon whose name starts with 'P' -pouch.query(myMapFunction, { - startkey: 'P', endkey: 'P\uffff', limit: 5, include_docs: true -}).then(function (result) { - // handle result -}); -``` - -{% include alert_start.html variant="info"%} - -The pagination options for <code>query()</code> – i.e., <code>startkey</code>/<code>endkey</code>/<code>key</code>/<code>keys</code>/<code>skip</code>/<code>limit</code>/<code>descending</code> – are exactly the same as with <code>allDocs()</code>. For a beginner's guide to pagination, read <a href='http://pouchdb.com/2014/04/14/pagination-strategies-with-pouchdb.html'>Pagination strategies with PouchDB</a>. - -{% include alert_end.html %} - -#### Reduce functions - -As for _reduce_ functions, there are a few handy built-ins that do aggregate operations (`'_sum'`, `'_count'`, and `'_stats'`), and you can typically steer clear of trying to write your own: - -```js -// emit the first letter of each pokemon's name -var myMapReduceFun = { - map: function (doc) { - emit(doc.name.charAt(0)); - }, - reduce: '_count' -}; -// count the pokemon whose names start with 'P' -pouch.query(myMapReduceFun, { - key: 'P', reduce: true, group: true -}).then(function (result) { - // handle result -}); -``` - -If you're adventurous, though, you should check out the [CouchDB documentation](http://couchdb.readthedocs.org/en/latest/couchapp/views/intro.html) or the [PouchDB documentation](http://pouchdb.com/api.html#query_database) for details on reduce functions. - -Map/reduce, reuse, recycle ----------- - -PouchDB has actually had map/reduce queries since way before version 2.2.0, via the `query()` API. It had a big flaw, though: all queries were performed in-memory, reading in every document in the entire database just to perform a single operation. - -This is fine when your data set is small, but it could be murder on large databases. On mobile devices especially, memory is a precious commodity, so you want to be as frugal as possible with the resources given to you by the OS. - -The new persistent `query()` method is much more memory-efficient, and it won't read in the entire database unless you tell it to. It has two modes: - -* Temporary views (like the old system) -* Persistent views (new system) - -Both of these concepts exist in CouchDB, and they're faithfully emulated in PouchDB. - -#### A room with a view - -First off, some vocabulary: CouchDB calls indexes _views_, and these views are stored in a special document called a _design document_. Basically, a design document describes a view, and a view describes a map/reduce query, which tells the database that you plan to use that query later, so it better start indexing it now. In other words, creating a view is the same as saying `CREATE INDEX` in a SQL database. - -**Temporary views** are exactly that – temporary. Instead of using a design document, you just call `pouch.query()`, so the view is created, written to disk, queried, and then poof, it's deleted. That's why, in older version of PouchDB, we could get away with doing it all in-memory. - -Crucially, though, temporary views have to do a full scan of all documents _every time you execute them_, along with all the reading and writing to disk that that entails, only to throw it away at the end. That may be fine for quick testing during development, but in production it can be a big drag on performance. - -**Persistent views**, on the other hand, are a much better solution if you want your queries to be fast. Persistent views need to be saved in a design document (hence "persistent"), so that the emitted fields are already indexed by the time you look them up. Subsequent lookups don't need to do any additional writes to disk, unless documents have been added or modified, in which case only the updated documents need to be processed. - -{% include alert_start.html variant="info"%} - -<strong>Why design docs?</strong> <a href='http://guide.couchdb.org/draft/design.html'>Design documents</a> are special meta-documents that CouchDB uses for things like indexes, security, and schema validation (think: "designing" your database). They are stored, updated, and deleted exactly like normal documents, but their <code>_id</code>s are prefixed with the reserved string <code>'_design/'</code>. They also show up in <code>allDocs()</code> queries, but you can filter them out by using <code>{startkey: '_design0'}</code>. - -{% include alert_end.html %} - -#### Writing your first view - -A design document with a view looks just like a regular document. The simplest one might look like this: - -```js -var designDoc = { - _id: '_design/my_index', - views: { - 'my_index': { - map: function(doc) { - emit(doc.name); - }.toString() - } - } -}; -``` - -All you need to do is `put()` this document into your database: - -```js -pouch.put(designDoc).then(function (info) { - // design doc created -}).catch(function (err) { - // if err.name === 'conflict', then - // design doc already exists -}); -``` - -… and then it will be available for querying using the name `'my_index'`: - -```js -pouch.query('my_index').then(function(result) { - // do something with result -}); -``` - -Whatever name you give, be sure to use the same one in both the `_id` (after `'_design/'`) and in the `views`; otherwise you will need to use the awkward format `'my_design_doc_name/my_view_name'` when you query. - -{% include alert_start.html variant="info"%} - -Technically, a design doc can contain multiple views, but there's really no advantage to this. Plus, it can even cause performance problems in CouchDB, since all the indexes are written to a single file. So we recommend that you create one view per design doc, and use the same name for both, in order to make things simpler. - -{% include alert_end.html %} - -Since there's a lot of boilerplate involved in creating views, you can use the following helper function to create a simple design doc based on a name and a map function: - -```js -function createDesignDoc(name, mapFunction) { - var ddoc = { - _id: '_design/' + name, - views: { - } - }; - ddoc.views[name] = { map: mapFunction.toString() }; - return ddoc; -} -``` - -Then you just need to `put()` it: - -```js -var designDoc = createDesignDoc('my_index', function (doc) { - emit(doc.name); -}); -pouch.put(designDoc).then(function (doc) { - // design doc created! -}).catch(function (err) { - // if err.name === 'conflict', then - // design doc already exists -}); -``` - -From now on, you can call `pouch.query('my_index')` and it will summon this design document for querying. - -Just like regular documents, design docs can always be deleted or changed later. The index will be updated automatically the next time you `query()` it. - -If you do this a lot, though, then old indexes will build up on disk. You can call `pouch.viewCleanup()` to clean up any orphaned indexes. - -{% include alert_start.html variant="warning"%} - -<strong>Performance tip</strong>: Technically, the view will not be built up on disk until the first time you <code>query()</code> it. So a good trick is to always call <code>query(viewName, {stale: 'update_after'})</code> after creating a view, to ensure that it starts building in the background. You can also use <code>{stale: 'ok'}</code> to avoid waiting for the most up-to-date results. In the future, we may add an API for auto-updating. - -{% include alert_end.html %} - -#### For those who get nostalgic - -Of course, some of our loyal Pouchinistas may have been perfectly happy with the old way of doing things. The fact that the old `query()` function slurped the entire database into memory might have served them just fine, thank you. - -To be sure, there are some legitimate use cases for this. If you don't store a lot of data, or if all your users are on desktop computers, or if you require closures (not supported by persistent views), then doing map/reduce in memory may have been fine for you. In fact, an upgrade to 2.2.0 might actually make your app _slower_, because now it has to read and write to disk. - -Luckily we have a great solution for you: instead of using the `query()` API, you can use the much more straightforward `allDocs()` API. This will read all documents into memory, just like before, but best of all, you can apply whatever functions you want to the data, without having to bother with learning a new API or even what the heck "map/reduce" is. - -But in general, we strongly recommend upgrading your apps to the new API instead. - -When *not* to use map/reduce ----- - -Now that I've sold you on how awesome map/reduce is, let's talk about the situations where you might want to avoid it. - -First off, you may have noticed that the CouchDB map/reduce API is pretty daunting. As a newbie Couch user who very recently struggled with the API, I can empathize: the vocabulary is new, the concepts are (probably) new, and there's no easy way to learn it, except to clack at your keyboard for awhile and try it out. - -Second off, views can take awhile to build up, both in CouchDB and PouchDB. Each document has to be fetched from the database, passed through the map function, and indexed, which is a costly procedure for large databases. And if your database is constantly changing, you will also incur the penalty at `query()` time of running the map function over the changed documents. - -Luckily, it turns out that the primary index, `_id`, is often good enough for a variety of querying and sorting operations. So if you're clever about how you name your document `_id`s, you can avoid using map/reduce altogether. - -For instance, say your documents are emails that you want to sort by recency: boom, just set the `_id` to `new Date().toJSON()`. Or say they're web pages that you want to look up by URL: use the URL itself as the `_id`! Neither CouchDB nor PouchDB have a limit on how long your `_id`s can be, so you can get as fancy as you want with this. - -#### Use and abuse your doc IDs - -For a more elaborate example, let's imagine you're writing a music app. Your database might contain artists: - -```js -[ { _id: 'artist_bowie', - type: 'artist', - name: 'David Bowie', - age: 67 }, - { _id: 'artist_dylan', - type: 'artist', - name: 'Bob Dylan', - age: 72 }, - { _id: 'artist_joni', - type: 'artist', - name: 'Joni Mitchell', - age: 70 } ] -``` - -… as well as albums: - -```js -[ { _id: 'album_bowie_1971_hunky_dory', - artist: 'artist_bowie', - title: 'Hunky Dory', - type: 'album', - year: 1971 }, - { _id: 'album_bowie_1972_ziggy_stardust', - artist: 'artist_bowie', - title: 'The Rise and Fall of Ziggy Stardust and the Spiders from Mars', - type: 'album', - year: 1972 }, - { _id: 'album_dylan_1964_times_they_are_changin', - artist: 'artist_dylan', - title: 'The Times They Are a-Changin\'', - type: 'album', - year: 1964 }, - { _id: 'album_dylan_1965_highway_61', - artist: 'artist_dylan', - title: 'Highway 61 Revisited', - type: 'album', - year: 1965 }, - { _id: 'album_dylan_1969_nashville_skyline', - artist: 'artist_dylan', - title: 'Nashville Skyline', - type: 'album', - year: 1969 }, - { _id: 'album_joni_1974_court_and_spark', - artist: 'artist_joni', - title: 'Court and Spark', - type: 'album', - year: 1974 } ] -``` - -See what I did there? Artist-type documents are prefixed with `'artist_'`, and album-type documents are prefixed with `'album_'`. This naming scheme is clever enough that we can already do lots of complex queries using `allDocs()`, even though we're storing two different types of documents. - -Want to find all artists? It's just: - -```js -allDocs({startkey: 'artist_', endkey: 'artist_\uffff'}); -``` - -Want to list all the albums? Try: - -```js -allDocs({startkey: 'album_', endkey: 'album_\uffff'}); -``` - -How about all albums by David Bowie? Wham bam, thank you ma'am: - -```js -allDocs({startkey: 'album_bowie_', endkey: 'album_bowie_\uffff'}); -``` - -Let's go even fancier. Can we find all of Bob Dylan's albums released between 1964 and 1965, in reverse order? Gather 'round people, and try this: - -```js -allDocs({startkey: 'album_dylan_1965_', endkey: 'album_dylan_1964_\uffff', descending: true}); -``` - -In this example, you're getting all those "indexes" for free, each time a document is added to the database. It doesn't take up any additional space on disk compared to the randomly-generated UUIDs, and you don't have to wait for a view to get built up, nor do you have to understand the map/reduce API at all. - -Of course, this system starts to get shaky when you need to search by a variety of criteria: e.g. all albums sorted by year, artists sorted by age, etc. And you can only sort strings – not numbers, booleans, arrays, or arbitrary JSON objects, like the map/reduce API supports. But for a lot of simple applications, you can get by without using the `query()` API at all. - -{% include alert_start.html variant="warning"%} - -<strong>Performance tip</strong>: if you're just using the randomly-generated doc IDs, then you're not only missing out on an opportunity to get a free index – you're also incurring the overhead of building an index you're never going to use. So use and abuse your doc IDs! - -{% include alert_end.html %} - -Tips for writing views ------ - -When you do need the full map/reduce API, though, it pays to know the tips and tricks. Below is a list of advanced techniques and common pitfalls, which you may find useful when you're trying to squeeze that last bit of performance out of your views. - -**1. Don't index it if you don't need it** - -If your database has several document types, but only the "person" type has a `lastName` field, do this: - -```js -function (doc) { - if (doc.lastName) { - emit(doc.lastName); - } -} -``` - -If you took out the `if` statement, you'd emit a `null` key for every non-person in your database, which needlessly bloats the size of your index. - -{% include alert_start.html variant="info"%} - -If the <code>null</code> field is meaningful for some reason, though, you can emit it and look it up later using <code>query(viewName, {key: null})</code>. Any <code>undefined</code> fields are treated as <code>null</code>. - -{% include alert_end.html %} - -**2. Move logic to the query params** - -Don't do: - -```js -function (doc) { - if (doc.highScore >= 1000) { - emit(doc.highScore); - } -} -``` - -Instead, do: - -```js -function (doc) { - emit(doc.highScore); -} -``` - -And then query with `{startkey: 1000}`. - -**3. Use high characters for prefix search** - -To find every `lastName` that starts with an `'L'`, you can use the high Unicode character `'\uffff'`: - -```js -pouch.query(viewName, {startkey: 'L', endkey: 'L\uffff'}); -``` - -Or you can set `inclusive_end` to `false`: - -```js -pouch.query(viewName, {startkey: 'L', endkey: 'M', inclusive_end: false}); -``` - -Both queries will do the same thing. - -**4. Use {} for complex key ranges** - -If your keys are `[lastName, firstName]`, and you need to find everybody with the last name `'Harvey'`, you can do: - -```js -pouch.query(viewName, {startkey: ['Harvey'], endkey: ['Harvey', {}]}); -``` - -In [CouchDB collation ordering][couchdb-collation], `{}` is higher than everything except other objects. - - -For the database geeks: implementation details -------- - -If you want to know how map/reduce works in PouchDB, it's actually exceedingly easy: just open up your browser's developer tools, head over to "Resources," and see where we've created a bonus database to store the index. - -One of the neat things about how we implemented map/reduce is that we managed to do it entirely within PouchDB itself. Yep, that's right: your map/reduce view is just a regular old PouchDB database, and map/reduce itself is a plugin with no special privileges, creating databases in exactly the same way a regular user would. Since the implementation sits on top of the PouchDB API, it's exactly the same for all three backends: LevelDB, IndexedDB, and WebSQL. - -How did we pull off this trick? To be clear: it's not like we set out to make PouchDB some kind of map/reduce engine. In fact, as we were debating how to implement this feature, we originally ran on the assumption that we'd need to build additional functionality on top of PouchDB. It was only after a few months of discussions and experiments that we realized the whole thing could be done in PouchDB proper. - -In the end, the only additional functionality we had to add to the main PouchDB code was a hook to tell PouchDB to destroy the map/reduce database when its parent database was destroyed. That's it. - -This technique also has a nice parallel in CouchDB: it turns out that they, too, reused the core `_view` code in order to write `_all_docs`. In CouchDB, `_all_Docs` is just a special kind of `_view`, whereas in PouchDB, we built map/reduce views on top of `allDocs()`. We did it backwards, but the spirit of the idea was the same. - -As for the index itself, what it basically boils down to is clever serialization of arbitrary JSON values into [CouchDB collation ordering][couchdb-collation] – i.e. nulls before booleans, booleans before numbers, numbers before strings, strings before arrays, arrays before objects, and so on recursively. Every JSON object maps to an indexable string that guarantees the same ordering in every database backend, and we only deviate from CouchDB by using ASCII string ordering instead of ICU ordering (since that's what our backends use). - - [couchdb-collation]: http://couchdb.readthedocs.org/en/latest/couchapp/views/collation.html - -Then, we take this value and concatenate it with whatever else needs to be indexed (usually just the doc `_id`), meaning the entire lookup key is a single string. We decided on this implementation because: - -1. LevelDB does not support complex indexes. -2. IndexedDB _does_ support complex indexes, but [not in IE][ie-complex-keys]. -3. WebSQL supports multi-field indexes, but it's also a dead spec, so we're not going to prioritize it above the others. - -The next part of the design was to divide the data we needed to store into two kinds of documents: 1) emitted key/values with doc IDs, which are used for querying and pagination, and 2) mappings from doc IDs to those key/values, so that we can delete or update them when their parent documents are deleted or updated. Since by design, PouchDB databases do not have multi-document transaction semantics, we implemented a task queue on top of the database to serialize writes. - -Aside from that, the only other neat trick was a liberal use of `_local` documents, which are a special class of documents that aren't counted in the `total_rows` count, don't show up in `allDocs`, but can still be accessed using the normal `put()` and `get()` methods. This is all it takes to fully reimplement CouchDB map/reduce in a tiny JavaScript database! - -Anyone interested in more implementation details can read the months-long discussions in [these][mapreduce-12] [Github][1549] [issues][1658]. The [map/reduce code][mapreduce] itself is also pretty succinct. - -[mapreduce]: https://github.com/pouchdb/mapreduce -[mapreduce-12]: https://github.com/pouchdb/mapreduce/issues/12 -[1549]: https://github.com/pouchdb/pouchdb/issues/1549 -[1658]: https://github.com/pouchdb/pouchdb/issues/1658 -[ie-complex-keys]: https://gist.github.com/nolanlawson/8330172
diff --git a/docs/_posts/2014-06-01-pouchdb-2.2.3.md b/docs/_posts/2014-06-01-pouchdb-2.2.3.md deleted file mode 100644 index e7c6f09..0000000 --- a/docs/_posts/2014-06-01-pouchdb-2.2.3.md +++ /dev/null
@@ -1,26 +0,0 @@ ---- -layout: post - -title: PouchDB 2.2.3 - -author: Dale Harvey - ---- - -[PouchDB 2.2.3](https://github.com/daleharvey/pouchdb/releases/tag/2.2.3) is now released! Please [file issues](https://github.com/daleharvey/pouchdb/issues) or [tell us what you think](https://github.com/daleharvey/pouchdb/blob/master/CONTRIBUTING.md#get-in-touch). We would also like to give a huge thanks to our [new and existing contributors](https://github.com/daleharvey/pouchdb/graphs/contributors?from=2014-05-01&to=2014-06-01). - -### Major Changes: - - * Experimental browser adapter plugins ([#2190](http://github.com/daleharvey/pouchdb/issues/2190)) - * Fix Ember.js integration ([#2158](http://github.com/daleharvey/pouchdb/issues/2158)) - * Fix Browserify integration ([#2249](http://github.com/daleharvey/pouchdb/issues/2249), [pouchdb/mapreduce#170](https://github.com/pouchdb/mapreduce/issues/170)) - * Fixes for conflict resolution ([#2072](http://github.com/daleharvey/pouchdb/issues/2072)) - * Better error handling in replication ([#2122](http://github.com/daleharvey/pouchdb/issues/2122)) - * Fix Internet Explorer 10-11 ([#1661](http://github.com/daleharvey/pouchdb/issues/1661), [#2198](http://github.com/daleharvey/pouchdb/issues/2198), [#2132](http://github.com/daleharvey/pouchdb/issues/2132)) - * Fix attachments in Android 4.x ([#1992](http://github.com/daleharvey/pouchdb/issues/1992)) - * Fix LevelDB memory leak, race condition, error messages ([#2250](http://github.com/daleharvey/pouchdb/issues/2250), [#2251](http://github.com/daleharvey/pouchdb/issues/2251), [#2144](http://github.com/daleharvey/pouchdb/issues/2144)) - * Perf improvements for replication in WebSQL & IndexedDB ([#2180](http://github.com/daleharvey/pouchdb/issues/2180), [#2178](http://github.com/daleharvey/pouchdb/issues/2178)) - * Bugfixes for IndexedDB inclusive_end ([#2129](http://github.com/daleharvey/pouchdb/issues/2129)) - * Fix `changes()` memory leak ([#2311](http://github.com/daleharvey/pouchdb/issues/2311)) - -###### [Complete list of changes](https://github.com/daleharvey/pouchdb/compare/2.2.0...2.2.3)
diff --git a/docs/_posts/2014-06-17-12-pro-tips-for-better-code-with-pouchdb.md b/docs/_posts/2014-06-17-12-pro-tips-for-better-code-with-pouchdb.md deleted file mode 100644 index b65d846..0000000 --- a/docs/_posts/2014-06-17-12-pro-tips-for-better-code-with-pouchdb.md +++ /dev/null
@@ -1,272 +0,0 @@ ---- -layout: post - -title: 12 pro tips for better code with PouchDB - -author: Nolan Lawson - ---- - -This is not a blog post per se, but more of a list of tips and tricks to get the most out of your PouchDB experience. - -There are a lot of PouchDB anti-patterns floating around out there on the Internet, and also some common pitfalls that can trip you up when you're new to the CouchDB API. I see this stuff all the time on Stack Overflow, Twitter, and IRC, and it never ceases to amaze and horrify me. We need to do better. - -So consider this your 12-step program to becoming a better PouchDB coder. Let's put these bad habits to bed. - -### 1. Use put(), not post() - -Never use `post()`. You don't need it, so just stop. - -Recall that `put()` requires you to supply your own doc ID, whereas `post()` generates a random one for you. However, this leads to inefficiencies, since you pay the cost of indexing a long ID like `'CB89021E-8439-392F-899C-054963FD0B9B'` without ever using it. - -Plus, you'll have to use `put()` anyway whenever you update or delete a document, so if you `post()`, you've got two APIs to learn instead of one. So remember: always `put()`, never `post()`. - -### 2. Don't emit(doc.foo, doc) - -Don't do: - -```js -function (doc) { - emit(doc.foo, doc); -} -``` - -Do: - -```js -function (doc) { - emit(doc.foo); -} -``` - -This anti-pattern is everywhere. It seems to date back to pre-PouchDB days, since it shows up in a lot of blog posts and articles about CouchDB. - -Folks, you never need to `emit()` the full document in your map/reduce functions. You can always just use `{include_docs: true}` when you query, and the freshest version of that document will be delivered right to your door. Free of charge. - -Plus, if you emit the full doc, then it will actually _serialize and write out that entire document to disk_. This is true in both PouchDB and CouchDB, and it's pure waste. - -So if you don't want big, inefficient map/reduce functions, then remember: only `emit()` what you need. - -### 3. Don't emit(doc.foo, 1) and then _sum - -Similar to the above, don't do: - -```js -{ - map: - function (doc) { - emit(doc.foo, 1); - }.toString(), - reduce: '_sum' -} -``` - -Do: - -```js -{ - map: - function (doc) { - emit(doc.foo); - }.toString(), - reduce: '_count' -} -``` - -You don't need to use `_sum` when a simple `_count` will do. - -### 4. Attachments are overrated - -NPM has [moved away from storing attachments in CouchDB](http://blog.npmjs.org/post/71267056460/fastly-manta-loggly-and-couchdb-attachments). Nowadays they use a CDN for the binaries, and CouchDB just stores the metadata. In PouchDB, attachments have been [one](https://github.com/pouchdb/pouchdb/issues/2098) [of](https://github.com/pouchdb/pouchdb/pull/1078) [the](https://github.com/pouchdb/pouchdb/issues/1992) [biggest](https://github.com/pouchdb/pouchdb/issues/900) [sources](https://github.com/pouchdb/pouchdb/pull/2063) [of](https://github.com/pouchdb/pouchdb/pull/1210) [bugs](https://github.com/pouchdb/pouchdb/pull/502), since every browser seems to handle them differently. Plus, the [attachment API is hard to understand](https://github.com/pouchdb/pouchdb/issues/1251), you need [a Blob shim](https://gist.github.com/nolanlawson/10340255) for older browsers, and let's not even talk about ArrayBuffers, ArrayBufferViews, Uint8Arrays, and browsers that don't even support any of the above. - -In general, both CouchDB and PouchDB are just poor fits for storing binary data. (Databases rarely are.) Instead of attachments, try using a CDN or a simple fileserver, and store the URLs or checksums in the database if you need to. - - -<blockquote> - -<p> -"One of the big things that everybody who's spent a lot of time with databases knows is that you should <em>never</em> put your binaries in the database. It's a terrible idea. It always goes wrong. I have never met a database in 15 years of which it is not true, and it's definitely not true of CouchDB. -</p> - -<p> -You are taking this thing which is meant to sort and organize data, and you're giving it binary data, which it can neither sort nor organize. It can't do anything with that data, other than get really fat." -</p> - -<footer> -<cite title="Source Title"> - Laurie Voss, on <a href='http://javascriptjabber.com/099-jsj-npm-inc-with-isaac-schlueter-laurie-voss-and-rod-boothby/'>JavaScript Jabber</a> -</cite> -</footer> - -</blockquote> - - -### 5. Use plugins - -[PouchDB has plugins](http://pouchdb.com/external.html). Use them, and if inspiration ever strikes, [write your own](https://github.com/pouchdb/plugin-seed)! - -### 6. Don't just update docs for the hell of it - -Every time you modify a document, another revision is added to its revision history – think Git. Except unlike Git, these revisions contain the full document data (not just the diffs), which can take up a lot of space on disk. So if nothing changed in a document, don't bother `put()`ing it again. - -### 7. Use and abuse your doc IDs - -I already wrote [a blog post about this](http://pouchdb.com/2014/05/01/secondary-indexes-have-landed-in-pouchdb.html), but basically, if you don't want bad performance from your secondary indexes, the best strategy is to avoid secondary indexes altogether. The primary index should be sufficient for sorting and searching in nearly all of your applications, or at least for the hot-path code. - -Also, if you really want to get fancy with your doc IDs, you can use [PouchDB Collate](https://github.com/pouchdb/collate/) to serialize arbitrary data into strings that are sorted according to [CouchDB collation ordering](https://wiki.apache.org/couchdb/View_collation). This allows you to index on arrays, objects, numbers – whatever you want: - -```js -var pouchCollate = require('pouchdb-collate'); -var myDoc = { - firstName: 'Scrooge', - lastName: 'McDuck', - age: 67, - male: true -}; -// sort by age, then gender, then last name, then first name -myDoc._id = pouchCollate.toIndexableString( - [myDoc.age, myDoc.male, mydoc.lastName, mydoc.firstName]); -``` - -In the above example, the doc ID will be a crazy string, which will sort correctly in both CouchDB and PouchDB: - -```js -'5323256.70000000000000017764\u000021\u00004McDuck\u00004Scrooge\u0000\u0000' -``` - -This is actually what persistent map/reduce uses under the hood! - -And for cases where you only need to build complex IDs out of strings, there is also the fantastic [DocURI](https://github.com/jo/docuri) project, which can build a more human-readable ID like this: - -```js -'movie/blade-runner/gallery-image/12/medium' -``` - -Choose whichever one fits your app better, or just concatenate the strings yourself. - - -### 8. Use Web SQL for better performance - -Our performance tests have shown it again and again: Web SQL is faster than IndexedDB. It's hard to tell if that's due to our implementation or the browser vendors', but in any case, if you feel the need for speed, then you'll want to prefer Web SQL to IndexedDB. - -So now that Android 4.4, iOS 8, and Safari 8 support IndexedDB in addition to Web SQL, it's more important than ever to consider using Web SQL instead of IndexedDB – at least, in apps where performance matters. To do so, the code is simply: - -```js -var pouch = new PouchDB('mydb', {adapter: 'websql'}); -if (!pouch.adapter) { // websql not supported by this browser - pouch = new PouchDB('mydb'); -} -``` - -{% include alert_start.html variant="info" %} - -<em>If Web SQL is so fast, why does PouchDB fall back to Web SQL from IndexedDB instead of the other way around?</em> Because we're trying to move the web forward, not rely on deprecated technology. If browser vendors can rest on their laurels with Web SQL, then they won't work to make IndexedDB faster. - -{% include alert_end.html %} - -### 9. Move logic from the map function to query() - -If you only remember one thing from [my blog post about secondary indexes](http://pouchdb.com/2014/05/01/secondary-indexes-have-landed-in-pouchdb.html), remember this: every `map` function you write has to be executed for every single document in your database. No exceptions. - -On the other hand, the `query()` options like `startkey`, `endkey`, `key`, and `keys` have been optimized to hell, and they leverage the native indexes in the database to deliver the maximum possible performance. - -So if you find yourself writing something like this, you're doing it wrong: - -```js -function getPostsSince(when) { - return db.query({ - map: function(doc, emit) { - if (doc.timestamp > when) { - emit(doc.name, 1); - } - }, - // ... -} -function getPostsBefore(when) { - return db.query({ - map: function(doc, emit) { - if (doc.timestamp < when) { - emit(doc.name, 1); - } - }, - // ... -} -function getPostsBetween(startTime, endTime) { - return db.query({ - map: function(doc, emit) { - if (doc.timestamp > startTime && doc.timestamp < endTime) { - emit(doc.name, 1); - } - }, - // ... -} -``` - -Each of those `db.query()` calls represents a separate _temporary index_. I.e., all your docs are read in, run through the map function, spit out to an index, queried, and then the whole thing is thrown away. For every query! This code is based on a real question I got from a developer on Twitter (sorry to pick on ya), and he described it as "crazy slow." No kidding. - -Since all of these map/reduce functions key off of `doc.timestamp`, a better approach (which I recommended to him) would be: - -```js -var ddoc = createDesignDoc('by_timestamp', function (doc) { - emit(doc.timestamp, doc.name); -}); -db.put(ddoc).then(function() {/* etc. */}); - -function getPostsSince(when) { - return db.query('by_timestamp', {endkey: when, descending: true}); -} -function getPostsBefore(when) { - return db.query('by_timestamp', {startkey: when}); -} -function getPostsBetween(startTime, endTime) { - return db.query('by_timestamp', {startkey: startTime, endkey: endTime}); -} -``` - -(That `createDesignDoc()` helper function comes from [this blost post](http://pouchdb.com/2014/05/01/secondary-indexes-have-landed-in-pouchdb.html).) - -Not only is the above code much simpler, but it's also faster and more tweakable. No need to completely rebuild the index when your query changes; just switch around `startkey`/`endkey`/`descending` and friends at query time to get the data you want. - -### 10. You probably don't need reduce - -In the previous example, the developer was also doing some fancy operations on the data using `'_count'` and `'_sum'`. Now, these are fine shortcuts that can save you a lot of code, but unless you're running your queries against the server, they don't buy you any performance benefits. - -PouchDB runs in Node or the browser, meaning it's a single-threaded, single-process environment. There's no massive parallelization of the map/reduce functions like you could get with CouchDB (or at least, BigCouch/Cloudant/Couchbase). So PouchDB takes a shortcut and just runs every `reduce` function in memory (there's no point in writing it to disk), meaning it's not doing anything you couldn't just do yourself. - -So if you find yourself writing three different design documents that all `emit` the same thing but have different `reduce` functions: don't bother. You can get better performance and smaller code by just writing a single design document with no `reduce`, and then doing the reduce yourself. - -### 11. Debug with the CouchDB UI - -One common question is: How do I debug my database? Well, that's easy: just replicate to CouchDB! Then you can browse your data in CouchDB's handy Futon interface. - -In your code or in the browser console, just run: - -```js -PouchDB.replicate('mydb', 'http://localhost:5984/mydb', {live: true}); -``` - -Then open up [http://localhost:5984/_utils](http://localhost:5984/_utils). Or if you want to try the new Fauxton API in CouchDB 1.5: [http://localhost:5984/_utils/fauxton/](http://localhost:5984/_utils/fauxton/). You'll get a nice interface that looks like this: - -<img src='/static/img/fauxton.png' title='Fauxton UI in PouchDB Server' alt='Fauxton UI in PouchDB Server' style='width:100%'/> - -And if you don't feel like installing CouchDB, you can install [PouchDB Server](https://github.com/pouchdb/pouchdb-server) instead: - -``` -$ npm install -g pouchdb-server -$ pouchdb-server -p 5984 -``` - -Then open up [http://localhost:5984/_utils](http://localhost:5984/_utils). - - -### 12. Contribute! - -To paraphrase [Martin Fowler's famous talk](https://www.youtube.com/watch?v=qI_g07C_Q5I), part of the motivation behind the NoSQL movement was the collective realization by a generation of developers that, you know, this whole "database" thing? It isn't really that hard. Keys map to values, stuff's written to disk: it's a cinch once you learn the basics. And PouchDB occupies an even humbler niche in the NoSQL community, since our NoSQL database is actually built on other databases. - -So if you find a bug, or if there's a missing feature you'd like to request, then check out the code and open a pull request! We've got a very handsomely documented [contributor's guide](https://github.com/pouchdb/pouchdb/raw/master/CONTRIBUTING.md), and we're always happy to answer questions on [IRC](irc://freenode.net/#pouchdb), [Twitter](http://twitter.com/pouchdb), and [the mailing list](https://groups.google.com/forum/#!forum/pouchdb). - -And even if you've committed the above errors (I know I have), we won't judge you too harshly. If you've read this far, then you're already on the path to recovery. - -### More tips - -For more CouchDB tips in easily-digestible list format, check out Joan Touzet's awesome presentation: [10 Common Misconceptions about CouchDB](http://youtu.be/BKQ9kXKoHS8). And to see what you can get away with if you bend these rules a bit, watch [the talk that Nathan Vander Wilt gave](http://youtu.be/4QttTEbQ_1I) right after.
diff --git a/docs/_posts/2014-07-25-pouchdb-levels-up.md b/docs/_posts/2014-07-25-pouchdb-levels-up.md deleted file mode 100644 index 5e05ec1..0000000 --- a/docs/_posts/2014-07-25-pouchdb-levels-up.md +++ /dev/null
@@ -1,75 +0,0 @@ ---- -layout: post - -title: PouchDB levels up - -author: Nolan Lawson - ---- - -You might not have noticed it, but PouchDB underwent a quiet revolution over the past few months. The catalyzing moment was [the LevelUP proposal](https://github.com/pouchdb/pouchdb/issues/1250) posted by Nick Thompson back in January 2014, which slowly led to a rewrite of the PouchDB adapter for LevelDB to support arbitrary LevelUP backends. If that looks like word soup, let me explain why this is such a big deal. - -### LevelDB - -In 2011, Google invented [LevelDB](https://en.wikipedia.org/wiki/LevelDB) as their answer to the [IndexedDB spec](http://www.w3.org/TR/IndexedDB/) designed by Nikunj Mehta. Like IndexedDB, it's quite a low-level abstraction that provides only the bare bones of what you'd need to qualify as a database – key-value storage, iteration, batch operations, and little else. Indeed, this was one of the big selling points of IndexedDB: it was low-level and unimposing enough that all the browser vendors could agree on it. - -As it turned out, though, Google's implementation was really good. Due to [its unique design](http://dailyjs.com/2013/04/19/leveldb-and-node-1/) inspired by BigTable, it scales well for anything from small application stores to huge multi-cluster databases. And thanks to its limited scope, it's been adopted as a core building block for more feature-rich databases, most notably Basho's [Riak](http://basho.com/riak/), Facebook's [RocksDB](http://rocksdb.org/), and [Hyperdex](http://hyperdex.org/). - -### LevelDB comes to Node - -In Node.js, LevelDB took an especially interesting turn when Rod Vagg started the [LevelUP project](https://github.com/rvagg/node-levelup). LevelUP aimed not only to provide a fluent, Node-friendly API for LevelDB, but also to create a new lingua franca for persistent datastores. With LevelUP, the team managed to separate the API from the underlying storage engine (cheekily named LevelDOWN), therefore allowing any database that exposes a LevelUP-compliant API to be swapped in under the hood. - -Since the LevelUP project began, the number of compatible datastores has exploded, and today you're spoiled for choice if you write your app to the LevelUP API. As a developer, you can start with LevelDOWN, but if you later decide LevelDB itself isn't to your tastes, you can swap it out for any one of: - -* [level-rocksdb](https://github.com/Level/level-rocksdb), Facebook's fork for RocksDB -* [Level.js](https://github.com/maxogden/level.js), a browser-based store built on IndexedDB -* [RiakDOWN](https://github.com/nlf/riakdown), a Riak-based store -* [MemDOWN](https://github.com/rvagg/memdown), an in-memory store -* and [many others](https://github.com/rvagg/node-levelup/wiki/Modules#storage-back-ends). - -What this means in practice is that you could, for instance, use: - -* MemDOWN for your unit tests, -* Level.js when your app runs in a browser, -* LevelDOWN on your dev server, -* and Riak in your production server. - -In a sense, LevelUP brings to the NoSQL world the same benefits of interoperability that the SQL world enjoyed for so long. SQL databases share the SQL language, and the LevelUP-compliant databases share the LevelUP API. - -### Enter PouchDB - -This brings us back to Nick Thompson's [LevelUP proposal](https://github.com/pouchdb/pouchdb/issues/1250). At the time he wrote it, PouchDB had three supported backends – LevelDB, Web SQL, and IndexedDB. All three were written as separate adapters tailored to PouchDB's API, but he pointed out that if we integrated with LevelUP, we could piggyback on LevelUP's success and potentially get lots of new backends for free. - -For instance, there was [a longstanding issue](https://github.com/pouchdb/pouchdb/issues/44) to add LocalStorage support for older browsers like IE 8 and 9. With LevelUP, we could avoid writing an entirely new, fourth adapter and simply plug into [localstorage-down](https://github.com/No9/localstorage-down). And it certainly wouldn't hurt to have Riak, Redis, or an in-memory database as potential backends. - -There was some hemming and hawing (mostly from me), but in the end we decided to cruise ahead with the proposal. (And ultimately, I was happily proven wrong.) Calvin Metcalf deserves the primary credit for integrating [Sublevel](https://github.com/dominictarr/level-sublevel) into the LevelDB adapter, while Adam Shih jumped in to get the new adapter browserified with three different backends: localstorage-down, level-js, and MemDOWN. I put the finishing touches to build them as separate plugins, and as of 2.2.3 they're fully passing the test suite and [ready to use](http://pouchdb.com/adapters.html#pouchdb_in_the_browser). - -Additionally, [PouchDB Server](https://github.com/pouchdb/pouchdb-server) has been updated to allow the use of alternate backends via the `--level-backend` option. This provides an instant CouchDB REST API to any LevelUP-compliant datastore – Redis, Riak, MySQL, you name it. There's also a new `--in-memory` option, courtesy of MemDOWN, of course. - -### Community dynamics - -Besides getting some new backends, another cool change was that PouchDB started to take a more active role in the LevelUP community. Calvin Metcalf wrote [SQLdown](https://github.com/calvinmetcalf/SQLdown), Adam Shih and I became maintainers of localstorage-down, and all three of us submitted patches to level-js, MemDOWN, [abstract-leveldown](https://github.com/rvagg/abstract-leveldown), and even LevelUP itself. The PouchDB test suite [has been offered](https://github.com/rvagg/abstract-leveldown/issues/26) as an additional means of testing for *DOWN authors, and it's already been used to fix bugs in [RiakDOWN](https://github.com/nlf/riakdown) and [RedisDOWN](https://github.com/hmalphettes/redisdown). - -So in a sense, we didn't really get these new adapters "for free." PouchDB is complex enough, and our unit tests are thorough enough, that we ended up pushing the LevelUP folks' code to the limit, discovering many new bugs in the process. - -But in a more positive sense, we've actually achieved Nick Thompson's goal of more deeply integrating with the LevelUP community, thereby reducing redundancy and putting more effort into a smaller codebase. And in the future, positive changes in PouchDB will spill over into the LevelUP universe, and vice-versa. - -The only original aim that we haven't achieved is to consolidate our three adapters (LevelDB, Web SQL, and IndexedDB) into one. We have a few reasons for this: our custom IndexedDB adapter is currently faster than Level.js, SQLdown is still a work in progress, and we're wary of the inevitable schema migration. - -However, the fact that we can have dozens of PouchDB backends, while only maintaining three parallel adapters, is still a huge boon and was well worth the effort. - -### Conclusion - -PouchDB has a bright future as part of the LevelUP ecosystem. What would have sounded like a crazy dream half a year ago is now a verifiable reality, with unit tests to boot. Today you can write an app that: - -* Syncs from CouchDB to an in-memory [PouchDB Server](https://github.com/pouchdb/pouchdb-server), -* Then syncs to LocalStorage on IE 8, -* Then syncs to [Cloudant](https://cloudant.com/), -* Then syncs to a PhoneGap app using the [SQLite Plugin](https://github.com/brodysoft/Cordova-SQLitePlugin), -* Then syncs to any one of Redis, Riak, SQLite, LevelDB, MySQL, PostgreSQL, and potentially [many more](https://github.com/rvagg/node-levelup/wiki/Modules#storage-back-ends). - -Or whatever other crazy combination you can cook up! - -The marriage of PouchDB and LevelUP has essentially resulted in a marriage of the CouchDB sync protocol to the LevelUP API. Any database that exposes a LevelUP interface is now a full-fledged CouchDB replication target, which is a huge win for application developers. - -Which database do you want to sync to? Well, which database do you feel like today? \ No newline at end of file
diff --git a/docs/_posts/2014-08-12-pouchdb-3.0.0.md b/docs/_posts/2014-08-12-pouchdb-3.0.0.md deleted file mode 100644 index a587195..0000000 --- a/docs/_posts/2014-08-12-pouchdb-3.0.0.md +++ /dev/null
@@ -1,43 +0,0 @@ ---- -layout: post - -title: PouchDB 3.0.0 - -author: Calvin Metcalf - ---- - -[PouchDB 3.0.0](https://github.com/pouchdb/pouchdb/releases/tag/3.0.1) is finally released! It's faster, it's more stable, it's easier to debug, it doesn't freeze the DOM and it spontaneously generates kittens. - -Please [file issues](https://github.com/pouchdb/pouchdb/issues) or [tell us what you think](https://github.com/pouchdb/pouchdb/blob/master/CONTRIBUTING.md#get-in-touch). We would also like to give a huge thanks to our [new and existing contributors](https://github.com/pouchdb/pouchdb/graphs/contributors?from=2014-06-01&to=2014-08-12). - -{% include alert_start.html variant="warning"%} -This release includes a migration. Your existing database will be updated automatically, but you cannot downgrade to a previous version of PouchDB once you've upgraded. -{% include alert_end.html %} - -### Breaking Changes: -* The browser build `pouchdb-nightly.js` has been renamed to `pouchdb.js`. It was never really a nightly anyway. ([#2146](https://github.com/pouchdb/pouchdb/issues/2146)) -* `opts.server` has been deprecated from the `replicate()` and `sync()` APIs. You can still replicate from one HTTP server to another, but the data will flow through PouchDB rather than being server-initiated. ([#2313](https://github.com/pouchdb/pouchdb/issues/2313)) -* You can no longer rely on errors to have an identifying name. Instead, rely on CouchDB-centric errors to have a status (i.e. `err.status` instead of `err.name`). There are some that still have an identifying name, but **these could be removed at any time**. The upside of this is that stack traces should be more consistently helpful. ([#2545](https://github.com/pouchdb/pouchdb/issues/2545)) - -### Major Changes: - - * Constructor option `opts.size` to work around Safari/iOS storage quotas ([#2347](https://github.com/pouchdb/pouchdb/issues/2347)) - * `PouchDB.defaults()` for default constructor options, which permits many new features in pouchdb-server. ([#2054](https://github.com/pouchdb/pouchdb/issues/2054)) - * `_local` documents are now unversioned in the underlying backend for better map/reduce performance and to better align the `update_seq` with CouchDB ([#2023](https://github.com/pouchdb/pouchdb/issues/2023)). Also fixes an issue with replication and `changes()`. ([#2342](https://github.com/pouchdb/pouchdb/issues/2342)) - * Performance improvements. ([#2391](https://github.com/pouchdb/pouchdb/issues/2391), [#2392](https://github.com/pouchdb/pouchdb/issues/2392), [#2393](https://github.com/pouchdb/pouchdb/issues/2393)) - * MD5 hashes are now calculated incrementally in a way that won't freeze the DOM. ([#445](https://github.com/pouchdb/pouchdb/issues/445), [#2497](https://github.com/pouchdb/pouchdb/issues/2497)) - * More efficient replication. ([#2466](https://github.com/pouchdb/pouchdb/issues/2466), [#2475](https://github.com/pouchdb/pouchdb/issues/2475)) - - -### Bugfixes: - - * Fix for replication of multiple attachments. ([#2358](https://github.com/pouchdb/pouchdb/issues/2358)) - * Fix for `bulkDocs()` in Cloudant. ([#2365](https://github.com/pouchdb/pouchdb/issues/2365)) - * Fix read-only replication for CORS/40*. ([#2484](https://github.com/pouchdb/pouchdb/issues/2484)) - * Fix for reserved words in docs. ([#2477](https://github.com/pouchdb/pouchdb/issues/2477)) - * Fixes for `change` events in `.sync()`. ([#2555](https://github.com/pouchdb/pouchdb/issues/2555)) - * Fixes for race condition in bulk docs with `new_edits=false` in LevelDB. ([#2574](https://github.com/pouchdb/pouchdb/issues/2574)) - * Fixes for `opts.stale` in `query()`. ([pouchdb/mapreduce#196](https://github.com/pouchdb/mapreduce/issues/196), [pouchdb/mapreduce#198](https://github.com/pouchdb/mapreduce/issues/198)) - -###### [Complete list of changes](https://github.com/pouchdb/pouchdb/compare/2.2.3...3.0.0)
diff --git a/docs/_posts/2014-08-16-pouchdb-3.0.1.md b/docs/_posts/2014-08-16-pouchdb-3.0.1.md deleted file mode 100644 index 0e243e6..0000000 --- a/docs/_posts/2014-08-16-pouchdb-3.0.1.md +++ /dev/null
@@ -1,12 +0,0 @@ ---- -layout: post - -title: PouchDB 3.0.1 - -author: Nolan Lawson - ---- - -[PouchDB 3.0.1](https://github.com/pouchdb/pouchdb/releases/tag/3.0.1) is a patch release to fix a migration bug in PouchDB 3.0.0 ([#2456](https://github.com/pouchdb/pouchdb/issues/2456)). Please upgrade your existing users directly from 2.2.3 and do not use 3.0.0. - -This release also contains a small performance boost for `bulkDocs()` ([#2553](https://github.com/pouchdb/pouchdb/issues/2553)). \ No newline at end of file
diff --git a/docs/_posts/2014-08-20-pouchdb-3.0.2.md b/docs/_posts/2014-08-20-pouchdb-3.0.2.md deleted file mode 100644 index 946b372..0000000 --- a/docs/_posts/2014-08-20-pouchdb-3.0.2.md +++ /dev/null
@@ -1,16 +0,0 @@ ---- -layout: post - -title: PouchDB 3.0.2 - -author: Nolan Lawson - ---- - -[PouchDB 3.0.2](https://github.com/pouchdb/pouchdb/releases/tag/3.0.2) is another small patch release, this time to fix a bug in replication of deleted documents ([#2636](https://github.com/pouchdb/pouchdb/issues/2636)). - -Other fixes: - -* Ensure PouchDB stops writing after replication is over ([#2639](https://github.com/pouchdb/pouchdb/issues/2639)) -* Fix a race condition in LevelDB ([#2631](https://github.com/pouchdb/pouchdb/issues/2631)) -* Allow special URI characters in doc IDs ([#2651](https://github.com/pouchdb/pouchdb/issues/2651)) \ No newline at end of file
diff --git a/docs/_posts/2014-08-29-pouchdb-3.0.3.md b/docs/_posts/2014-08-29-pouchdb-3.0.3.md deleted file mode 100644 index 150cd39..0000000 --- a/docs/_posts/2014-08-29-pouchdb-3.0.3.md +++ /dev/null
@@ -1,32 +0,0 @@ ---- -layout: post - -title: PouchDB 3.0.3 - -author: Nolan Lawson - ---- - -Another week, another PouchDB patch release! - -This week we present [PouchDB 3.0.3](https://github.com/pouchdb/pouchdb/releases/tag/3.0.3), which fixes some ornery issues with replication that were introduced by recent performance optimizations ([#2685](https://github.com/pouchdb/pouchdb/issues/2685)). - -In fact, those performance optimizations have been rolled back. The current implementation appears to be the fastest possible given CouchDB's replication protocol, and the clever tricks introduced in 3.0.0 actually pushed conflicts into CouchDB's revision history, which is bad news for apps that rely on custom conflict resolution. (If you just use the default "pick a random winner," you probably didn't notice anything.) - -And although "custom conflict resolution" may only describe a minority of apps, we felt it's better to be correct 100% of the time than to be speedy. - -### Dealing with slow replication - -If you experience slow replications after upgrading to 3.0.3, here are some suggestions: - -1. Avoid CORS if you can, because it uses twice as many HTTP requests. Some tips for doing this: - * If you are using IrisCouch, you can [create a couchapp](https://github.com/couchapp/couchapp) (i.e. let CouchDB serve your HTML/CSS/JS). - * If you are running your own CouchDB, you can set up a reverse proxy with Apache or Nginx that allows you to serve your app and CouchDB from the same domain. Or create a couchapp. -2. Try using the "every doc is a delta" pattern, as described in [this blog post](http://atypical.net/archive/2014/04/17/understanding-race-induced-conflicts-in-bigcouch) and exemplified in [the delta-pouch plugin](https://github.com/redgeoff/delta-pouch). Your replications will be much faster, because PouchDB is able to use an optimization for generation-1 documents, and in this setup, every document is a generation-1 document. -3. Otherwise, just minimize the number of documents you create. Or minimize the number of documents you sync to the client. Views can be helpful with this, although the low performance of the `query()` API relative to the `allDocs()` API should be balanced with that. - -### Other fixes in 3.0.3 - -* Auto-compaction is no longer experimental! It's fully supported. ([#2655](https://github.com/pouchdb/pouchdb/issues/2655)) -* `'change'` listeners aren't called after replication is canceled. ([#2478](https://github.com/pouchdb/pouchdb/issues/2478)) -* Bower package is smaller. ([#2659](https://github.com/pouchdb/pouchdb/issues/2659)) \ No newline at end of file
diff --git a/docs/_posts/2014-09-04-pouchdb-3.0.4.md b/docs/_posts/2014-09-04-pouchdb-3.0.4.md deleted file mode 100644 index e24979e..0000000 --- a/docs/_posts/2014-09-04-pouchdb-3.0.4.md +++ /dev/null
@@ -1,24 +0,0 @@ ---- -layout: post - -title: PouchDB 3.0.4: Night of the Living Attachments - -author: Calvin Metcalf - ---- - -This week we present [PouchDB 3.0.4](https://github.com/pouchdb/pouchdb/releases/tag/3.0.4), which fixes a bunch of stuff with attachments. Now the kittens generated by the [3.0.0 release](http://pouchdb.com/2014/08/12/pouchdb-3.0.0.html) may be safely stored in Pouch. - -[](/static/img/kittens.jpg) - -### Attachmentspalooza - -- In Firefox, different attachments now (correctly) have different MD5 hashes. Previously they were just hashes of the string `'[Object] object'`. With this, we also now check that the hashes we produce are identical to the ones that CouchDB produces (with the exception of plaintext ones due to Erlang being weird and not having ASCII strings) ([#2698](https://github.com/pouchdb/pouchdb/issues/2698)). -- Weirdness in Chrome 37-39 with FileReader and empty blobs is now fixed ([#2713](https://github.com/pouchdb/pouchdb/issues/2713)). -- Fix for [a bug in Chrome 37](https://code.google.com/p/chromium/issues/detail?id=408120) relating to blobs in IndexedDB ([#2701](https://github.com/pouchdb/pouchdb/issues/2701)). -- HTTP pouches now support buffer/blob data in attachments ([#2577](https://github.com/pouchdb/pouchdb/issues/2577)). - -### Other fixes in 3.0.4 - -* When running sync, it only creates one instance for each database ([#2662](https://github.com/pouchdb/pouchdb/pull/2662)). -* Performance improvements for persisted map/reduce, and it also uses less space ([pouchdb/mapreduce#191](https://github.com/pouchdb/mapreduce/pull/191) and [pouchdb/mapreduce#185](https://github.com/pouchdb/mapreduce/issues/185)).
diff --git a/docs/_posts/2014-09-07-pouchdb-3.0.5.md b/docs/_posts/2014-09-07-pouchdb-3.0.5.md deleted file mode 100644 index 3134ac5..0000000 --- a/docs/_posts/2014-09-07-pouchdb-3.0.5.md +++ /dev/null
@@ -1,48 +0,0 @@ ---- -layout: post - -title: PouchDB 3.0.5: Turtles All the Way Down - -author: Nolan Lawson - ---- - -Tonight our fine dining selection is [PouchDB 3.0.5](https://github.com/pouchdb/pouchdb/releases/tag/3.0.5), which fixes some issues with excessive recursion and also `PouchDB.sync` not always working correctly. - -### PouchDB.sync un-borked ([#2735](https://github.com/pouchdb/pouchdb/issues/2735)) - -You can now call `PouchDB.sync('mydb', 'http://localhost:5984/mydb')` using just the database names. - -Less typing === more win. - -### No more infinite recursion ([#2543](https://github.com/pouchdb/pouchdb/issues/2543)) - -You can now have as many revisions to your documents as you want, and you'll no longer descend _Inception_-style into a "too much recursion" or "maximum call stack" error. - -We literally wrote [a custom JSON parser](https://github.com/nolanlawson/vuvuzela) to fix this. That's how much we love you. - -### Notes on excessive revision histories - -The ["infinite recursion" bug](https://github.com/pouchdb/pouchdb/issues/2543) shows up when you have many (> 1000) revisions to the same document. For instance, imagine a text editor that `put()`s a new version of the document for every keystroke. This is fine in traditional databases, but it can be a big problem in PouchDB/CouchDB, because we store the entire history of the database. - -Make no mistake: inifinitely-large revision histories will now work in PouchDB 3.0.5. However, it's a lot like riding a bicycle without a helmet: you _can_ do it, but you probably shouldn't. - -Your mental model for this can be something like Git. Imagine a new `git commit` for every keystroke, and you'll see why it might be a bit problematic. - -```js -{ "text": "The quick brown fox jumps over the lazy doge." } -{ "text": "The quick brown fox jumps over the lazy doge" } -{ "text": "The quick brown fox jumps over the lazy dog" } -// -// 40 revisions earlier ... -// -{ "text": "The q" } -{ "text": "The " } -{ "text": "The" } -{ "text": "Th" } -{ "text": "T" } -``` - -Of course, you can always `compact()` to remove old versions, but this just removes the document data. PouchDB still needs to maintain a permanent tree of the `_rev` hashes in order for the replication algorithm to work properly. If this tree grows excessively, it can bloat your database, whether or not you do compaction. - -What this means is that you should be very careful about updating your documents. Try to update your documents in larger batches, or use a pattern like [delta-pouch](https://github.com/redgeoff/delta-pouch) to avoid creating new revisions altogether. \ No newline at end of file
diff --git a/docs/_posts/2014-09-22-3.0.6.md b/docs/_posts/2014-09-22-3.0.6.md deleted file mode 100644 index 7ae03e1..0000000 --- a/docs/_posts/2014-09-22-3.0.6.md +++ /dev/null
@@ -1,53 +0,0 @@ ---- -layout: post - -title: PouchDB 3.0.6: Safari Madness - -author: Nolan Lawson - ---- - -As Cupertino fans snuggle up to their bigger and better iDevices, PouchDB users will appreciate [PouchDB 3.0.6](https://github.com/pouchdb/pouchdb/releases/tag/3.0.6). This release contains a workaround for [some unforeseen hiccups](https://github.com/pouchdb/pouchdb/issues/2533) in Apple's new implementation of IndexedDB for Safari 7.1 and iOS 8. - -<img alt="Apple introduces IndexedDB support" src="/static/img/apple-indexeddb.png" style="max-width:700px;"/> - -All joking aside, we are happy to welcome Apple to the IndexedDB party (better late than never!), and [we are working with the WebKit devs](https://bugs.webkit.org/show_bug.cgi?id=136888) to resolve the issue. In the meantime, PouchDB 3.0.6 provides a workaround where we fall back to Web SQL on Apple browsers. - -Other fixes in this release: ------- - -* `db.compact()` performance improvements ([#2623](https://github.com/pouchdb/pouchdb/pull/2623)) -* Ensure attachments work after Chrome 38 upgrade ([#2773](https://github.com/pouchdb/pouchdb/issues/2773)) -* Invalid/unauthorized documents no longer halt replication ([#2268](https://github.com/pouchdb/pouchdb/issues/2268)) -* Filtering no longer halts replication ([#2689](https://github.com/pouchdb/pouchdb/issues/2689)) -* Update lie dependency to [2.8.0](https://github.com/calvinmetcalf/lie/releases/tag/2.8.0) - -New features in this release: --------- - -* `db.info()` shows whether `auto_compaction` is set ([#2744](https://github.com/pouchdb/pouchdb/issues/2744)) - -An aside on browser compatibility --------- - -From the get-go, PouchDB's goal was to work seamlessly on every browser, with one API to rule them all. I like to call it the "jQuery for databases" approach. - -In practice, this is pretty tough to achieve. I poke fun at Apple, but there are also bugs in IE's implementation of IndexedDB ([here](https://connect.microsoft.com/IE/feedbackdetail/view/866495) [are](https://connect.microsoft.com/IE/feedbackdetail/view/866489) [three](https://connect.microsoft.com/IE/feedbackdetail/view/866474)), Firefox's implementation ([this one](https://bugzilla.mozilla.org/show_bug.cgi?id=701634)), and Chrome's implementation ([these](https://code.google.com/p/chromium/issues/detail?id=408120) [two](https://code.google.com/p/chromium/issues/detail?id=108012)). Additionally, some Android devices ship with [an outdated version of IndexedDB](https://github.com/pouchdb/pouchdb/issues/1207) in the notoriously non-evergreen "stock" browser. - -And that's just IndexedDB! Don't even get me started on Web SQL. Here's just a small taste: - - * [UTF-8 vs UTF-16 encoding on Chrome vs Safari](https://github.com/pouchdb/pouchdb/pull/1733#issuecomment-38723096) - * [Null character causes string truncation](https://github.com/pouchdb/pouchdb/pull/1731#issuecomment-38622342) - * [Cannot use Promises, or the transaction ends early](https://github.com/pouchdb/pouchdb/pull/2536#issuecomment-50435837) - -We've written workarounds for all these issues in PouchDB, so that you, dear developer, need never worry your pretty head about them. - -So this new Safari/iOS bug doesn't phase us. If we were keeping score, this would probably be workaround #72 by now. We're used to it. - -However, that doesn't mean we should get complacent. All of these bugs are opportunities to hold browser vendors' feet to the fire, so that eventually the hacks and workarounds are no longer necessary. You don't want to have to download 10KB of workarounds just to use the native HTML5 APIs. And nobody wants to see HTML5 sink under the weight of browser quirks and non-compliance. - -We look forward to removing most of these workarounds from PouchDB (including Web SQL support!), so making some noise in the Microsoft/Mozilla/Chromium/WebKit bug trackers is a great way to get there. Submitting test cases and pull requests is even better. - -Thanks to [Elmer Bulthuis](https://github.com/elmerbulthuis) and [Kyaw Tun](https://github.com/yathit) for finding reproducible test cases to submit to the WebKit devs. Let's move the web forward! - -And as always, thanks to [our new and existing contributors](https://github.com/pouchdb/pouchdb/graphs/contributors).
diff --git a/docs/_posts/2014-10-26-10-things-i-learned-from-reading-and-writing-the-pouchdb-source.md b/docs/_posts/2014-10-26-10-things-i-learned-from-reading-and-writing-the-pouchdb-source.md deleted file mode 100644 index f12a2bd..0000000 --- a/docs/_posts/2014-10-26-10-things-i-learned-from-reading-and-writing-the-pouchdb-source.md +++ /dev/null
@@ -1,412 +0,0 @@ ---- -layout: post - -title: 10 things I learned from reading (and writing) the PouchDB source - -author: Nolan Lawson - ---- - -In the spirit of [Paul Irish](http://www.paulirish.com/2010/10-things-i-learned-from-the-jquery-source/), here's a list of some surprising things I learned while reading (and writing) the PouchDB source code. - -To set the stage: I first joined the project around December of last year, at which point PouchDB was already fairly mature. (The [first commit from Mikeal Rodgers](https://github.com/pouchdb/pouchdb/commit/d600081962d3f54b410e5cfcf78cd413ad94abb9) is already 4 years old!) My own background was mostly in Android development, but I had some knowledge of Web SQL thanks to [a PhoneGap app](http://www.kaahe.org/app/support_en.html) I had worked on. - -The main goals I had with PouchDB were to increase its performance and browser compatibility. And having dealt with that ugly F-word that haunts the Android ecosystem ("fragmentation"), I figured compatibility in the web dev world couldn't be much worse. Could it? - -**Warning: graphic content ahead.** If you've ever been a soldier on the front lines of the browser compatibility war, the following may make you relive some of those past horrors. Be prepared to weep. - -Also, if you're not familiar with [LocalStorage](http://www.w3.org/TR/webstorage/), [Web SQL](http://www.w3.org/TR/webdatabase/), or [IndexedDB](http://www.w3.org/TR/IndexedDB/), you may want to read up on those first. - -### 1. Nobody can agree on what the Web SQL "estimated size" means - -When you open a Web SQL database, you use [openDatabase()](http://www.w3.org/TR/webdatabase/#dom-opendatabase), e.g.: - -```js -var db = openDatabase('documents', '1.0', 'some description', 5000000); -``` - -That last parameter is the so-called *estimated size*. And [here's](https://github.com/pouchdb/pouchdb/blob/c32597564160dcaad7b3e715ddf1c0dc923b59cd/lib/adapters/websql.js#L118-L132) how we set it in PouchDB: - -```js -function getSize(opts) { - /* ... */ - var isAndroid = /Android/.test(window.navigator.userAgent); - return isAndroid ? 5000000 : 1; -} -``` - -User agent sniffing! Yes, we should be ashamed of ourselves. But here's why we do it: - -* In modern **Chrome** and **Android 4.4+**, the size is simply ignored. The browser calculates the remaining size on disk and sets a limit based on that. -* Aha, but in **Android < 4.4**, this is actually a hard limit! So if you ask for 5000000, you'll only ever get 5 MB. -* Oh, but in **Safari/iOS**, it gets trickier. If you ask for > 5000000, then it will show an [annoying popup](http://pouchdb.com/errors.html#not_enough_space) when the app is first loaded, which is a great way to spook your users. But if you ask for less, then there's another popup when the database reaches 5MB, and beyond that there's a bug in iOS 7.1 where the browser will no longer show any more popups, so you're forever capped at 10MB. To store more than 10MB, you need to ask for more than 10MB up-front. -* Additionally, if you specify anywhere between 0 and 5000000, Safari and iOS will use that size as a hint for when, precisely, to show the popup. And in the case of PouchDB, we need to avoid the popup in our automated tests, because Selenium doesn't give us a way to press the "OK" button, meaning our tests would just fail if we request too much. So the ideal size to request is 0. -* However, in **PhantomJS** and older WebKit (Safari ~5), if you request 0, then it will blow up. - -For the recored, here's what the dreaded Safari popup looks like: - -<img src='/static/img/safari_popup.png' alt='annoying Safari popup'/> - -So that's why we sniff for Android and only bump the size to 5000000 in those cases. In all other cases, we set it to 1. - -Additionally, the W3C has done everyone a disservice by using `5*1024*1024` in [their sample code](http://www.w3.org/TR/webdatabase/#introduction), because this has no relation to the 5MB limit in iOS/Safari. The actual cutoff to avoid the popup is 5000000 (i.e. 5 megabytes, aka 5MB), not `5*1024*1024` (5 *mebibytes*, aka 5MiB). And yet, if you read blog posts and Stack Overflow comments about Web SQL, you'll see the mistaken `1024*1024` repeated all over the place. - - -### 2. IE has race conditions in IndexedDB - -Microsoft has a very fast implementation of IndexedDB – it's a bit slower than Chrome's, but much faster than Firefox's ([here are some tests](https://gist.github.com/nolanlawson/11100235)). However, to get that speed, they must have taken some shortcuts, because both IE10 and IE11 have some [nasty](https://connect.microsoft.com/IE/feedbackdetail/view/1009247) [race](https://connect.microsoft.com/IE/feedbackdetail/view/866489) [conditions](https://connect.microsoft.com/IE/feedbackdetail/view/866495). - -Due to that, you'll often see PouchDB code [like this](https://github.com/pouchdb/pouchdb/blob/c32597564160dcaad7b3e715ddf1c0dc923b59cd/lib/adapters/idb.js#L1369-L1372): - -```js -//Close open request for "name" database to fix ie delay. -if (IdbPouch.openReqList[name] && IdbPouch.openReqList[name].result) { - IdbPouch.openReqList[name].result.close(); -} -``` - -Or code [like this](https://github.com/pouchdb/pouchdb/blob/c32597564160dcaad7b3e715ddf1c0dc923b59cd/lib/adapters/idb.js#L1390-L1398), where we ensure all "open" and "destroy" operations on the databases are done sequentially: - -```js -taskQueue.queue.push({ - action: function (thisCallback) { - destroy(name, opts, thisCallback); - }, - callback: callback -}); -``` - -Or code [like this](https://github.com/pouchdb/pouchdb/blob/c32597564160dcaad7b3e715ddf1c0dc923b59cd/lib/adapters/idb.js#L1215-L1226), where we keep a cache of all databases by name, since IE will not allow us to open two databases with the same name at the same time: - -```js -var cached = cachedDBs[name]; - -if (cached) { - idb = cached.idb; - /* ... */ -} -``` - -To their credit, though, the IE team has been [very responsive](https://twitter.com/jacobrossi/status/525715434838827009) to our bug reports, so this might be fixed soon. - - -### 3. Binary data in Web SQL is a mess - -At the time the Web SQL spec was hammered out, nothing like [Blobs](https://developer.mozilla.org/en-US/docs/Web/API/Blob) or [ArrayBuffers](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer) had been standardized. SQLite of course has support for the [binary BLOB type](https://www.sqlite.org/datatype3.html), but in order to store binary data in WebSQL, you need to do it the old-fashioned way, and pass in a JavaScript binary string. - -This produces two interesting problems: - -* There is a bug in both [WebKit](https://bugs.webkit.org/show_bug.cgi?id=137637) and [Chromium](https://code.google.com/p/chromium/issues/detail?id=422690), where the `\u0000` character is treated as a null terminator, and although you can insert and sort on the full string, when you retrieve it, it will be truncated. And since BLOBs must be inserted as binary strings, this means *any binary data containing the 0 byte will be truncated*. The only workaround is to use `SELECT HEX(columnName)`, which returns the full binary data in hexadecimal format. -* However, `HEX()` presents its own problems, because Safari < 7.1 and iOS < 8 [coerce all strings to UTF-16](https://github.com/pouchdb/pouchdb/pull/1733#issuecomment-38723096), meaning that the hexadecimal format must be parsed differently in UTF-8 browsers (Chrome/Opera/Android as well as modern Safari/iOS) vs. UTF-16 browsers (early Safari/iOS). - -Thus you will see fun code [like this](https://github.com/pouchdb/pouchdb/blob/c32597564160dcaad7b3e715ddf1c0dc923b59cd/lib/adapters/websql.js#L89-L101): - -```js -function parseHexString(str, encoding) { - var result = ''; - var charWidth = encoding === 'UTF-8' ? 2 : 4; - for (var i = 0, len = str.length; i < len; i += charWidth) { - var substring = str.substring(i, i + charWidth); - if (charWidth === 4) { // UTF-16, twiddle the bits - substring = substring.substring(2, 4) + substring.substring(0, 2); - } - result += String.fromCharCode(parseInt(substring, 16)); - } - result = encoding === 'UTF-8' ? decodeUtf8(result) : result; - return result; -} -``` - -(That "twiddle the bits" comment is a bit inaccurate; the technical term is, of course, [nibble-swizzling](http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1/com/android/internal/telephony/IccUtils.java#IccUtils.bcdToString%28byte%5B%5D%2Cint%2Cint%29). In the future we will correct this gross oversight by finding some way to work the word "swizzle" into the source code.) - -You'll also see us detect UTF-8 vs. UTF-16 encoding [like this](https://github.com/pouchdb/pouchdb/blob/c32597564160dcaad7b3e715ddf1c0dc923b59cd/lib/adapters/websql.js#L306-L315): - -```js -function checkDbEncoding(tx) { - // check db encoding - utf-8 (chrome, opera) or utf-16 (safari)? - tx.executeSql('SELECT dbid, hex(dbid) AS hexId FROM ' + META_STORE, [], - function (tx, result) { - var id = result.rows.item(0).dbid; - var hexId = result.rows.item(0).hexId; - encoding = (hexId.length === id.length * 2) ? 'UTF-8' : 'UTF-16'; - } - ); -} -``` - -In this code, we know based on the length of the hexadecimal string returned whether the database is UTF-16 or not. So thankfully, because it's feature-detected, this "just works" in Safari 7.1+ and iOS 8+. - -As of PouchDB 3.1.0, we will also [avoid hexing entirely](https://github.com/pouchdb/pouchdb/pull/2900) for large binary attachments, because it causes performance problems. The new workaround will be to just remove `\u0000` characters while preserving enough information to put them back in later. - - -### 4. Binary data in IndexedDB is a mess too - -IndexedDB, as Web SQL's younger, hipper sibling, is supposed to have native support for Blob objects. In practice, though, Blobs [were not supported in Chrome until v37](https://code.google.com/p/chromium/issues/detail?id=108012), and assuming Apple fixes [the more fundamental problems in IndexedDB](http://www.raymondcamden.com/2014/9/25/IndexedDB-on-iOS-8--Broken-Bad), they also apparently [will not support them](http://html5test.com/s/9b895f1cfb68b0d5.html). - -In those cases, PouchDB falls back to storing Blobs as base64-encoded strings. And we use [feature detection to test it](https://github.com/pouchdb/pouchdb/blob/c32597564160dcaad7b3e715ddf1c0dc923b59cd/lib/adapters/idb.js#L1303-L1344): - -```js -try { - var blob = utils.createBlob([''], {type: 'image/png'}); - txn.objectStore(DETECT_BLOB_SUPPORT_STORE).put(blob, 'key'); - txn.oncomplete = function () { - /* ... */ - blobSupport = true; - /* ... */ - }; -} catch (err) { - blobSupport = false; - /* ... */ -} -``` - -Ah, but if only it were so easy! It turns out that Chrome v37 also [implemented Blob support incorrectly](https://code.google.com/p/chromium/issues/detail?id=408120), returning the wrong MIME type when you fetch it. So in Chrome v37, we need to detect the broken blob support, whereas in v38 we can finally start treating it like the other browsers: - -```js -var storedBlob = e.target.result; -var url = URL.createObjectURL(storedBlob); -utils.ajax({ - url: url, - cache: true, - binary: true -}, function (err, res) { - if (err && err.status === 405) { - // firefox won't let us do that. but firefox doesn't - // have the blob type bug that Chrome does, so that's ok - blobSupport = true; - } else { - blobSupport = !!(res && res.type === 'image/png'); - } -}); -``` - -And yes, Firefox has [a tiny bug here](https://bugzilla.mozilla.org/show_bug.cgi?id=1081668) as well! Luckily, it's fixed in the nightly build. - -So for those keeping score, PouchDB has three different strategies for each of Chrome v36, v37, and v38. And since Android represents different versions of Chromium frozen in amber, all three variations will be out there in the wild for the near future. - - -### 5. IE doesn't support complex keys - -CouchDB is one of the grandaddies of NoSQL databases, so unsurprisingly it influenced IndexedDB's design. One of the more useful but tricky features of CouchDB is *complex keys*, [best described by Christopher Lenz](https://connect.microsoft.com/IE/feedbackdetail/view/866474): - -> Obvious to Damien [Katz, creator of CouchDB], but not at all obvious to the rest of us: it's fairly simple to make a view that includes both the content of the blog post document, and the content of all the comments associated with that post. The way you do that is by using *complex keys*. Until now we've been using simple string values for the view keys, but in fact they can be arbitrary JSON values, so let's make some use of that: - - -The example given is: - -```js -function(doc) { - if (doc.type == "post") { - map([doc._id, 0], doc); - } else if (doc.type == "comment") { - map([doc.post, 1], doc); - } -} -``` - -See that? The key is actually an array containing a string and an integer, meaning it would sort first by the string, then by the integer. Cool, right? - -This feature [is in the IndexedDB spec](http://www.w3.org/TR/IndexedDB/#key-construct), and would be a great fit for PouchDB, since we're basically trying to rewrite CouchDB on top of IndexedDB. However, in the source code you will see [pseudo-complex keys like this](https://github.com/pouchdb/pouchdb/blob/c32597564160dcaad7b3e715ddf1c0dc923b59cd/lib/adapters/idb.js#L512-L514): - -```js -docInfo.data._doc_id_rev = docInfo.data._id + "::" + docInfo.data._rev; -var seqStore = txn.objectStore(BY_SEQ_STORE); -var index = seqStore.index('_doc_id_rev'); -``` - -Leading to [gnarly queries like this](https://github.com/pouchdb/pouchdb/blob/c32597564160dcaad7b3e715ddf1c0dc923b59cd/lib/adapters/idb.js#L174-L179): - -```js -var start = docId + "::"; -var end = docId + "::~"; -var index = seqStore.index('_doc_id_rev'); -var range = global.IDBKeyRange.bound(start, end, false, false); -var seqCursor = index.openCursor(range); -``` - -Did we mess up? Nope, it's intentional: we concatenate the strings together, because [IE does not support complex keys](https://connect.microsoft.com/IE/feedbackdetail/view/866474). - -This also heavily influenced our design for [persistent map/reduce](http://pouchdb.com/2014/05/01/secondary-indexes-have-landed-in-pouchdb.html), because instead of assuming the underlying database can sort by more than one value, we invented [a toIndexableString() function](https://github.com/pouchdb/collate/blob/0e22e6e833e24ee5d677d73df2620c20b58aba1f/lib/index.js#L116-L165) that converts any JSON object into a big CouchDB-collation-ordered string. Yeah, we went there. - - -### 6. IndexedDB throws an error if you try to iterate backwards with start/end keys - -This is one of those wonderful "bugs" that is actually part of the IndexedDB spec, so it's faithfully reproduced in all three of Firefox, IE, and Chrome. I guess we should be thankful? - -Anyway, [here's the code](https://github.com/pouchdb/pouchdb/blob/c32597564160dcaad7b3e715ddf1c0dc923b59cd/lib/adapters/idb.js#L746-L776): - -```js -try { - if (start && end) { - keyRange = global.IDBKeyRange.bound(start, end, false, !inclusiveEnd); - } else if (start) { - /* ... */ - } -} catch (e) { - if (e.name === "DataError" && e.code === 0) { - // data error, start is less than end - return callback(null, { - total_rows : totalRows, - offset : opts.skip, - rows : [] - }); - } else { - return callback(errors.error(errors.IDB_ERROR, e.name, e.message)); - } -} -``` - -In IndexedDB, an error will be thrown for any `IDBKeyRange` where the start is greater than the end, even if you're iterating backwards. We work around this by [manually checking for the end key](https://github.com/pouchdb/pouchdb/blob/c32597564160dcaad7b3e715ddf1c0dc923b59cd/lib/adapters/idb.js#L832-L838): - -```js -if (manualDescEnd) { - if (inclusiveEnd && doc.key < manualDescEnd) { - return; - } else if (!inclusiveEnd && doc.key <= manualDescEnd) { - return; - } -} -``` - -Luckily, this doesn't really have a big performance impact, except that we fetch one more key than necessary. - -### 7. IndexedDB and Web SQL are jealous of other callbacks - -In both IndexedDB and Web SQL, you can forget about using [Promises](https://promisesaplus.com/) or even invoking another callback within a transaction. Whenever control is returned to the event loop, [the transaction auto-closes](https://twitter.com/nolanlawson/status/515893338474831872). - -So although your own PouchDB-using code can be elegant and Promisey (thanks especially to Calvin Metcalf's work on [lie](https://github.com/calvinmetcalf/lie)), under the hood, PouchDB's own code is pure callback hell. - -Here's a taste of [our IndexedDB code](https://github.com/pouchdb/pouchdb/blob/c32597564160dcaad7b3e715ddf1c0dc923b59cd/lib/adapters/idb.js#L209-L635) and [our WebSQL code](https://github.com/pouchdb/pouchdb/blob/c32597564160dcaad7b3e715ddf1c0dc923b59cd/lib/adapters/websql.js#L456-L899). We party like it's 2009, because you'll see lots of callback patterns like this: - -```js -verifyAttachments(function (err) { - if (err) { - return callback(err); - } - /* ... */ -}); -``` - -Or this wannabe `Promise.all()`: - -```js -function checkDoneWritingDocs() { - if (++numDocsWritten === docInfos.length) { - complete(); - } -} -``` - -And if we need to use some other callback API, such as [FileReader](https://developer.mozilla.org/en-US/docs/Web/API/FileReader), we need to be careful to do it outside of the transaction. Hence you'll see functions like [preprocessAttachments()](https://github.com/pouchdb/pouchdb/blob/c32597564160dcaad7b3e715ddf1c0dc923b59cd/lib/adapters/websql.js#L886-L898): - -```js -preprocessAttachments(function () { - db.transaction(function (txn) { - /* ... */ - }); -}); -``` - -Suffice it to say, if we didn't have extensive integration tests, we'd barely be sure the code worked at all. - -### 8. Recursion is a double-edged sword - -Consider [this code](https://github.com/pouchdb/pouchdb/blob/c32597564160dcaad7b3e715ddf1c0dc923b59cd/lib/adapters/idb.js#L45-L58): - -```js -// Unfortunately, the metadata has to be stringified -// when it is put into the database, because otherwise -// IndexedDB can throw errors for deeply-nested objects. -// Originally we just used JSON.parse/JSON.stringify; now -// we use this custom vuvuzela library that avoids recursion. -// If we could do it all over again, we'd probably use a -// format for the revision trees other than JSON. -function encodeMetadata(metadata, winningRev, deleted) { - var storedObject = {data: vuvuzela.stringify(metadata)}; - storedObject.winningRev = winningRev; - storedObject.deletedOrLocal = deleted ? '1' : '0'; - storedObject.id = metadata.id; - return storedObject; -} -``` - -As it turns out, this is [a very tricky bug](https://github.com/pouchdb/pouchdb/issues/2543) that ended up affecting all browsers, and even Node.js. - -The gist is that any native JavaScript function that takes an object as input, such as `JSON.stringify()` or IndexedDB's `put()`, has a maximum limit on the depth of the object you can pass in. By depth I mean: - -```js -var object = { - enhance: { - enhance: { - enhance: { - /* and so on */ - } - } - } -}; -``` - -The limit itself will vary based on the available memory, but in any case, if you hit that limit, you get a "too much recursion" or "maximum call stack" error. As well as an unhappy PouchDB user. - -Calvin and I solved this by writing [a non-recursive JSON library with a silly name](https://github.com/nolanlawson/vuvuzela). It's slower than the native methods, but in cases where we can't afford to have a crash, this code turned out to be a lifesaver. - -### 9. In IndexedDB, unique indexes throw constraint errors, but keyPaths don't - -This is one of those counter-intuitive things that probably made sense to IndexedDB creator [Nikunj Mehta](http://blog.o-micron.com/), but surprised the hell out of me. - -In SQLite and Web SQL, you can create a table with a primary key: - -```sql -CREATE TABLE employees (id PRIMARY KEY UNIQUE, name); -``` - -And you can also add a unique index: - -```sql -CREATE TABLE employees (id, name); -CREATE UNIQUE INDEX id_index ON employees (id); -``` - -And these two are essentially equivalent, because if you try to `INSERT` a row with an `id` that already exists, you'll get a constraint error. - -In IndexedDB, however, object stores with primary keys will *not* throw an error upon insertion, but instead silently overwrite the existing object. In other words, the `put()` is an [upsert](http://en.wiktionary.org/wiki/upsert). Unique indexes, however, behave totally differently and will indeed throw. - -Here's [a live example](http://bl.ocks.org/nolanlawson/1afe3b5e98e4111c67c4). The big takeaway is that the following two examples are *not* equivalent: - -With a primary key: - -```js -db.createObjectStore('employees', {keyPath : 'id'}); -``` - -With a unique index: - -```js -db.createObjectStore('employees').createIndex('id', 'id', {unique: true}); -``` - -Better hope you choose the right one the first time! Otherwise you may get a constraint error when you don't expect one, or vice versa. - -**Edit:** As pointed out by [Simon Friis Vindum](https://twitter.com/paldepind/status/539012069061033984), you can use `add()` instead of `put()` to get a constraint error with keyPaths. Here's [a live example](http://bl.ocks.org/nolanlawson/c9a4673830de2b185b8b). Thanks for the tip! - -### 10. CouchDB influenced IndexedDB influenced LevelDB influenced... - -Databases are not designed in a vacuum, and the more I learn about this stuff, the more I find that everything is related somehow. - -Web SQL was originally inspired by [Google Gears](http://gearsblog.blogspot.com/2011/03/stopping-gears.html), which in 2008 [was poised](https://code.google.com/p/gears/wiki/GearsHistory) to become the standard for storing data in mobile webapps. And of course neither would have been possible without SQLite, which, according to creator Richard Hipp, [was heavily influenced](http://use-the-index-luke.com/blog/2014-05/what-i-learned-about-sqlite-at-a-postgresql-conference) by PostgreSQL. In fact, I find [his presentation](http://www.pgcon.org/2014/schedule/attachments/319_PGCon2014OpeningKeynote.pdf) especially inspiring, because Hipp's process of using Postgres as a gold standard for building SQLite reminds me a lot of how PouchDB has been molded in CouchDB's image. - -And although [the Web SQL spec was eventually abandoned](http://nolanlawson.com/2014/04/26/web-sql-database-in-memoriam/), it certainly influenced its younger sibling IndexedDB. Among other family traits, they share the same asynchronous structure, auto-closing transactions, and security models. (Compare the "security" sections for [both](http://www.w3.org/TR/webdatabase/) [specs](http://www.w3.org/TR/IndexedDB/), and note how much of the language is simply copied over). - -Web SQL also lives on indirectly in IndexedDB, given that both [Mozilla's](https://hacks.mozilla.org/2010/06/beyond-html5-database-apis-and-the-road-to-indexeddb/) and [Apple's](https://bugs.webkit.org/show_bug.cgi?id=132176) implementations are independently (!) implemented on top of SQLite. - -What's more intriguing is that you can even find [the influence of CouchDB](http://lists.w3.org/Archives/Public/public-webapps/2009AprJun/0106.html) in early discussions of IndexedDB. This might explain features like complex keys, start/end key iteration, and the document-esque data model. Nikunj Mehta [even said way back in 2009](http://t.co/9N6O9qkn4S): - -> Some people find [IndexedDB] good for a JavaScript CouchDB. - -In a sense, this statement may be the earliest expression of what eventually became PouchDB! - -Furthermore, Google went on to create LevelDB as their implementation of the IndexedDB spec, which is currently enjoying [enormous popularity in the Node.js ecosystem](http://dailyjs.com/2013/04/19/leveldb-and-node-1/), especially thanks to [the LevelUP project](https://github.com/rvagg/node-levelup). PouchDB itself [has hopped on the LevelUP bandwagon](http://pouchdb.com/2014/07/25/pouchdb-levels-up.html), and today we have PouchDB Server, which is a nearly-complete implementation of CouchDB's HTTP API, but based on Node.js and LevelDB. - -So from the earliest discussions of IndexedDB, influenced as it was by CouchDB and Web SQL, through LevelDB and the LevelUP ecosystem, we now have a database that unites them all: PouchDB. - -When I look through the PouchDB source code, this enormous accomplishment still gives me chills. It's enough to make you overlook all the odd hacks, workarounds, and inelegancies. The fact that PouchDB works at all is a tiny miracle.
diff --git a/docs/_posts/2014-11-10-3.1.0.md b/docs/_posts/2014-11-10-3.1.0.md deleted file mode 100644 index 4e9c0d7..0000000 --- a/docs/_posts/2014-11-10-3.1.0.md +++ /dev/null
@@ -1,51 +0,0 @@ ---- -layout: post - -title: PouchDB 3.1.0: A Guide to Recognizing Your Marsupials (The PouchDB Guide) - -author: Dale Harvey - ---- - -Today marks the dawn of a new PouchDB release, [3.1.0](https://github.com/pouchdb/pouchdb/releases/tag/3.1.0) is released today with a whole bunch of goodness. Here are some of the highlights: - -{% include alert_start.html variant="warning"%} -This release includes a migration. Your existing database will be updated automatically, but you cannot downgrade to a previous version of PouchDB once you've upgraded. -{% include alert_end.html %} - -### PouchDB Guides ([#2766](https://github.com/pouchdb/pouchdb/issues/2766)) - -Nolan Lawson and Nick Colley worked together to produce some excellent guides to PouchDB which you can see @ [http://pouchdb.com/guides/](http://pouchdb.com/guides/). They cover a lot of the issues surrounding building PouchDB applications including conflicts and promises vs callbacks. As a bonus the guides as well as the rest of the website [now work offline](https://github.com/pouchdb/pouchdb/issues/2957). - -### Compaction removes orphaned attachments ([#2818](https://github.com/pouchdb/pouchdb/issues/2818)) - -If you have been using attachments in your PouchDB databases, you may have noticed that it was a bit bigger round the waist than it should have been. We now work harder to ensure there isnt any extra things lying around the database taking up space that you no longer need. This change came along with a lot of compaction and attachment related fixes: [#2890](https://github.com/pouchdb/pouchdb/issues/2890), [#2905](https://github.com/pouchdb/pouchdb/issues/2905), [#2951](https://github.com/pouchdb/pouchdb/issues/2951) - -### Test against CouchDB master ([#2850](https://github.com/pouchdb/pouchdb/issues/2850)) - -There is a big change brewing in CouchDB world, [https://issues.apache.org/jira/browse/COUCHDB-1843](https://issues.apache.org/jira/browse/COUCHDB-1843) is in progress to merge the clustered 'BigCouch' merge from Cloudant into CouchDB master. This will represent a big change towards CouchDB however there is no need to worry, we now run all of our tests against the current master CouchDB (and they are all green!) so when the big CouchDB 2.0 release comes, your PouchDB applications will continue to work as well as before. - -### In related news - -We keep a list of [plugins and related external projects](http://pouchdb.com/external.html) to PouchDB, here are a few new ones we added during this month: - - * PouchDB [Dump](https://github.com/nolanlawson/pouchdb-dump-cli) and [Load](https://github.com/nolanlawson/pouchdb-load) are designed to help you load data into your newly started PouchDB app faster than replication will do currently. - * If you want to use PouchDB with Angular, you are in luck, there are now 4! adapters to help you integrate them: [angular-pouchdb](https://github.com/wspringer/angular-pouchdb), [Factoryng](https://github.com/redgeoff/factoryng), [ngPouch](https://github.com/jrhicks/ngPouch), [ng-pouchdb](https://github.com/danielzen/ng-pouchdb). - * Ember users arent left in the wild: [ember-pouchdb](https://github.com/taras/ember-pouchdb) should get you going with PouchDB and Ember. - * If you are using Blobs with PouchDB, you probably want to take a look at [blob-util](https://github.com/nolanlawson/blob-util). - -### Bug fixes Galore - -Some of the other important fixes include: - - * ([#2951](https://github.com/pouchdb/pouchdb/issues/2951)) - fix concurrency in leveldb.js - * ([#2935](https://github.com/pouchdb/pouchdb/issues/2935)) - new_edits=false works regardless of order - * ([#2867](https://github.com/pouchdb/pouchdb/issues/2867)) - do not stack notify change listeners - * ([#2779](https://github.com/pouchdb/pouchdb/issues/2779)) - fix undeletion with wrong rev - * ([#2794](https://github.com/pouchdb/pouchdb/issues/2794)) - explain normal 404s in console.info - * ([#2841](https://github.com/pouchdb/pouchdb/issues/2841)) - respect options when making dependent dbs - * ([#2844](https://github.com/pouchdb/pouchdb/issues/2844)) - Encode attachment names - * ([#2807](https://github.com/pouchdb/pouchdb/issues/2807)) - auto_compaction properly trims tree - * ([#2708](https://github.com/pouchdb/pouchdb/issues/2708)) - implement attachment stub length - -Please [file issues](https://github.com/pouchdb/pouchdb/issues) or [tell us what you think](https://github.com/pouchdb/pouchdb/blob/master/CONTRIBUTING.md#get-in-touch). We would also like to give a huge thanks to our [new and existing contributors](https://github.com/pouchdb/pouchdb/graphs/contributors).
diff --git a/docs/_posts/2014-11-27-testing-pouchdb.md b/docs/_posts/2014-11-27-testing-pouchdb.md deleted file mode 100644 index 95306a3..0000000 --- a/docs/_posts/2014-11-27-testing-pouchdb.md +++ /dev/null
@@ -1,66 +0,0 @@ ---- -layout: post - -title: How we test PouchDB - -author: Dale Harvey - ---- - -While working on and researching improvements for automated testing in PouchDB, I found a lack of blog posts and general information about how open-source libraries test themselves. With PouchDB, a huge amount of effort has gone into testing, but we haven't talked about it much outside the project. So I wanted to explain a little about our approach. - -### How do we test PouchDB? - -Every pull request and check-in to the PouchDB repository goes through the following test run: - -<a href="https://travis-ci.org/pouchdb/pouchdb/builds/40528881"><img src='/static/img/travis-screenshot.png' title='Travis Passing Screenshot' alt='Travis Passing Screenshot' style='width:100%'/></a> - -This combination of tests takes around 6 hours running time and covers the minimal options we have found to be confident in not introducing regressions. We test PouchDB against plain CouchDB 1.6.0 on the most popular modern browsers and Node.js, as well as testing alternative backends, servers and options (LocalStorage, PouchDB Server, auto-compaction, etc.). Ideally we would run a full matrix of configurations, however we are hitting the upper limit on how long our tests take to run, so we have picked the ones most likely to surface regressions. - -### Why care? - -Hopefully I don't need to espouse most of the virtues of testing; things that change and aren't tested are usually broken. PouchDB is fairly complex, so we rely on a comprehensive test suite, primarily to ensure we don't introduce regressions as we work on the code. - -With PouchDB, however, I have found an added benefit is enabling contributors. By improving our test infrastructure, we make it easier for contributors to have a clear process for verifying behaviour as bugs, writing a failing test and then confirming a fix. - -Being confident in your test suite's ability to catch regressions enables us to accept contributions in a reasonable time frame. If we are ever unsure of whether a contribution may break a particular feature, then we use that as an indication to improve the tests in that area, not as a reason to avoid merging the contribution. - -### Test library - -We use [Mocha](http://mochajs.org/) to write almost all of our tests. Mocha has become pretty much the de-facto library for testing JavaScript, and it has worked really well for us. - -If I had one complaint about Mocha, it would be I often find myself seeing `does not equal [object Object]` as its output too often. Some assertion libraries are better than others, but I rarely remember which. We previously used [QUnit](http://qunitjs.com/), but its Node support was sub-par. I experimented with [Tape](https://www.npmjs.org/package/tape) and it was by far the [easiest to get setup to run in the browser and Node](http://substack.net/how_I_write_tests_for_node_and_the_browser), however it is opinionated, and if you deviate from the expected workflow, we found it got in the way more than it helped. - -### Test platform - -Our tests run on every check-in and PR on [Travis CI](travis-ci.org). Travis an amazing platform; it was easy to get up and running and has been incredibly stable. PouchDB would be nowhere near the state it is today without it. - -However, we are beginning to outgrow Travis's free open-source capacity, and the paid options are prohibitively expensive. So we are beginning to look around for self-hosted alternatives, albiet without a lot of options. - -[Travis is open-source](https://github.com/travis-ci/travis-ci), however it is not a well-setup project for self-hosting – there isn't so much as a README to get started with. We previously used [Jenkins](http://jenkins-ci.org/), however I found it a huge maintenance burden. It's very possible someone with more experience in Jenkins could do a better job, though, and I am also keeping an eye on [Strider](http://stridercd.com/) as a possible alternative. - -### Test runner - -We use [Selenium](http://www.seleniumhq.org/) to drive tests in the browser, and [Saucelabs](https://saucelabs.com/) to run the browsers that we can't run locally. Saucelabs is great, however due to the nature of our tests, we generate a lot of HTTP traffic that needs to be proxied back to Travis, which has been a common point of failure. - -We are also finding some platforms (particularly iPhone and Internet Explorer) will become unstable on Saucelabs. The errors almost always come from our code, but it is hard to maintain a reliable test suite when the underlying platform changes and you have little control over it. - -Before settling on Selenium, I had previously tried out [Testling](https://ci.testling.com/), and similiarly to Tape it was very easy to get started but opinionated. It was also broken on OSX with pull requests containing fixes that hadn't been touched for months. Selenium had the advantage that it was very widely used, and new frameworks or platforms are likely to have WebDriver support early on. - -I have however found Selenium as a project fustrating to use, from the first time visiting [http://www.seleniumhq.org/](http://www.seleniumhq.org/) to understanding what I needed to download and write a first test that started a browser, it was an unclear and confusing process. Even today getting ChromeDriver started correctly gets me confused, also the download cost of 30MB for what is mostly a proxy server is an annoyance. - -I would love to see a project wrap up Selenium / ChromeDriver and possibly Cordova / Appium into a nice, well-documented module that installs and boots your browser(ish) platform of choice, ready to be driven by Selenium tests. - -### Performance tests - -Performance testing has been troublesome for PouchDB. We have a performance test suite, but it has been hard to integrate it into our CI process, which means it is not comprehensive and often forgotten. - -The issue with running in CI is that Travis is set up to run one test per commit, and every time there is a change to the test suite, its data needs to be backfilled in order to properly compare versions. There is also the fact that Saucelabs and Travis may change their running environment at any time, which makes comparisons over time useless. - -I expect that to fix this, we will need to run the tests on dedicated hardware and give performance tests some ability to choose which version of PouchDB to test, along with some helper scripts to backfill the performance data. - -### And done. - -Hopefully that gives a little insight into the process and issues we have with testing. It's a long and ongoing process, and I am hoping that the work we do to improve our testing infrastructure can be reused by other projects. - -We would love to hear more about the tools, techniques and issues that other similiar projects have come across while working on their tests. If you have anything to share, please send it along to [@pouchdb](https://twitter.com/pouchdb).
diff --git a/docs/_posts/2014-12-04-3.2.0.md b/docs/_posts/2014-12-04-3.2.0.md deleted file mode 100644 index 651bb04..0000000 --- a/docs/_posts/2014-12-04-3.2.0.md +++ /dev/null
@@ -1,58 +0,0 @@ ---- -layout: post - -title: PouchDB 3.2.0: To code is human, to debug is divine - -author: Nolan Lawson - ---- - -Hot on the heels of the last release, we present [3.2.0](https://github.com/pouchdb/pouchdb/releases/tag/3.2.0), which has new features to increase developer productivity, as well as a slew of bugfixes. - - -### New features - -* Finally, PouchDB has a [debug mode][]! ([#2874][], [#3084][]) -* You can now use `{attachments: true}` to fetch attachments in `allDocs()`, `changes()`, and `query()`, just like CouchDB 1.6.0+ ([#2771][], [#3074][], [#190][]) -* The `doc_ids` filter is now supported for `changes()` ([#3056][]) - -### Bugfixes - -* Fix conflict during replication of deleted documents ([#2970][]) -* Only detect blob support once ([#2990][]) -* Fix tree-merging algorithm, correctly attach docs to deleted winning revs ([#2888][]) -* Fix compaction-related race condition in LevelDB ([#3026][]) -* Fix LevelDB `bulkDocs()` ordering ([#3062][]) -* Fix WebSQL `put()` local docs when missing ([#3066][]) -* Fix encoding of base64-string attachments over HTTP ([#3008][]) -* Better error for invalid revs ([#2994][]) -* Upgrade Browserify to v6 ([#2884][]) - - -### In related news - -* [Hoodie ♥ PouchDB](https://github.com/hoodiehq/wip-hoodie-store-on-pouchdb) (and the feeling is mutual) -* [crypto-pouch](https://github.com/calvinmetcalf/crypto-pouch), a plugin to encrypt a CouchDB/PouchDB database -* [Porting Node.js crypto to the browser, part 1](http://calvinmetcalf.com/post/104082905653/porting-node-js-crypto-to-the-browser-part-1-all) -* [pouchdb-express-router](https://github.com/daleharvey/pouchdb-express-router), the minimum required to replicate PouchDB to an Express server (which will eventually be folded into express-pouchdb and pouchdb-server) -* [PouchDB performance report for November 2014](https://github.com/nolanlawson/pouchdb-perf-report-3.10#readme) - -Please [file issues](https://github.com/pouchdb/pouchdb/issues) or [tell us what you think](https://github.com/pouchdb/pouchdb/blob/master/CONTRIBUTING.md#get-in-touch). And as always, a big thanks to our [new and existing contributors](https://github.com/pouchdb/pouchdb/graphs/contributors)! - -[3.2.0]: https://github.com/pouchdb/pouchdb/releases/tag/3.2.0 -[#2771]: https://github.com/pouchdb/pouchdb/issues/2771 -[#3074]: https://github.com/pouchdb/pouchdb/issues/3074 -[#2874]: https://github.com/pouchdb/pouchdb/issues/2874 -[#3084]: https://github.com/pouchdb/pouchdb/issues/3084 -[#3056]: https://github.com/pouchdb/pouchdb/issues/3056 -[#2970]: https://github.com/pouchdb/pouchdb/issues/2970 -[#2888]: https://github.com/pouchdb/pouchdb/issues/2888 -[#3026]: https://github.com/pouchdb/pouchdb/issues/3026 -[#3062]: https://github.com/pouchdb/pouchdb/issues/3062 -[#3066]: https://github.com/pouchdb/pouchdb/issues/3066 -[#3008]: https://github.com/pouchdb/pouchdb/issues/3008 -[#2994]: https://github.com/pouchdb/pouchdb/issues/2994 -[#2990]: https://github.com/pouchdb/pouchdb/issues/2990 -[#2884]: https://github.com/pouchdb/pouchdb/issues/2884 -[#190]: https://github.com/pouchdb/mapreduce/issues/190 -[debug mode]: /api.html#debug_mode \ No newline at end of file
diff --git a/docs/adapters.md b/docs/adapters.md deleted file mode 100644 index 7bf162c..0000000 --- a/docs/adapters.md +++ /dev/null
@@ -1,301 +0,0 @@ ---- -layout: 2ColLeft -title: Adapters -sidebar: nav.html ---- - -PouchDB is not a self-contained database; it is a CouchDB-style abstraction layer over other databases. By default, PouchDB ships with [IndexedDB][] and [WebSQL][] adapters in the browser, and a [LevelDB][] adapter in Node.js. - -PouchDB attempts to provide a consistent API that "just works" across every browser and JavaScript environment, and in most cases, you can just use the defaults. However, if you're trying to reach the widest possible audience, or if you want the best performance, then you will sometimes want to tinker with the adapter settings. - -#### Topics: -* [PouchDB in the browser](#pouchdb_in_the_browser) -* [PouchDB in Node.js](#pouchdb_in_node_js) -* [PouchDB over HTTP](#pouchdb_over_http) -* [More resources](#more_resources) - - -{% include anchor.html title="PouchDB in the browser" hash="pouchdb_in_the_browser"%} - -In the browser, PouchDB prefers IndexedDB, and falls back to WebSQL if IndexedDB is not available. As of 2014, the browser support looks like this: - -### Desktop - -<div class="table-responsive"> -<table class="table"> -<tr> - <td></td> - <th><img src="static/img/browser-logos/internet-explorer_32x32.png" alt="IE"/></th> - <th><img src="static/img/browser-logos/firefox_32x32.png" alt="Firefox"/></th> - <th><img src="static/img/browser-logos/chrome_32x32.png" alt="Chrome"/></th> - <th><img src="static/img/browser-logos/safari_32x32.png" alt="Safari"/></th> - <th><img src="static/img/browser-logos/opera_32x32.png" alt="Opera"/></th> -</tr> -<tr> - <th>Adapter</th> - <th>IE</th> - <th>Firefox</th> - <th>Chrome</th> - <th>Safari</th> - <th>Opera</th> -</tr> -<tr> - <td>IndexedDB</td> - <td>✓ (10+)</td> - <td>✓</td> - <td>✓</td> - <td></td> - <td>✓</td> -</tr> -<tr> - <td>WebSQL</td> - <td></td> - <td></td> - <td>✓</td> - <td>✓</td> - <td>✓</td> -</tr> -</table> -</div> - -### Mobile - -<div class="table-responsive"> -<table class="table"> -<tr> - <th></th> - <th><img src="static/img/browser-logos/safari-ios_32x32.png" alt="Safari iOS"/></th> - <th><img src="static/img/browser-logos/opera_32x32.png" alt="Opera"/></th> - <th><img src="static/img/browser-logos/android_32x32.png" alt="Android"/></th> - <th><img src="static/img/browser-logos/blackberry_32x32.png" alt="BlackBerry"/></th> - <th><img src="static/img/browser-logos/opera_32x32.png" alt="Opera"/></th> - <th><img src="static/img/browser-logos/chrome-android_32x32.png" alt="Chrome for Android"/></th> - <th><img src="static/img/browser-logos/firefox_32x32.png" alt="Firefox for Android"/></th> - <th><img src="static/img/browser-logos/internet-explorer-tile_32x32.png" alt="IE"/></th> -</tr> -<tr> - <th>Adapter</th> - <th>iOS Safari</th> - <th>Opera Mini</th> - <th>Android Browser</th> - <th>BlackBerry Browser</th> - <th>Opera Mobile</th> - <th>Chrome for Android</th> - <th>Firefox for Android</th> - <th>IE Mobile</th> -</tr> -<tr> - <td>IndexedDB</td> - <td></td> - <td></td> - <td>✓ (4.4+)</td> - <td>✓ (10+)</td> - <td>✓ (21+)</td> - <td>✓</td> - <td>✓</td> - <td>✓</td> -<tr> -<tr> - <td>WebSQL</td> - <td>✓</td> - <td></td> - <td>✓</td> - <td>✓</td> - <td>✓</td> - <td>✓</td> - <td></td> - <td></td> -<tr> -</table> -</div> - -{% include alert_start.html variant="info"%} -Safari 7.1+ and iOS 8+ supposedly support IndexedDB, but their implementation has many bugs, so PouchDB currently ignores it. -{% include alert_end.html%} - -If you're ever curious which adapter is being used in a particular browser, you can use the following method: - -```js -var pouch = new PouchDB('myDB'); -console.log(pouch.adapter); // prints either 'idb' or 'websql' -``` - - -### SQLite plugin for Cordova/PhoneGap - -On Cordova/PhoneGap, it is often more performant to use the native SQLite database rather than the WebSQL database. This is also a good way to avoid [HTML5 storage quotas](http://www.html5rocks.com/en/tutorials/offline/quota-research). - -Luckily, there is a [SQLite Plugin][] that accomplishes exactly this. If you include this plugin in your project, then PouchDB will automatically pick it up based on the `window.sqlitePlugin` object. - -However, this only occurs if the adapter is `'websql'`, not `'idb'` (e.g. on Android 4.4+). To force PouchDB to use the WebSQL adapter, you can do: - -```js -var websqlPouch = new PouchDB('myDB', {adapter: 'websql'}); -``` - -The SQLite plugin is known to pass the PouchDB test suite on both iOS and Android. You may run into issues on Windows Phone 8. - -### Experimental adapter plugins - -PouchDB also offers separate browser plugins that use backends other than IndexedDB and WebSQL. These plugins pass our test suite at 100%, but are not yet part of the official release due to build issues with Browserify. They also add a hefty footprint due to external dependencies, so take them with a grain of salt. - -{% include alert_start.html variant="warning"%} -Currently these plugins do not work with Browserify itself; you have to include them as separate scripts in your HTML page. -{% include alert_end.html%} - -**Downloads:** - -* [pouchdb.localstorage.js](https://github.com/daleharvey/pouchdb/releases/download/{{ site.version }}/pouchdb.localstorage.js) -* [pouchdb.memory.js](https://github.com/daleharvey/pouchdb/releases/download/{{ site.version }}/pouchdb.memory.js) -* [pouchdb.idb-alt.js](https://github.com/daleharvey/pouchdb/releases/download/{{ site.version }}/pouchdb.idb-alt.js) - -#### LocalStorage plugin - -If you need to support very old browsers, such as IE ≤ 9.0 and Opera Mini, you can use the `pouchdb.localstorage.js` plugin, which allows PouchDB to fall back to [LocalStorage][] on browsers that don't support either IndexedDB or WebSQL. The [es5-shims][] will also be necessary. - -```html -<script src="pouchdb.js"></script> -<script src="pouchdb.localstorage.js"></script> -<script> - // this pouch is backed by LocalStorage - var pouch = new PouchDB('mydb', {adapter: 'localstorage'}); -</script> -``` - -{% include alert_start.html variant="warning"%} -The LocalStorage plugin should be considered highly experimental, and the underlying structure may change in the future. Currently it stores all document IDs in memory, which works fine on small databases but may crash on larger databases. You can follow <a href='https://github.com/No9/localstorage-down'>localstorage-down</a> to track our progress. -{% include alert_end.html %} - -#### Memory plugin - -If you want a quick database for your unit tests, you can use the `pouchdb.memory.js` plugin, which offers a pure in-memory PouchDB: - -```html -<script src="pouchdb.js"></script> -<script src="pouchdb.memory.js"></script> -<script> - // this pouch is ephemeral; it only exists in memory - var pouch = new PouchDB('mydb', {adapter: 'memory'}); -</script> -``` - -This pouch will act exactly like a normal one – replicating, storing attachments, pagination, etc. – but it will be deleted as soon as the user closes their browser. However, multiple `PouchDB` objects with the same database name will share the same data: - -```js -// pouch1 and pouch2 will share the same data -var pouch1 = new PouchDB('myDB', {adapter: 'memory'}); -var pouch2 = new PouchDB('myDB', {adapter: 'memory'}); - -// pouch3 will have its own data -var pouch3 = new PouchDB('myOtherDB', {adapter: 'memory'}); -``` - -#### Alternative IndexedDB adapter - -We are currently experimenting with a [LevelDown][]-based IndexedDB adapter (using [level-js][]) which may eventually replace the current IndexedDB adapter. If you would like to experiment with this, you may use the `pouchdb.idb-alt.js` plugin: - -```html -<script src="pouchdb.js"></script> -<script src="pouchdb.idb-alt.js"></script> -<script> - // this pouch is backed by IndexedDB but uses - // a different structure than the main one - var pouch = new PouchDB('mydb', {adapter: 'idb-alt'}); -</script> -``` - -This adapter does not currently offer any advantages over the `'idb'` adapter, but PouchDB developers will be interested in testing it. - -{% include anchor.html title="PouchDB in Node.js" hash="pouchdb_in_node_js"%} - -In Node.js, the adapter situation is much simpler than in browsers. By default, if you create a PouchDB like this one: - -```js -var pouch = new PouchDB('./path/to/db'); -``` - -then a LevelDB-based database will be created in the directory `./path/to/db`. - -Plus, since the LevelDB adapter is based on [LevelDOWN][], you also benefit from the rich ecosystem of LevelDOWN-based adapters. They may be installed using plain old `npm install` and `require()`. Below are a few examples. - -#### In-memory - -Just as in the browser, you can create a pure in-memory pouch based on [MemDOWN][]: - -``` -$ npm install memdown -``` - -then: - -```js -var pouch = new PouchDB('myDB', {db: require('memdown')}); -``` - -Notice that in Node.js, we use the key `'db'` instead of `'adapter'`. In Node.js the adapter is always called `'leveldb'` for historical reasons. - -#### Riak-based adapter - -This pouch is backed by [RiakDOWN][]: - -``` -$ npm install riakdown -``` - -then: - -```js -var pouch = new PouchDB('riak://localhost:8087/somebucket', {db: require('riakdown')}); -``` - -#### More LevelDOWN adapters - -There are many other LevelDOWN-based plugins – far too many to list here. You can find a [mostly-complete list on Github](https://github.com/rvagg/node-levelup/wiki/Modules) that includes implementations on top of MySQL, Windows Azure Table Storage, and SQLite. - - -{% include alert_start.html variant="warning"%} -We do not currently test against any LevelDOWN adapters other than LevelDB and MemDOWN, so the other backends should be considered experimental. -{% include alert_end.html%} - -{% include anchor.html title="PouchDB over HTTP" hash="pouchdb_over_http"%} - -In both the browser and in Node.js, PouchDB can also function as a straightforward API on top of any [CouchDB](https://couchdb.apache.org/)-compliant database, such as [IrisCouch](http://www.iriscouch.com/), [Cloudant](https://cloudant.com/), and [Couchbase Sync Gateway](http://docs.couchbase.com/sync-gateway/): - -```js -var pouch = new PouchDB('http://my-site.com:5984/my-db'); -var securePouch = new PouchDB('https://my-secure-site.com:5984/my-secure-db'); -``` - -However, we do not currently claim to support any database at 100% fidelity except for CouchDB, so your mileage may vary when syncing with the others. We will add databases to our supported list as we increase our test coverage. - -If you are ever unsure what to do, consider replicating from PouchDB to a CouchDB, then from that CouchDB to one of the other servers. - - - -#### PouchDB Server - -[PouchDB Server](https://github.com/pouchdb/pouchdb-server) is a standalone REST server that implements the CouchDB API, while using a LevelDB-based PouchDB under the hood. PouchDB Server passes our unit test suite at 100%, but be aware that it is not as full-featured or battle-tested as CouchDB. - -#### PouchDB Express - -The underlying module for PouchDB Server, [Express PouchDB](https://github.com/pouchdb/express-pouchdb) is an Express submodule that mimics most of the CouchDB API within your Express application. - -{% include anchor.html title="More resources" hash="more_resources"%} - -The best place to look for information on which browsers support which databases is [caniuse.com](http://caniuse.com). You can consult their tables on browser support for various backends: - -* [IndexedDB](http://caniuse.com/indexeddb) -* [WebSQL](http://caniuse.com/sql-storage) -* [LocalStorage](http://caniuse.com/namevalue-storage) - -[IndexedDB]: http://www.w3.org/TR/IndexedDB/ -[WebSQL]: http://www.w3.org/TR/webdatabase/ -[LevelDB]: https://code.google.com/p/leveldb/ -[LocalStorage]: https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Storage -[es5-shims]: https://github.com/es-shims/es5-shim -[sqlite plugin]: https://github.com/brodysoft/Cordova-SQLitePlugin -[leveldown]: https://github.com/rvagg/node-leveldown -[level-js]: https://github.com/maxogden/level.js -[memdown]: https://github.com/rvagg/memdown -[localstorage-down]: https://github.com/No9/localstorage-down -[RiakDOWN]: https://github.com/nlf/riakdown
diff --git a/docs/api.md b/docs/api.md deleted file mode 100644 index 7182ece..0000000 --- a/docs/api.md +++ /dev/null
@@ -1,1154 +0,0 @@ ---- -layout: 2ColLeft -title: API Reference -sidebar: api.html ---- - -Most of the PouchDB API is exposed as `fun(arg, [options], [callback])` where both the options and the callback are optional. Callbacks use the `function(err, result)` idiom where the first argument will be undefined unless there is an error, and the second argument holds the result. - -Additionally, any method that only returns a single thing (e.g. `db.get`) also returns a [promise][]. Promises come from the minimal library [lie][] in the browser, and the feature-rich [Bluebird][] in Node. - - [promise]: http://www.html5rocks.com/en/tutorials/es6/promises/ - [lie]: https://github.com/calvinmetcalf/lie - [bluebird]: https://github.com/petkaantonov/bluebird - -{% include anchor.html title="Create a database" hash="create_database" %} - -{% highlight js %} -new PouchDB([name], [options]) -{% endhighlight %} - -This method creates a database or opens an existing one. If you use a URL like `'http://domain.com/dbname'` then PouchDB will work as a client to an online CouchDB instance. Otherwise it will create a local database using whatever backend is present (i.e. IndexedDB, WebSQL, or LevelDB). - -### Options - -* `options.name`: You can omit the `name` argument and specify it via `options` instead. Note that the name is required. -* `options.auto_compaction`: This turns on auto compaction, which means `compact()` is called after every change to the database. Defaults to `false`. -* `options.adapter`: One of `'idb'`, `'leveldb'`, `'websql'`, or `'http'`. If unspecified, PouchDB will infer this automatically, preferring IndexedDB to WebSQL in browsers that support both (i.e. Chrome, Opera and Android 4.4+). -* `options.ajax`: An object of options to be sent to the ajax requester. In Node they are sent verbatim to [request][] with the exception of: - * `options.ajax.cache`: Appends a random string to the end of all HTTP GET requests to avoid them being cached on IE. Set this to `true` to prevent this happening. - -**Notes:** - -1. In IndexedDB and WebSQL, PouchDB will use `_pouch_` to prefix the internal database names. Do not manually create databases with the same prefix. -2. When acting as a client on Node, any other options given will be passed to [request][]. -3. When using the `'leveldb'` adapter (the default on Node), any other options given will be passed to [levelup][]. The storage layer of leveldb can be replaced by passing a level backend factory (such as [MemDOWN][]) as `options.db`. The rest of the supported options are [documented here][levelup_options]. -4. When using the `'websql'` adapter, you can use `options.size` to request more than 5MB up-front, in order to avoid errors caused by reaching the storage limit on iOS/Safari. Details [here](errors.html). - - [request]: https://github.com/mikeal/request - [levelup]: https://github.com/rvagg/node-levelup - [MemDOWN]: https://github.com/rvagg/memdown - [levelup_options]: https://github.com/rvagg/node-levelup/#options - -#### Example Usage: -{% highlight js %} -var db = new PouchDB('dbname'); -// or -var db = new PouchDB('http://localhost:5984/dbname'); -{% endhighlight %} - -Create a WebSQL-only Pouch (e.g. when using the [SQLite Plugin][] for Cordova/PhoneGap): - - [sqlite plugin]: https://github.com/lite4cordova/Cordova-SQLitePlugin - -{% highlight js %} -var db = new PouchDB('dbname', {adapter : 'websql'}); -{% endhighlight %} - -Create an in-memory Pouch (in Node): - -{% highlight js %} -var db = new PouchDB('dbname', {db : require('memdown')}); -{% endhighlight %} - -{% include anchor.html title="Delete a database" hash="delete_database"%} - -{% highlight js %} -db.destroy([options], [callback]) -{% endhighlight %} - -Delete database. - -**Notes:** With a remote CouchDB on Node, options are passed to [request][]. - -#### Example Usage: -{% highlight js %} -db.destroy(function(err, info) { }); -{% endhighlight %} - -You can also delete a database using just the name: - -{% highlight js %} -PouchDB.destroy('dbname', function(err, info) { }); -{% endhighlight %} - -{% include anchor.html title="Create / update a document" hash="create_document" %} - -### Using db.put() -{% highlight js %} -db.put(doc, [docId], [docRev], [options], [callback]) -{% endhighlight %} - -Create a new document or update an existing document. If the document already exists, you must specify its revision `_rev`, otherwise a conflict will occur. - -There are some restrictions on valid property names of the documents. These are explained [here](http://wiki.apache.org/couchdb/HTTP_Document_API#Special_Fields). - -#### Example Usage: - -Create a new doc with an `_id`: - -{% highlight js %} -db.put({ - title: 'Heroes' -}, 'mydoc', function(err, response) { }); -{% endhighlight %} - -Like all methods, you can also use a promise: - -{% highlight js %} -db.put({ - title: 'Lady Stardust' -}, 'myOtherDoc').then(function(response) { }); -{% endhighlight %} - -Update an existing doc using `_rev`: - -{% highlight js %} -db.get('myOtherDoc', function(err, otherDoc) { - db.put({ - title: "Let's Dance" - }, 'myOtherDoc', otherDoc._rev, function(err, response) { - }); -}); -{% endhighlight %} - -You can also include the `_id` and `_rev` directly in the document: - -{% highlight js %} -db.get('myOtherDoc').then(function(otherDoc) { - return db.put({ - _id: 'myOtherDoc', - _rev: otherDoc._rev, - title: 'Be My Wife', - }); -}, function(err, response) { - if (err) { - // on error - } else { - // on success - } -}); -{% endhighlight %} - -#### Example Response: -{% highlight js %} -{ - "ok": true, - "id": "mydoc", - "rev": "1-A6157A5EA545C99B00FF904EEF05FD9F" -} -{% endhighlight %} - -### Using db.post() -{% highlight js %} -db.post(doc, [options], [callback]) -{% endhighlight %} - -Create a new document and let PouchDB generate an `_id` for it. - -#### Example Usage: -{% highlight js %} -db.post({ - title: 'Ziggy Stardust' -}, function (err, response) { }); -{% endhighlight %} - -### Example Response: -{% highlight js %} -{ - "ok" : true, - "id" : "8A2C3761-FFD5-4770-9B8C-38C33CED300A", - "rev" : "1-d3a8e0e5aa7c8fff0c376dac2d8a4007" -} -{% endhighlight %} - -**Put vs. post**: The basic rule of thumb is: `put()` new documents with an `_id`, `post()` new documents without an `_id`. - -{% include anchor.html title="Fetch a document" hash="fetch_document"%} - -{% highlight js %} -db.get(docId, [options], [callback]) -{% endhighlight %} - -Retrieves a document, specified by `docId`. - -### Options - -All options default to `false` unless otherwise specified. - -* `options.rev`: Fetch specific revision of a document. Defaults to winning revision (see [the CouchDB guide](http://guide.couchdb.org/draft/conflicts.html)). -* `options.revs`: Include revision history of the document. -* `options.revs_info`: Include a list of revisions of the document, and their availability. -* `options.open_revs`: Fetch all leaf revisions if `open_revs="all"` or fetch all leaf revisions specified in `open_revs` array. Leaves will be returned in the same order as specified in input array. -* `options.conflicts`: If specified, conflicting leaf revisions will be attached in `_conflicts` array. -* `options.attachments`: Include attachment data. -* `options.local_seq`: Include sequence number of the revision in the database. -* `options.ajax`: An object of options to be sent to the ajax requester. In Node they are sent verbatim to [request][] with the exception of: - * `options.ajax.cache`: Appends a random string to the end of all HTTP GET requests to avoid them being cached on IE. Set this to `true` to prevent this happening. - - -#### Example Usage: - -{% highlight js %} -db.get('mydoc', function(err, doc) { }); -{% endhighlight %} - -#### Example Response: -{% highlight js %} -{ - "title": "Rock and Roll Heart", - "_id": "mydoc", - "_rev": "1-A6157A5EA545C99B00FF904EEF05FD9F" -} -{% endhighlight %} - -{% include anchor.html title="Delete a document" hash="delete_document"%} - -{% highlight js %} -db.remove(doc, [options], [callback]) -{% endhighlight %} - -Or: - -{% highlight js %} -db.remove(docId, docRev, [options], [callback]) -{% endhighlight %} - - -Deletes the document. `doc` is required to be a document with at least an `_id` and a `_rev` property. Sending the full document will work as well. - -#### Example Usage: -{% highlight js %} -db.get('mydoc', function(err, doc) { - db.remove(doc, function(err, response) { }); - // or: - db.remove(doc._id, doc._rev, function(err, response) { }); -}); -{% endhighlight %} - -### With Promises: -{% highlight js %} -db.get('mydoc').then(function(doc) { - return db.remove(doc); -}).catch(function(err){ - //errors -}); -{% endhighlight %} - -#### Example Response: -{% highlight js %} -{ - "ok": true, - "id": "mydoc", - "rev": "2-9AF304BE281790604D1D8A4B0F4C9ADB" -} -{% endhighlight %} - -{% include anchor.html title="Create/update a batch of documents" hash="batch_create" %} - -{% highlight js %} -db.bulkDocs(docs, [options], [callback]) -{% endhighlight %} - -Create, update or delete multiple documents. The `docs` argument is an array of documents. - -If you omit an `_id` parameter on a given document, the database will create a new document and assign the ID for you. To update a document, you must include both an `_id` parameter and a `_rev` parameter, which should match the ID and revision of the document on which to base your updates. Finally, to delete a document, include a `_deleted` parameter with the value `true`. - -**Note**: Previously `bulkDocs()` took an object with a key `docs` holding the array of documents. This is deprecated, but still works. - -#### Example Usage: - -Post some new docs and auto-generate the `_id`s: - -{% highlight js %} -db.bulkDocs([ - {title : 'Lisa Says'}, - {title : 'Space Oddity'} -], function(err, response) { }); -{% endhighlight %} - -#### Example Response: -{% highlight js %} -[ - { - "ok": true, - "id": "06F1740A-8E8A-4645-A2E9-0D8A8C0C983A", - "rev": "1-84abc2a942007bee7cf55007cba56198" - }, - { - "ok": true, - "id": "6244FB45-91DB-41E5-94FF-58C540E91844", - "rev": "1-7b80fc50b6af7a905f368670429a757e" - } -] -{% endhighlight %} - -#### Bulk update/delete: - -Then you can update those same docs: - -{% highlight js %} -db.bulkDocs([ - { - title : 'Lisa Says', - artist : 'Velvet Underground', - _id : "06F1740A-8E8A-4645-A2E9-0D8A8C0C983A", - _rev : "1-84abc2a942007bee7cf55007cba56198" - }, - { - title : 'Space Oddity', - artist : 'David Bowie', - _id : "6244FB45-91DB-41E5-94FF-58C540E91844", - _rev : "1-7b80fc50b6af7a905f368670429a757e" - } -], function(err, response) { }); -{% endhighlight %} - -Or delete them: - -{% highlight js %} -db.bulkDocs([ - { - title : 'Lisa Says', - _deleted : true, - _id : "06F1740A-8E8A-4645-A2E9-0D8A8C0C983A", - _rev : "1-84abc2a942007bee7cf55007cba56198" - }, - { - title : 'Space Oddity', - _deleted : true, - _id : "6244FB45-91DB-41E5-94FF-58C540E91844", - _rev : "1-7b80fc50b6af7a905f368670429a757e" - } -], function(err, response) { }); -{% endhighlight %} - -**Note:** You can also specify a `new_edits` property on the options object that when set to `false` allows you to post and overwrite [existing documents](http://wiki.apache.org/couchdb/HTTP_Bulk_Document_API#Posting_Existing_Revisions). Normally only the replication algorithm needs to do this. - -{% include anchor.html title="Fetch a batch of documents" hash="batch_fetch" %} - -{% highlight js %} -db.allDocs([options], [callback]) -{% endhighlight %} - -Fetch multiple documents. Deleted documents are only included if `options.keys` is specified. - -### Options - -All options default to `false` unless otherwise specified. - -* `options.include_docs`: Include the document itself in each row in the `doc` field. Otherwise by default you only get the `_id` and `_rev` properties. - - `options.conflicts`: Include conflict information in the `_conflicts` field of a doc. - - `options.attachments`: Include attachment data. -* `options.startkey` & `options.endkey`: Get documents with IDs in a certain range (inclusive/inclusive). -* `options.inclusive_end`: Include documents having an ID equal to the given `options.endkey`. Default: `true`. -* `options.limit`: Maximum number of documents to return. -* `options.skip`: Number of docs to skip before returning (warning: poor performance on IndexedDB/LevelDB!). -* `options.descending`: Reverse the order of the output documents. -* `options.key`: Only return documents with IDs matching this string key. -* `options.keys`: Array of string keys to fetch in a single shot. - - Neither `startkey` nor `endkey` can be specified with this option. - - The rows are returned in the same order as the supplied `keys` array. - - The row for a deleted document will have the revision ID of the deletion, and an extra key `"deleted":true` in the `value` property. - - The row for a nonexistent document will just contain an `"error"` property with the value `"not_found"`. - - For details, see the [CouchDB query options documentation](http://wiki.apache.org/couchdb/HTTP_view_API#Querying_Options). - -**Notes:** For pagination, `options.limit` and `options.skip` are also available, but the same performance concerns as in CouchDB apply. Use the [startkey/endkey pattern](http://docs.couchdb.org/en/latest/couchapp/views/pagination.html) instead. `total_rows` is the total number of documents in the database. - -#### Example Usage: -{% highlight js %} -db.allDocs({include_docs: true}, function(err, response) { }); -{% endhighlight %} - -#### Example Response: -{% highlight js %} -{ - "offset": 0, - "total_rows": 1, - "rows": [{ - "doc": { - "_id": "0B3358C1-BA4B-4186-8795-9024203EB7DD", - "_rev": "1-5782E71F1E4BF698FA3793D9D5A96393", - "title": "Sound and Vision" - }, - "id": "0B3358C1-BA4B-4186-8795-9024203EB7DD", - "key": "0B3358C1-BA4B-4186-8795-9024203EB7DD", - "value": { - "rev": "1-5782E71F1E4BF698FA3793D9D5A96393" - } - }] -} -{% endhighlight %} - -{% include anchor.html title="Listen to database changes" hash="changes" %} - -{% highlight js %} -db.changes(options) -{% endhighlight %} - -A list of changes made to documents in the database, in the order they were made. -It returns an object with the method `cancel()`, which you call if you don't want to listen to new changes anymore. - -It is an [event emitter][event emitter] and will emit a `'change'` event on each document change, a `'complete'` event when all the changes have been processed, and an `'error'` event when an error occurs. In addition to the `'change'` event, any change will also emit a `'create'`, `'update'`, or `'delete'` event. - -### Options - -All options default to `false` unless otherwise specified. - -* `options.include_docs`: Include the associated document with each change. - * `options.conflicts`: Include conflicts. - * `options.attachments`: Include attachments. -* `options.descending`: Reverse the order of the output documents. -* `options.filter`: Reference a filter function from a design document to selectively get updates. -* `options.doc_ids`: Only show changes for docs with these ids (array of strings). -* `options.since`: Start the results from the change immediately after the given sequence number, you can also pass 'now' if you want only new changes. -* `options.live`: Uses the `_longpoll_` feed. -* `options.limit`: Limit the number of results to this number. -* `options.style`: Specifies how many revisions are returned in the changes array. The default, `'main_only'`, will only return the current "winning" revision; `'all_docs'` will return all leaf revisions (including conflicts and deleted former conflicts). -* `options.view`: Specify a view function to act as a filter. Documents counted as "passed" for a view filter if a map function emits at least one record for them. -* `options.returnDocs`: Is available for non http databases and defaults to true, passing `false` prevents the changes feed from keeping all the documents in memory, in other words complete always has an empty results array, and the `change` event is the only way to get the event. Useful for large change sets where otherwise you would run out of memory. -* `options.batch_size`: Only available for http databases, this configures how many changes to fetch at a time. Increasing this can reduce the number of requests made. Default is 25. - -#### Example Usage: -{% highlight js %} -var changes = db.changes({ - since: 20, - live: true -}).on('change', function(change) { }); - -changes.cancel(); // whenever you want to cancel -{% endhighlight %} - -#### Example Response: -{% highlight js %} -{ - "id":"somestuff", - "seq":21, - "changes":[{ - "rev":"1-8e6e4c0beac3ec54b27d1df75c7183a8" - }], - "doc":{ - "title":"Ch-Ch-Ch-Ch-Changes", - "_id":"someDocId", - "_rev":"1-8e6e4c0beac3ec54b27d1df75c7183a8" - } -} -{% endhighlight %} - -#### Example Usage: -{% highlight js %} -db.changes() - .on('error', function (err) {}) - .on('complete', function (resp) {}); -{% endhighlight %} - -#### Example Response: -{% highlight js %} -{ - "results": [{ - "id": "0B3358C1-BA4B-4186-8795-9024203EB7DD", - "seq": 1, - "changes": [{ - "rev": "1-5782E71F1E4BF698FA3793D9D5A96393" - }] - }, { - "id": "mydoc", - "seq": 2, - "changes": [{ - "rev": "1-A6157A5EA545C99B00FF904EEF05FD9F" - }] - }, { - "id": "otherdoc", - "seq": 3, - "changes": [{ - "rev": "1-3753476B70A49EA4D8C9039E7B04254C" - }] - }, { - "id": "828124B9-3973-4AF3-9DFD-A94CE4544005", - "seq": 4, - "changes": [{ - "rev": "1-A8BC08745E62E58830CA066D99E5F457" - }] - }] -} -{% endhighlight %} - -**Note:** - -* The `'complete'` event only fires when you aren't doing live changes. With live changes, use the `'uptodate'` event instead. -* The `changes()` method was not an event emitter before PouchDB 2.2.0, and instead of the `'change'` and `'complete'` events it took `complete` and `onChange` function options. This is deprecated and could be removed in PouchDB version 3. -* The `'since'`option formally took 'latest' but has been changed to 'now' to keep consistency with CouchDB, 'latest' is deprecated but will still work to ensure backwards compatibility. - -{% include anchor.html title="Replicate a database" hash="replication" %} - -{% highlight js %} -PouchDB.replicate(source, target, [options]) -{% endhighlight %} - -Replicate data from `source` to `target`. Both the `source` and `target` can be a PouchDB instance or a string representing a CouchDB database URL or the name of a local PouchDB database. If `options.live` is `true`, then this will track future changes and also replicate them automatically. This method returns an object with the method `cancel()`, which you call if you want to cancel live replication. - -Replication is an event emiter like `changes()` and emits the `'complete'`, `'uptodate'`, `'change'` and `'error'` events. - -### Options - -All options default to `false` unless otherwise specified. - -* `options.filter`: Reference a filter function from a design document to selectively get updates. -* `options.query_params`: Query params sent to the filter function. -* `options.doc_ids`: Only replicate docs with these ids (array of strings). -* `options.live`: If `true`, starts subscribing to future changes in the `source` database and continue replicating them. -* `options.since`: Replicate changes after the given sequence number. -* `options.create_target`: Create target database if it does not exist. Only for server replications. -* `options.batch_size`: Number of documents to process at a time. Defaults to 100. This affects the number of docs held in memory and the number sent at a time to the target server. You may need to adjust downward if targeting devices with low amounts of memory (e.g. phones) or if the documents are large in size (e.g. with attachments). If your documents are small in size, then increasing this number will probably speed replication up. -* `options.batches_limit`: Number of batches to process at a time. Defaults to 10. This (along wtih `batch_size`) controls how many docs are kept in memory at a time, so the maximum docs in memory at once would equal `batch_size` × `batches_limit`. - -#### Example Usage: -{% highlight js %} -var replication = PouchDB.replicate('mydb', 'http://localhost:5984/mydb', {live: true}) - .on('change', function (info) { - // handle change - }).on('complete', function (info) { - // handle complete - }).on('uptodate', function (info) { - // handle up-to-date - }).on('error', function (err) { - // handle error - }); - -replication.cancel(); // whenever you want to cancel -{% endhighlight %} - -There are also shorthands for replication given existing PouchDB objects. These behave the same as `PouchDB.replicate()`: - -{% highlight js %} -db.replicate.to(remoteDB, [options]); -// or -db.replicate.from(remoteDB, [options]); -{% endhighlight %} - -**Notes:** - -* The `'complete'` event only fires when you aren't doing live replication, or when live replication fails. -* The `'uptodate'` event fires during live replication, when the target database is up-to-date and just idling, waiting for new changes. - -#### Example Response: - -Example response in the `'change'` listener: - -{% highlight js %} -{ - "doc_write_failures": 0, - "docs_read": 1, - "docs_written": 1, - "errors": [], - "last_seq": 1, - "ok": true, - "start_time": "Fri May 16 2014 18:23:12 GMT-0700 (PDT)" -} -{% endhighlight %} - -Example response in the `'complete'` listener: - -{% highlight js %} -{ - "doc_write_failures": 0, - "docs_read": 2, - "docs_written": 2, - "end_time": "Fri May 16 2014 18:26:00 GMT-0700 (PDT)", - "errors": [], - "last_seq": 2, - "ok": true, - "start_time": "Fri May 16 2014 18:26:00 GMT-0700 (PDT)", - "status": "complete" -} -{% endhighlight %} - -**Notes:** - -* The response for server replications (via `options.server`) is slightly different. See the [CouchDB replication documentation](http://wiki.apache.org/couchdb/Replication) for details. -* The `'live'` option was formerly called `'continuous'`. You can still use `'continuous'` if you can spell it. -* The replicate() method was not an event emitter before PouchDB 2.2.0, and instead of the `'change'` and `'complete'` events it took `complete` and `onChange` function options. This is deprecated and could be removed in PouchDB version 3. - -{% include anchor.html title="Sync a database" hash="sync" %} - -{% highlight js %} -var sync = PouchDB.sync(src, target, [options]) -{% endhighlight %} - -Sync data from `src` to `target` and `target` to `src`. This is a convenience method for bidirectional data replication. - -In other words, this code: - -{% highlight js %} -PouchDB.replicate('mydb', 'http://localhost:5984/mydb'); -PouchDB.replicate('http://localhost:5984/mydb', 'mydb'); -{% endhighlight %} - - -is equivalent to this code: - -{% highlight js %} -PouchDB.sync('mydb', 'http://localhost:5984/mydb'); -{% endhighlight %} - - -### Options - -Please refer to [Replication](api.html#replication) for documentation on options, as `sync()` is just a convenience method that entails bidirectional replication. - -#### Example Usage: -{% highlight js %} -var sync = PouchDB.sync('mydb', 'http://localhost:5984/mydb', {live: true}) - .on('change', function (info) { - // handle change - }).on('complete', function (info) { - // handle complete - }).on('uptodate', function (info) { - // handle up-to-date - }).on('error', function (err) { - // handle error - }); - -sync.cancel(); // whenever you want to cancel -{% endhighlight %} - -There is also a shorthand for syncing given existing PouchDB objects. This behaves the same as `PouchDB.sync()`: - -{% highlight js %} -db.sync(remoteDB, [options]); -{% endhighlight %} - -For any further details, please further to [Replication](api.html#replication). - -{% include anchor.html title="Save an attachment" hash="save_attachment" %} - -{% highlight js %} -db.putAttachment(docId, attachmentId, rev, attachment, type, [callback]); -{% endhighlight %} - -Attaches a binary object to a document. Most of PouchDB's API deals with JSON, but if you're dealing with large binary data (such as PNGs), you may incur a performance or storage penalty if you simply include them as base64- or hex-encoded strings. In these cases, you can store the binary data as an attachment. For details, see the [CouchDB documentation on attachments](https://wiki.apache.org/couchdb/HTTP_Document_API#Attachments). - -#### Example Usage: -{% highlight js %} -var attachment = new Blob(['Is there life on Mars?']); -db.putAttachment('a', 'text', rev, attachment, 'text/plain', function(err, res) {}) -{% endhighlight %} - -#### Example Response: -{% highlight js %} -{ - "ok": true, - "id": "otherdoc", - "rev": "2-068E73F5B44FEC987B51354DFC772891" -} -{% endhighlight %} - -Within Node, you must use a `Buffer` instead of a `Blob`: - -{% highlight js %} -var attachment = new Buffer('Is there life on Mars?'); -{% endhighlight %} - -For details, see the [Mozilla docs on `Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) or the [Node docs on `Buffer`](http://nodejs.org/api/buffer.html). If you need a shim for older browsers that don't support the `Blob` constructor, you can use [blob-util](https://github.com/nolanlawson/blob-util). - -### Save an inline attachment - -You can also inline attachments inside the document. In this case, the attachment data must be supplied as a base64-encoded string: - -{% highlight js %} -{ - '_id': 'otherdoc', - 'title': 'Legendary Hearts', - '_attachments': { - "text": { - "content_type": "text/plain", - "data": "TGVnZW5kYXJ5IGhlYXJ0cywgdGVhciB1cyBhbGwgYXBhcnQKT" + - "WFrZSBvdXIgZW1vdGlvbnMgYmxlZWQsIGNyeWluZyBvdXQgaW4gbmVlZA==" - } - } -} -{% endhighlight %} - -See [Inline Attachments](http://wiki.apache.org/couchdb/HTTP_Document_API#Inline_Attachments) -on the CouchDB wiki for details. - -{% include anchor.html title="Get an attachment" hash="get_attachment" %} - -{% highlight js %} -db.getAttachment(docId, attachmentId, [options], [callback]) -{% endhighlight %} - -Get attachment data. - -#### Example Usage: - -{% highlight js %} -db.getAttachment('otherdoc', 'text', function(err, res) { }); -{% endhighlight %} - -In Node you get `Buffer`s, and in the browser you get `Blob`s. - -### Inline attachments - -You can specify `attachments: true` to most read operations. The attachment data will then be included inlined in the resulting list of docs. - -{% include anchor.html title="Delete an attachment" hash="delete_attachment" %} - -{% highlight js %} -db.removeAttachment(docId, attachmentId, rev, [callback]) -{% endhighlight %} - -Delete an attachment from a doc. - -#### Example Usage: -{% highlight js %} -db.removeAttachment('otherdoc', - 'text', - '2-068E73F5B44FEC987B51354DFC772891', - function(err, res) { }); -{% endhighlight %} - -#### Example Response: -{% highlight js %} -{ - "ok": true, - "rev": "3-1F983211AB87EFCCC980974DFC27382F" -} -{% endhighlight %} - -{% include anchor.html title="Query the database" hash="query_database" %} - -{% highlight js %} -db.query(fun, [options], [callback]) -{% endhighlight %} - -Retrieves a view, which allows you to perform more complex queries on PouchDB. The [CouchDB documentation for map/reduce](http://docs.couchdb.org/en/latest/couchapp/views/intro.html) applies to PouchDB. - -Since views perform a full scan of all documents, this method may be slow, unless you first save your view in a design document. - -### Options - -All options default to `false` unless otherwise specified. - -* `fun`: Map/reduce function, which can be one of the following: - * A map function by itself (no reduce). - * A full CouchDB-style map/reduce object: `{map : ..., reduce: ...}`. - * The name of a view in an existing design document (e.g. `'myview'` or `'mydesigndoc/myview'`). -* `options.reduce`: Reduce function, or the string name of a built-in function: `'_sum'`, `'_count'`, or `'_stats'`. Defaults to `false` (no reduce). - * Tip: if you're not using a built-in, [you're probably doing it wrong](http://youtu.be/BKQ9kXKoHS8?t=865s). - * PouchDB will always call your reduce function with rereduce == false. As for CouchDB, refer to the [CouchDB documentation](http://docs.couchdb.org/en/1.6.1/couchapp/views/intro.html). -* `options.include_docs`: Include the document in each row in the `doc` field. - - `options.conflicts`: Include conflicts in the `_conflicts` field of a doc. - - `options.attachments`: Include attachment data. -* `options.startkey` & `options.endkey`: Get rows with keys in a certain range (inclusive/inclusive). -* `options.inclusive_end`: Include rows having a key equal to the given `options.endkey`. Default: `true`. -* `options.limit`: Maximum number of rows to return. -* `options.skip`: Number of rows to skip before returning (warning: poor performance on IndexedDB/LevelDB!). -* `options.descending`: Reverse the order of the output rows. -* `options.key`: Only return rows matching this key. -* `options.keys`: Array of keys to fetch in a single shot. - - Neither `startkey` nor `endkey` can be specified with this option. - - The rows are returned in the same order as the supplied `keys` array. - - The row for a deleted document will have the revision ID of the deletion, and an extra key `"deleted":true` in the `value` property. - - The row for a nonexistent document will just contain an `"error"` property with the value `"not_found"`. -* `options.group`: True if you want the reduce function to group results by keys, rather than returning a single result. Defaults to `false`. -* `options.group_level`: Number of elements in a key to group by, assuming the keys are arrays. Defaults to the full length of the array. -* `options.stale`: One of `'ok'` or `'update_after'`. Only applies to saved views. Can be one of: - * unspecified (default): Returns the latest results, waiting for the view to build if necessary. - * `'ok'`: Returns results immediately, even if they're out-of-date. - * `'update_after'`: Returns results immediately, but kicks off a build afterwards. - -For details, see the [CouchDB query options documentation](http://wiki.apache.org/couchdb/HTTP_view_API#Querying_Options). - -#### Example Usage: -{% highlight js %} -function map(doc) { - if (doc.title) { - emit(doc.title); - } -} - -db.query({map: map}, {reduce: false}, function(err, response) { }); -{% endhighlight %} - -#### Example Response: -{% highlight js %} -{ - "offset" : 0, - "rows": [{ - "id": "0B3358C1-BA4B-4186-8795-9024203EB7DD", - "key": "Cony Island Baby", - "value": null - }, { - "id": "otherdoc", - "key": "Legendary Hearts", - "value": null - }, { - "id": "828124B9-3973-4AF3-9DFD-A94CE4544005", - "key": "Lisa Says", - "value": null - }, { - "id": "mydoc", - "key": "Rock and Roll Heart", - "value": null - }], - "total_rows" : 4 -} -{% endhighlight %} - -**Note:** `total_rows` is the total number of possible results in the view. - -#### Complex keys - -You can also use [complex keys](https://wiki.apache.org/couchdb/Introduction_to_CouchDB_views#Complex_Keys) for fancy ordering: - -{% highlight js %} -function map(doc) { - // sort by last name, first name, and age - emit([doc.lastName, doc.firstName, doc.age]); -} -db.query(map, function (err, response) {}); -{% endhighlight %} - -#### Example Response: -{% highlight js %} -{ - "offset": 0, - "rows": [{ - "id" : "bowie", - "key" : ["Bowie", "David", 67] - }, { - "id" : "dylan", - "key" : ["Dylan", "Bob", 72] - }, { - "id" : "younger_dylan", - "key" : ["Dylan", "Jakob", 44] - }, { - "id" : "hank_the_third", - "key" : ["Williams", "Hank", 41] - }, { - "id" : "hank", - "key" : ["Williams", "Hank", 91] - }], - "total_rows": 5 -} -{% endhighlight %} - -**Tips:** - -* CouchDB sorts objects last, so `{startkey: ['Williams'], endkey: ['Williams', {}]}` would return all people with the last name `'Williams'`. -* `group_level` can be very helpful when working with complex keys. In the example above, you can use `{group_level: 1}` to group by last name, or `{group_level: 2}` to group by last and first name. - -#### Linked documents - -PouchDB fully supports [linked documents](https://wiki.apache.org/couchdb/Introduction_to_CouchDB_views#Linked_documents). Use them to join two types of documents together, by simply adding an `_id` to the emitted value: - -{% highlight js %} -function map(doc) { - // join artist data to albums - if (doc.type === 'album') { - emit(doc.name, {_id : doc.artistId, albumYear : doc.year}); - } -} -db.query(map, {include_docs : true}, function (err, response) {}); -{% endhighlight %} - -#### Example response: - -{% highlight js %} -{ - "offset": 0, - "rows": [ - { - "doc": { - "_id": "bowie", - "_rev": "1-fdb234b78904a5c8293f2acf4be70d44", - "age": 67, - "firstName": "David", - "lastName": "Bowie" - }, - "id": "album_hunkydory", - "key": "Hunky Dory", - "value": { - "_id": "album_hunkydory", - "albumYear": 1971 - } - }, - { - "doc": { - "_id": "bowie", - "_rev": "1-fdb234b78904a5c8293f2acf4be70d44", - "age": 67, - "firstName": "David", - "lastName": "Bowie" - }, - "id": "album_low", - "key": "Low", - "value": { - "_id": "album_low", - "albumYear": 1977 - } - }, - { - "doc": { - "_id": "bowie", - "_rev": "1-fdb234b78904a5c8293f2acf4be70d44", - "age": 67, - "firstName": "David", - "lastName": "Bowie" - }, - "id": "album_spaceoddity", - "key": "Space Oddity", - "value": { - "_id": "album_spaceoddity", - "albumYear": 1969 - } - } - ], - "total_rows": 3 -} -{% endhighlight %} - -#### Closures - -If you pass a function to `db.query` and give it the `emit` function as the second argument, then you can use a closure. (Otherwise we have to use `eval()` to bind `emit`.) - -{% highlight js %} -// BAD! will throw error -var myId = 'foo'; -db.query(function(doc) { - if (doc._id === myId) { - emit(doc); - } -}, function(err, results) { /* ... */ }); - -// will be fine -var myId = 'foo'; -db.query(function(doc, emit) { - if (doc._id === myId) { - emit(doc); - } -}, function(err, results) { /* ... */ }); -{% endhighlight %} - -You don't actuallly have to call them by those names, though: -{% highlight js %} -var myId = 'foo'; -db.query(function(thisIs, awesome) { - if (thisIs._id === myId) { - awesome(thisIs); - } -}, function(err, results) { /* ... */ }); -{% endhighlight %} - -Note that closures are only supported by local databases with temporary views. - -{% include anchor.html title="View cleanup" hash="view_cleanup" %} - -{% highlight js %} -db.viewCleanup([options], [callback]) -{% endhighlight %} - -Cleans up any stale map/reduce indexes. - -As design docs are deleted or modified, their associated index files (in CouchDB) or companion databases (in local PouchDBs) continue to take up space on disk. `viewCleanup()` removes these unnecessary index files. - -See [the CouchDB documentation on view cleanup](http://couchdb.readthedocs.org/en/latest/maintenance/compaction.html#views-cleanup) for details. - -#### Example Usage: -{% highlight js %} -db.viewCleanup([options], [callback]) -{% endhighlight %} - -#### Example Response: -{% highlight js %} -{ - "ok" : "true" -} -{% endhighlight %} - -{% include anchor.html title="Get database information" hash="database_information" %} - -{% highlight js %} -db.info(callback) -{% endhighlight %} - -Get information about a database. - -#### Example Usage: -{% highlight js %} -db.info(function(err, info) { }) -{% endhighlight %} - -#### Example Response: -{% highlight js %} -{ - "db_name": "test", - "doc_count": 4, - "update_seq": 5 -} -{% endhighlight %} - -**Response object:** - -* `db_name` is the name of the database you gave when you called `new PouchDB()`, and also the unique identifier for the database. -* `doc_count` is the total number of non-deleted documents in the database. -* `update_seq` is the sequence number of the database. It starts at 0 and gets incremented every time a document is added or modified. - -{% include anchor.html title="Compact the database" hash="compaction" %} - -{% highlight js %} -db.compact([options], [callback]) -{% endhighlight %} - -Triggers a compaction operation for `db` on the local or remote database. This reduces the database's size by removing unused and old data. If a `callback` function is specified, Pouch checks compaction status at regular intervals and fires the callback upon completion. Consult the [compaction section of CouchDB's maintenance documentation](http://couchdb.readthedocs.org/en/latest/maintenance/compaction.html) for more detail about database compaction. - -* `options.interval`: Number of milliseconds Pouch waits before asking again if compaction is already done. Defaults to 200. - -{% include anchor.html title="Document revisions diff" hash="revisions_diff" %} - -{% highlight js %} -db.revsDiff(diff, [callback]) -{% endhighlight %} - -Given a set of document/revision IDs, returns the subset of those that do not correspond -to revisions stored in the database. Primarily used in replication. - -#### Example Usage: -{% highlight js %} -db.revsDiff({ - myDoc1: [ - "1-b2e54331db828310f3c772d6e042ac9c", - "2-3a24009a9525bde9e4bfa8a99046b00d" - ] -}, function (err, diffs) { }); -{% endhighlight %} - -#### Example Response: -{% highlight js %} -{ - "myDoc1": { - "missing": ["2-3a24009a9525bde9e4bfa8a99046b00d"] - } -} -{% endhighlight %} - -{% include anchor.html title="Events" hash="events"%} - -PouchDB is an [event emitter][event emitter] and will emit a `'created'` event when a database is created. A `'destroyed'` event is emitted when a database is destroyed. - -{% highlight js %} -PouchDB.on('created', function (dbName) { - // called whenver a db is created. -}); -PouchDB.on('destroyed', function (dbName) { - // called whenver a db is destroyed. -}); -{% endhighlight %} - -{% include anchor.html title="Default settings" hash="defaults"%} - -If you find yourself using the same constructor options repeatedly, -you can simplify your code with `PouchDB.defaults()`: - -{% highlight js %} -PouchDB.defaults({ - option1: 'foo', - option2: 'value' -}); -{% endhighlight %} - -The returned object is a constructor function that works the same as `PouchDB`, except that whenever you invoke it (e.g. with `new`), the given options will be passed in by default. - -#### Example Usage: -{% highlight js %} -var MyMemPouch = PouchDB.defaults({ - db: require('memdown') -}); -// MemDOWN-backed Pouch (in Node) -var MyMemPouch = new MyMemPouch('dbname'); - -var MyPrefixedPouch = PouchDB.defaults({ - prefix: '/path/to/my/db/' -}); -// db will be named '/path/to/my/db/dbname', useful for LevelDB -var myPrefixedPouch = new MyPrefixedPouch('dbname'); -{% endhighlight %} - -Note the special constructor option `prefix`, which appends a prefix to the database name -and can be helpful for URL-based or file-based LevelDOWN path names. - -All [constructor options](#create_database) are supported. Default options can still be overriden individually. - -{% include anchor.html title="Plugins" hash="plugins"%} - -Writing a plugin is easy! The API is: - -{% highlight js %} -PouchDB.plugin({ - methodName: myFunction -}); -{% endhighlight %} - -This will add the function as a method of all databases with the given method name. It will always be called in context, so that `this` always refers to the database object. - -We also offer a [PouchDB Plugin Seed project](https://github.com/pouchdb/plugin-seed), which is the fastest way to get started writing, building and testing your very own plugin. - -#### Example Usage: -{% highlight js %} -PouchDB.plugin({ - sayMyName : function () { - this.info().then(function (info) { - console.log('My name is ' + info.db_name); - }).catch(function (err) { }); - } -}); -new PouchDB('foobar').sayMyName(); // prints "My name is foobar" -{% endhighlight %} - -{% include anchor.html title="Debug mode" hash="debug_mode"%} - -PouchDB uses the [debug](https://www.npmjs.org/package/debug) module for fine-grained debug output. - -To enable debug mode, just call: - -{% highlight js %} -PouchDB.debug.enable('*'); -{% endhighlight %} - -In your browser console, you should then see something like this: - -<img alt="colored log output" style="max-width: 700px;" src="static/img/debug_mode.png"/> - -In Node.js, you can also set a command-line flag: - -{% highlight bash %} -DEBUG=pouchdb:* node myscript.js -{% endhighlight %} - -You can also enable debugging of specific modules. Currently we only have `pouchb:api` (API-level calls) and `pouchdb:http` (HTTP requests): - -{% highlight js %} -PouchDB.debug.enable('pouchdb:api'); // or -PouchDB.debug.enable('pouchdb:http'); -{% endhighlight %} - -These settings are saved to the browser's LocalStorage. So to disable them, you must call: - -{% highlight js %} -PouchDB.debug.disable(); -{% endhighlight %} - -Your users won't see debug output unless you explicitly call `PouchDB.debug.enable()` within your application code. - -[event emitter]: http://nodejs.org/api/events.html#events_class_events_eventemitter
diff --git a/docs/blog/index.html b/docs/blog/index.html deleted file mode 100644 index cffd22a..0000000 --- a/docs/blog/index.html +++ /dev/null
@@ -1,30 +0,0 @@ ---- -layout: default -title: Blog ---- - -<article class='container'> -<div class='row'> -<div class='col-md-8'> -{% for post in paginator.posts %} - -<a class='h3' href='{{ site.baseurl }}{{ post.url }}'>{{ post.title }}</a> -{% include post_details.html %} - -{% endfor %} -<ul class='pagination'> - <li {% if paginator.page == 1 %}class='disabled'{% endif %}><a href='{{paginator.previous_page_path | replace:'/index.html','' }}/'>«</a></li> - {% for page in (1..paginator.total_pages) %} - {% if page == paginator.page %} - <li class='active'><a>{{page}}</a></li> - {% elsif page == 1 %} - <li><a href='/blog/'>{{page}}</a></li> - {% else %} - <li><a href='/blog/page{{page}}/'>{{page}}</a></li> - {% endif %} - {% endfor %} - <li {% if paginator.page == paginator.total_pages %} class='disabled' {% endif %}><a href='{{paginator.next_page_path}}/'>»</a></li> -</ul> -</div> -</div> -</article>
diff --git a/docs/errors.md b/docs/errors.md deleted file mode 100644 index 9294f6c..0000000 --- a/docs/errors.md +++ /dev/null
@@ -1,156 +0,0 @@ ---- -layout: 2ColLeft -title: Common Errors -sidebar: nav.html ---- - -{% include anchor.html class="h3" title="No 'Access-Control-Allow-Origin' header" hash="no_access_control_allow_origin_header" %} - -If you see the error: - -> XMLHttpRequest cannot load [...] -> No 'Access-Control-Allow-Origin' header is present on the requested resource. -> Origin [...] is therefore not allowed access. - -or this one: - -> Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://[couchDBIP]:[couchDBPort]/[dbname]/?_nonce=[request hash]. This can be fixed by moving the resource to the same domain or enabling CORS - -it's because you need to enable [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) on CouchDB/IrisCouch/whatever you're using. Otherwise, your scripts can only access the server database if they're served from the same domain. - -You can enable CORS in CouchDB using `curl` or the Futon web interface, but we've saved you some time by making a Node script called [add-cors-to-couchdb](https://github.com/pouchdb/add-cors-to-couchdb). Just run: - -{% highlight bash %} -$ npm install -g add-cors-to-couchdb -$ add-cors-to-couchdb -{% endhighlight %} - -Or if your database is not at `127.0.0.1:5984`: - -{% highlight bash %} -$ add-cors-to-couchdb http://me.iriscouch.com \ - -u myusername -p mypassword -{% endhighlight %} - -You can check that CORS is now enabled by visiting [http://localhost:5984/_utils/config.html](http://localhost:5984/_utils/config.html) in your browser. You should see something like this: - - - -{% include anchor.html class="h3" title="iOS/Safari: \"there was not enough remaining storage space\"" hash="not_enough_space" %} - -On iOS and Safari, if you expect your app to use more than 5MB of space, you will need to request the space up-front from the user. In certain versions, notably Safari/iOS 7, you can never request more than what the user originally grants you. - - - -To get around this, when you create your PouchDB, use the `opts.size` option for the expected _maximum_ size of the database in MB. Valid increments are 10, 50, 100, 500, and 1000. For instance, if you request 50, then Safari will show a popup saying "allow 50MB?" but if you request 51, then Safari will show a popup saying "allow 100MB?". - -If you don't use the `size` option, then you'll be able to use up to 5MB without any popup, but then once you use more, there will be a popup asking for 10. - -```js -new PouchDB('mydb', {size: 10}); // request 10 MB with a popup -new PouchDB('mydb', {size: 50}); // request 50 MB with a popup -new PouchDB('mydb'); // implicitly request 5 MB, no popup until you exceed 5MB -``` - -This does not affect any backend other than Web SQL. Chrome, Android, and Opera do not show the popup. On PhoneGap/Cordova apps, you can also use the [SQLite plugin][sqlite] to get around this problem. Here's [more information about storage quotas](http://www.html5rocks.com/en/tutorials/offline/quota-research) and [details on the Safari/iOS 7 bug](https://github.com/pouchdb/pouchdb/issues/2347). - -{% include anchor.html class="h3" title="PouchDB throws 404 (Object Not Found) for '_local' document" hash="404__local_document" %} - -Don't worry, nothing is amiss, this is expected behaviour: -During PouchDB's initial replication PouchDB will check for a checkpoint, if it doesn't exist a 404 will be returned and a checkpoint will subsequently be written. - -{% include anchor.html class="h3" title="PouchDB is throwing `InvalidStateError`" hash="throwing_invalidstateerror" %} - -Are you in private browsing mode? IndexedDB is [disabled in private browsing mode](https://developer.mozilla.org/en-US/docs/IndexedDB/Using_IndexedDB) in Firefox. - -{% include anchor.html class="h3" title="Can't open second database on Android WebView with Cordova/Phone Gap" hash="phonegap_cordova_second_database" %} - -There is a limit of one database per app in some versions of the Android WebView. Install the [SQLite plugin][sqlite], then PouchDB will use that if it is available. - -{% include anchor.html class="h3" title="Database size limitation of ~5MB on iOS with Cordova/Phone Gap" hash="size_limitation_5mb" %} - -If you're storing large amounts of data, such as PNG attachments, the [SQLite plugin][sqlite] is again your friend. (See [issue #1260](https://github.com/daleharvey/pouchdb/issues/1260) for details.) - -{% include anchor.html class="h3" title="CouchDB returns a 404 for GETs from a CouchApp" hash="404_get_couchapp" %} - -Certain URL rewrites are broken by PouchDB's cache-busting; try adding `{cache : false}` to the PouchDB constructor. (See [issue #1233](https://github.com/daleharvey/pouchdb/issues/1233) for details.) - -{% include anchor.html class="h3" title="Uncaught TypeError: object is not a function" hash="typeerror_object_is_not_a_function" %} - -Did you include the [es6-promise shim library](https://github.com/jakearchibald/es6-promise)? Not every browser implements ES6 Promises correctly. (See [issue #1747](https://github.com/daleharvey/pouchdb/issues/1747) for details.) - -{% include anchor.html class="h3" title="Uncaught TypeError: 'undefined' is not a function" hash="undefined_is_not_a_function" %} - -Did you include the [es5-shim library][es5shim]? In particular this shows up in PhantomJS because of [this bug](https://github.com/ariya/phantomjs/issues/10522). - -{% include anchor.html class="h3" title="SyntaxError: Parse error (Cordova on Android)" hash="cordova_android_parse_error" %} - -Did you include the [es5-shim library][es5shim]? PouchDB is written in ES5, which is supported by modern browsers, but requires shims for older browsers (e.g. IE 9, Android 2.1 WebView). - -In Android, if you're loading PouchDB directly via `webView.loadUrl('javascript://' + js')`, you should prefer the minified PouchDB javascript file to the unminified one, since code comments can also cause parse errors. - -{% include anchor.html class="h3" title="PouchDB object fails silently (Safari)" hash="safari_object_silent_fail" %} - -Safari requires users to confirm that they want to allow an app to store data locally ("Allow this website to use space on your disk?"). If PouchDB is loaded in an `iframe` or some other unusual way, the dialog might not be shown, and the database will silently fail. - -{% include anchor.html class="h3" title="window.localStorage is not available (Chrome apps)" hash="window_localstorage_chrome_apps" %} - -In Chrome apps, you'll see the warning "window.localStorage is not available in packaged apps. Use chrome.storage.local instead." This is harmless; since PouchDB doesn't use localStorage if it's not available. - -{% include anchor.html class="h3" title="Error: UnknownError (Firefox)" hash="unknown_error_ff" %} - -Are you using a webserver to host and run your code? This error can be caused by running your script/file locally using the `file:///` setting in Firefox, since Firefox does not [allow access to IndexedDB locally](https://bugzilla.mozilla.org/show_bug.cgi?id=643318). You can use the SimpleHTTPServer to deploy your script by running `python -m SimpleHTTPServer` from the directory containing the script, or use the Apache webserver and then access the script by using `http://localhost/{path_to_your_script}`. - -{% include anchor.html class="h3" title="DOM Exception 18 in Android pre-Kitkat WebView" hash="android_pre_kitkat" %} - -This applies to hybrid apps designed to run in Android pre-Kitkat (i.e. before 4.4). - -If you are directly using a `WebView` and not using Cordova/PhoneGap, you will probably either run into an error where PouchDB silently fails or you see `Error: SECURITY_ERR: DOM Exception 18` in the console. As a sanity test, you can run this JavaScript: - -```js -openDatabase('mydatabase', 1, 'mydatabase', 5000000, function (db) { console.log('it works!'); }); -``` - -If you see "it works" in the console, then everything's peachy. Otherwise there are a few things you have to do. - -First, make sure Web SQL is enabled on your `WebView` in the first place using [setDatabaseEnabled](http://developer.android.com/reference/android/webkit/WebSettings.html#setDatabaseEnabled%28boolean%29): - -```java -myWebView.getSettings().setDatabaseEnabled(true); -``` - -Second, specify a path for the database. Yes, you need to do this, even though it's deprecated in Kitkat: - -```java -String databasePath = getContext().getApplicationContext().getDir( - "database", Context.MODE_PRIVATE).getPath(); -webView.getSettings().setDatabasePath(databasePath); -``` - -Third, you'll need to set an `onExceededDatabaseQuota` handler. Yes, it's also deprecated in Kitkat. Yes, you still need to do it. - -```java -webView.setWebChromeClient(new WebChromeClient() { - - @Override - public void onExceededDatabaseQuota(String url, String databaseIdentifier, long currentQuota, long estimatedSize, - long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) { - quotaUpdater.updateQuota(estimatedSize * 2); - } -}); -``` - -If you skip any one of these three steps, then you will get the `DOM Exception 18` error. You need to do all three. - -Alternatively, you can also load the `WebView` with a fake `http://` URL, but this may cause other errors when you try to fetch files based on a relative path: - -```java -webView.loadDataWithBaseURL("http://www.example.com", - htmlContent, - "text/html", - "utf-8", - null); -``` - -[es5shim]: https://github.com/es-shims/es5-shim -[sqlite]: https://github.com/brodysoft/Cordova-SQLitePlugin
diff --git a/docs/external.md b/docs/external.md deleted file mode 100644 index 4f89c9c..0000000 --- a/docs/external.md +++ /dev/null
@@ -1,166 +0,0 @@ ---- -layout: 2ColLeft -title: Plugins and External Projects -sidebar: nav.html ---- - -Below is a list of known plugins, tools and projects can be used with PouchDB. [Fork this page](https://github.com/pouchdb/pouchdb/blob/master/docs/external.md) to add your own! - -{% include anchor.html title="Plugins" hash="plugins" %} - -#### [PouchDB allDbs()](https://github.com/nolanlawson/pouchdb-all-dbs) - -Revives the `allDbs()` function, which lists all PouchDB databases. - -#### [PouchDB Authentication](https://github.com/nolanlawson/pouchdb-authentication) - -Plugin for CouchDB's authentication system. - -#### [PouchDB Collate](https://github.com/pouchdb/collate) - -Collation utilities, so you can use complex keys as doc IDs. - -#### [Crypto Pouch](https://github.com/calvinmetcalf/crypto-pouch) - -Encrypt a PouchDB/CouchDB database. - -#### [Pouch Dat](https://github.com/calvinmetcalf/pouch-dat) - -Replicate from PouchDB to Dat. - -#### [Pouch Datalog](https://github.com/dahjelle/pouch-datalog) - -Implement the Datalog query language on PouchDB, with indexes. - -#### [PouchDB Dump](https://github.com/nolanlawson/pouchdb-dump-cli) and [PouchDB Load](https://github.com/nolanlawson/pouchdb-load) - -Dump a PouchDB/CouchDB to a file, then load it wholesale. Designed for fast initial replication. - -#### [Delta Pouch](https://github.com/redgeoff/delta-pouch) - -Implements the handy "every document is a delta" pattern, so you don't have to deal with conflicts. - -#### [Filter Pouch](https://github.com/nolanlawson/filter-pouch) - -Applies filter functions to documents before and after storage, e.g. for encryption, compression, or massaging data. - -#### [PouchDB GQL](https://github.com/pouchdb/GQL) - -Google Query Language (GQL) queries with PouchDB. ([Documentation](http://pouchdb.com/gql.html)) - -#### [PouchDB List](http://python-pouchdb.marten-de-vries.nl/plugins.html) - -Allows you to re-use your CouchDB list functions on the client side. ([Documentation](http://pythonhosted.org/Python-PouchDB/js-plugins.html#pouchdb-rewrite-plug-in)) - -#### [Pouch Mirror](https://github.com/colinskow/pouch-mirror) - -Creates a synced in-memory mirror of a remote CouchDB for faster reads. - -#### [PouchDB No-Eval Map/Reduce](https://github.com/evidenceprime/pouchdb.mapreduce.noeval) - -Allows you to use the `query()` API in environments that disallow `eval()`, like Chrome packaged apps. - -#### [Peer Pouch](https://github.com/natevw/PeerPouch) - -PouchDB over WebRTC. - -#### [PouchDB Quick Search](https://github.com/nolanlawson/pouchdb-quick-search) - -Full-text search engine on top of PouchDB. - -#### [Relational Pouch](https://github.com/nolanlawson/relational-pouch) - -A relational database API on top of PouchDB/CouchDB. - -#### [PouchDB Rewrite](http://python-pouchdb.marten-de-vries.nl/plugins.html) - -A PouchDB plugin that allows you to re-use your CouchDB rewrites on the client side. ([Documentation](http://pythonhosted.org/Python-PouchDB/js-plugins.html#pouchdb-list-plug-in)) - -#### [PouchDB Show](http://python-pouchdb.marten-de-vries.nl/plugins.html) - -A PouchDB plugin that allows you to re-use your CouchDB show functions on the client side. ([Documentation](http://pythonhosted.org/Python-PouchDB/js-plugins.html#pouchdb-show-plug-in)) - -#### [PouchDB Spatial](https://github.com/pouchdb/geopouch) - -Multidimensional and spatial queries with PouchDB. - -#### [Pouch Stream](https://github.com/calvinmetcalf/PouchStream) - -A plugin to let PouchDB talk streams. - -#### [PouchDB Update](http://python-pouchdb.marten-de-vries.nl/plugins.html) - -A PouchDB plugin that allows you to re-use your CouchDB update functions on the client side. ([Documentation](http://pythonhosted.org/Python-PouchDB/js-plugins.html#pouchdb-update-plug-in)) - -#### [PouchDB Validation](http://python-pouchdb.marten-de-vries.nl/plugins.html) - -A PouchDB plugin that allows you to re-use your CouchDB `validate_doc_update` functions on the client side. ([Documentation](http://pythonhosted.org/Python-PouchDB/js-plugins.html#pouchdb-validation-plug-in)) - -{% include anchor.html title="Server Side" hash="Server Side" %} - -#### [PouchDB Server](https://github.com/pouchdb/pouchdb-server) - -A standalone CouchDB-style REST interface server to PouchDB. - -#### [Express PouchDB](https://github.com/pouchdb/express-pouchdb) - -An express submodule with a CouchDB-style REST interface to PouchDB. Powers PouchDB Server. - -{% include anchor.html title="Framework adapters" hash="framework_adapters" %} - -### Angular - -#### [angular-pouchdb](https://github.com/wspringer/angular-pouchdb) - -Wrapper for using PouchDB within Angular.js. - -#### [Factoryng - AngularJS Adapter](https://github.com/redgeoff/factoryng) - -An all-in-one AngularJS factory that wraps PouchDB and Delta Pouch. - -#### [ngPouch](https://github.com/jrhicks/ngPouch) - -Angular service to persist remote connection settings and maintain continuous replication. - -#### [ng-pouchdb](https://github.com/danielzen/ng-pouchdb) - -AngularJS binding for PouchDB. - -### Backbone - -#### [Backbone PouchDB](https://github.com/jo/backbone-pouch) - -Backbone PouchDB Sync Adapter. - -### Ember - -#### [Ember Pouch](https://github.com/nolanlawson/ember-pouch) - -Ember Data adapter for PouchDB/CouchDB. - -#### [ember-pouchdb](https://github.com/taras/ember-pouchdb) - -Promisy PouchDB wrapper for Ember.js - -{% include anchor.html title="Other languages" hash="Other languages" %} - -#### [Python-PouchDB](http://python-pouchdb.marten-de-vries.nl/) -A Python interface to PouchDB, with both a synchronous and an asynchronous API. Uses QtWebKit internally (via either PySide, PyQt4 or PyQt5). Some PouchDB plugins are also wrapped. ([Documentation](http://pythonhosted.org/Python-PouchDB/) / [Launchpad](https://launchpad.net/python-pouchdb)) - -#### [PouchDroid](https://github.com/nolanlawson/PouchDroid/) - -Android adapter with a native Java interface to PouchDB. - -{% include anchor.html title="Tools" hash="Tools" %} - -#### [blob-util](https://github.com/nolanlawson/blob-util) - -Not strictly PouchDB-related, but a useful set of shims and utility functions for working with Blobs in the browser. - -#### [Puton](http://puton.jit.su/) - -A bookmarklet for inspecting PouchDB databases within the browser. ([Github](http://github.com/ymichael/puton)) - -#### [Revision Tree Visualizer](http://neojski.github.io/visualizeRevTree) - -A tool drawing revision tree of a couchdb document. You can see what is a conflict, which revisions are deleted and which is winning. ([Github](https://github.com/neojski/visualizeRevTree)) \ No newline at end of file
diff --git a/docs/faq.md b/docs/faq.md deleted file mode 100644 index 73872bf..0000000 --- a/docs/faq.md +++ /dev/null
@@ -1,143 +0,0 @@ ---- -layout: 2ColLeft -title: FAQ -sidebar: nav.html ---- - -{% include anchor.html class="h3" title="Can PouchDB sync with MongoDB/MySQL/my current non-CouchDB database?" hash="sync_non_couchdb" %} - - -No, your backend needs to speak the [CouchDB replication protocol](http://couchdb.readthedocs.org/en/latest/replication/protocol.html). The magic of PouchDB <–> CouchDB sync comes from this design, which in particular requires all documents to be versioned with the `_rev` marker. This allows PouchDB and CouchDB to [elegantly handle conflicts](http://writing.jan.io/2013/12/19/understanding-couchdb-conflicts.html), among other benefits. - -{% include anchor.html class="h3" title="What can PouchDB sync with?" hash="what_can_pouchdb_sync_with" %} - -There are a number of databases that implement a CouchDB-like protocol, and PouchDB should be able to replicate with them. They include: - - * [CouchDB](http://couchdb.apache.org/) – CouchDB is our primary reference database and is used for automated testing. - * [Cloudant](https://cloudant.com/) – A cluster-aware fork of CouchDB. - * [Couchbase Sync Gateway](http://www.couchbase.com/communities/couchbase-sync-gateway) – A sync gateway for Couchbase. - * [IrisCouch](http://iriscouch.com/) – CouchDB in the cloud. - * [PouchDB Server](https://github.com/pouchdb/pouchdb-server) – An HTTP API written on top of PouchDB. Additionally, it supports alternate backends like in-memory, Redis, Riak and MySQL via [the LevelUP ecosystem](https://github.com/rvagg/node-levelup/wiki/Modules#storage). Note that your application must use the PouchDB API rather than directly modifying the database, however. - -{% include anchor.html class="h3" title="The web is nice, but I want to build a native app?" hash="native_support" %} - -PouchDB is one of multiple projects that implement the CouchDB protocol, and these can all be used to sync the same set of data. - -For desktop applications, you may want to look into embedding CouchDB (or [rcouch](https://github.com/refuge/rcouch)). PouchDB also works great with web-based frameworks like [node-webkit](https://github.com/rogerwang/node-webkit), [Chrome apps](https://developer.chrome.com/apps/about_apps), [Atom Shell](https://github.com/atom/atom-shell) and [WinJS](http://try.buildwinjs.com/#listview). - -For mobile applications, you can use PouchDB within [PhoneGap](http://phonegap.com/)/[Cordova](http://cordova.apache.org/) (optionally using the [SQLite Plugin](https://github.com/brodysoft/Cordova-SQLitePlugin)), or there are several native libraries: - -**iOS**: - -* [Couchbase Lite for iOS](https://github.com/couchbase/couchbase-lite-ios) -* [Cloudant Sync for iOS](https://github.com/cloudant/CDTDatastore) - -**Android**: - -* [Couchbase Lite for Android](https://github.com/couchbase/couchbase-lite-android) -* [Cloudant Sync for Android](https://github.com/cloudant/sync-android) - -{% include anchor.html class="h3" title="How much data can PouchDB store?" hash="data_limits" %} - -In **Firefox**, PouchDB uses IndexedDB. Though Firefox has no upper limit besides disk space, if your application wishes to store more than 50MB locally, Firefox will [ask the user](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) to confirm that this is okay. - -**Chrome** also uses IndexedDB, it determines the amount of storage left available on the user’s hard drive and uses [that to calculate a limit](https://developers.google.com/chrome/whitepapers/storage#temporary). - -**Opera 15+** shares a codebase Chromium / Blink, and behaves similarly. - -**Internet Exporer 10+** has a hard 250MB limit. - -**Mobile Safari** on iOS has a hard 50MB limit, while **desktop Safari ≤7** will prompt the user if an application requests more than 5MB of data, up to a limit of 500MB. Some versions of Safari will only let you request additional storage once, but you can get around this using [the `size` option](http://pouchdb.com/api.html#create_database). - -**Android** works the same as Chrome as of 4.4+, while older version can store up to 200MB. - -In [PhoneGap](http://phonegap.com/)/[Cordova](http://cordova.apache.org/), you can have unlimited data on both iOS and Android by using the [SQLite Plugin](https://github.com/brodysoft/Cordova-SQLitePlugin). - -For more information, see [Working with quota on mobile browsers](http://www.html5rocks.com/en/tutorials/offline/quota-research/). - -{% include anchor.html class="h3" title="What data types does PouchDB support?" hash="data_types" %} - -PouchDB has two types of data: documents and attachments. - -#### Documents - -As in CouchDB, the documents you store must be serializable as JSON. Modifying the `Object` prototype or storing classes is not supported. - -IndexedDB will actually support non-JSON data (e.g. `Date`s aren't stringified), but you should not rely on this, because CouchDB, LevelDB, and Web SQL do not behave the same. - -#### Attachments - -PouchDB also supports attachments, which are the most efficient way to store binary data. Attachments may either be supplied as base64-encoded strings or as `Blob` objects. - -Different backends have different strategies for storing binary data, which may affect the overall database size. Attachment stubs have a `length` property that describes the number of bytes in the `Blob` object, but under the hood, it may actually take up more space than that. - -PouchDB's strategies are: - -* **Blob**: data is stored in a true binary format. The most efficient method. -* **UTF-16 Blob**: blobs are coerced to UTF-16, so they takes up 2x the normal space. -* **Base-64**: data is stored as a base-64-encoded string. The least efficient method. - -Here are the strategies used by various browsers in PouchDB: - -<div class="table-responsive"> -<table class="table"> -<tr> - <td></td> - <th><img src="static/img/browser-logos/internet-explorer_32x32.png" alt="IE"/></th> - <th><img src="static/img/browser-logos/firefox_32x32.png" alt="Firefox"/></th> - <th><img src="static/img/browser-logos/chrome_32x32.png" alt="Chrome"/></th> - <th><img src="static/img/browser-logos/chrome_32x32.png" alt="Chrome"/></th> - <th><img src="static/img/browser-logos/safari_32x32.png" alt="Safari"/></th> - <th><img src="static/img/browser-logos/safari_32x32.png" alt="Safari"/></th> -</tr> -<tr> - <th>Adapter</th> - <th>IE (10+)</th> - <th>Firefox</th> - <th>Chrome < 38, <br/>Android <= 4.4</th> - <th>Chrome >= 38</th> - <th>Safari < 7.1 <br/>iOS < 8</th> - <th>Safari >= 7.1, <br/>iOS >= 8</th> -</tr> -<tr> - <td>IndexedDB</td> - <td>Blob</td> - <td>Blob</td> - <td>Base-64</td> - <td>Blob</td> - <td></td> - <td></td> -</tr> -<tr> - <td>WebSQL</td> - <td></td> - <td></td> - <td>Blob</td> - <td>Blob</td> - <td>UTF-16 Blob</td> - <td>Blob</td> -</tr> -</table> -</div> - -Attachments are deduplicated based on their MD5 sum, so duplicate attachments won't take up extra space. - -To truly remove an attachment from the data store, you will need to use [compaction](http://pouchdb.com/api.html#compaction) to remove document revisions that reference that attachment. - -{% include anchor.html class="h3" title="Is it safe to upgrade PouchDB?" hash="safe_to_upgrade" %} - -Since v1.0.0, PouchDB has supported automatic schema migrations. This means that if you open a database that was built with an older version of PouchDB, the newer version will run all the steps necessary to get the old database up to date. We have extensive tests in place to guarantee that this feature works correctly. - -Even in the case of a major version release, PouchDB still performs the schema migrations. So for instance, you can create a database with PouchDB 1.0.0 and it will still work after you open it in 3.0.0. - -Once a database is migrated, however, you can no longer open it with an older version of PouchDB. So if an update contains a migration, it will be clearly marked in the release notes. - -{% include anchor.html class="h3" title="How is PouchDB different from CouchDB?" hash="couchdb_differences" %} - -PouchDB is also a CouchDB client, and you should be able to switch between a local database or an online CouchDB instance without changing any of your application's code. - -However, there are some minor differences to note: - -**View Collation** - CouchDB uses ICU to order keys in a view query; in PouchDB they are ASCII ordered. - -**View Offset** - CouchDB returns an `offset` property in the view results. In PouchDB, `offset` just mirrors the `skip` parameter rather than returning a true offset.
diff --git a/docs/getting-started.md b/docs/getting-started.md deleted file mode 100644 index 2edcfa6..0000000 --- a/docs/getting-started.md +++ /dev/null
@@ -1,208 +0,0 @@ ---- -layout: 2ColLeft -title: Getting Started Guide -sidebar: nav.html ---- - -In this tutorial we will write a basic Todo web application based on [TodoMVC](http://todomvc.com/) that syncs to an online CouchDB server. It should take around 10 minutes. - -{% include anchor.html class="h3" title="Video Tutorial" hash="video_tutorial" %} - -If you get stuck or just prefer video tutorials, this guide is available in video format: - -{% include iframe.html src="//www.youtube.com/embed/-Z7UF2TuSp0" %} - -{% include anchor.html class="h3" title="Download Assets" hash="download" %} - -We will start with a template of the project where all the data related functions have been replaced with empty stubs. Download and unzip [pouchdb-getting-started-todo.zip]({{ site.baseurl }}/static/assets/pouchdb-getting-started-todo.zip). When dealing with XHR and IndexedDB you are better off running web pages from a server as opposed to a filesystem. To do this you can run: - -{% highlight bash %} -$ cd pouchdb-getting-started-todo -$ python -m SimpleHTTPServer -{% endhighlight %} - -Then visit [http://127.0.0.1:8000/](http://127.0.0.1:8000/). If you see the following screenshot, you are good to go: - -<a href="{{ site.baseurl }}/static/img/screenshots/todo-1.png" style="display: block; text-align: center;"> - <img src="{{ site.baseurl }}/static/img/screenshots/todo-1.png" style="width:400px;"/> -</a> - -It's also a good idea to open your browser's console so you can see any errors or confirmation messages. - -{% include anchor.html class="h3" title="Installing PouchDB" hash="installing_pouchdb" %} - -Open `index.html` and include PouchDB in the app by adding a script tag: - -{% highlight html %} -<script src="//cdn.jsdelivr.net/pouchdb/{{site.version}}/pouchdb.min.js"></script> -<script src="js/base.js"></script> -<script src="js/app.js"></script> -{% endhighlight %} - -PouchDB is now installed in your app and ready to use! (In production, you should use a local copy of the script.) - -{% include anchor.html class="h3" title="Creating a database" hash="creating_a_database" %} - -The rest of the work will be done inside `app.js`. We will start by creating a database to enter your todos. To create a database simply instantiate a new PouchDB object with the name of the database: - -{% highlight js %} -// EDITING STARTS HERE (you dont need to edit anything above this line) - -var db = new PouchDB('todos'); -var remoteCouch = false; -{% endhighlight %} - -You don't need to create a schema for the database. After giving it a name, you can immediately start writing objects to it. - -{% include anchor.html class="h3" title="Write todos to the database" hash="write_todos_to_database" %} - -The first thing we shall do is start writing items to the database. The main input will call `addTodo` with the current text when the user presses `Enter`. We can complete this function with the following code: - -{% highlight js %} -function addTodo(text) { - var todo = { - _id: new Date().toISOString(), - title: text, - completed: false - }; - db.put(todo, function callback(err, result) { - if (!err) { - console.log('Successfully posted a todo!'); - } - }); -} -{% endhighlight %} - -In PouchDB each document is required to have a unique `_id`. Any subsequent writes to a document with the same `_id` will be considered updates. Here we are using a date string as an `_id`. For our use case, it will be unique, and it can also be used to sort items in the database. You can use `db.post()` if you want random ids. The `_id` is the only thing required when creating a new document. The rest of the object you can create as you like. - -The `callback` function will be called once the document has been written (or failed to write). If the `err` argument is not null, then it will have an object explaining the error, otherwise the `result` will hold the result. - -{% include anchor.html class="h3" title="Show items from the database" hash="show_database_items" %} - -We have included a helper function `redrawTodosUI` that takes an array of todos to display, so all we need to do is read the todos from the database. Here we will simply read all the documents using `db.allDocs`. The `include_docs` option tells PouchDB to give us the data within each document, and the `descending` option tells PouchDB how to order the results based on their `_id` field, giving us newest first. - -{% highlight js %} -function showTodos() { - db.allDocs({include_docs: true, descending: true}, function(err, doc) { - redrawTodosUI(doc.rows); - }); -} -{% endhighlight %} - -Once you have included this code, you should be able to refresh the page to see any todos you have entered. - -{% include anchor.html class="h3" title="Update the UI" hash="update_the_ui" %} - -We dont want to refresh the page to see new items. More typically you would update the UI manually when you write data to it, however, in PouchDB you may be syncing data remotely, so you want to make sure you update whenever the remote data changes. To do this we will call `db.changes` which subscribes to updates to the database, wherever they come from. You can enter this code between the `remoteCouch` and `addTodo` declaration: - -{% highlight js %} -var remoteCouch = false; - -db.changes({ - since: 'now', - live: true -}).on('change', showTodos); - -// We have to create a new todo document and enter it in the database -function addTodo(text) { -{% endhighlight %} - -So every time an update happens to the database, we redraw the UI to show the new data. The `live` flag means this function will continue to run indefinitely. Now try entering a new todo and it should appear immediately. - -{% include anchor.html class="h3" title="Edit a todo" hash="edit_a_todo" %} - -When the user checks a checkbox, the `checkboxChanged` function will be called, so we'll fill in the code to edit the object and call `db.put`: - -{% highlight js %} -function checkboxChanged(todo, event) { - todo.completed = event.target.checked; - db.put(todo); -} -{% endhighlight %} - -This is similiar to creating a document, however the document must also contain a `_rev` field (in addition to `_id`), otherwise the write will be rejected. This ensures that you dont accidently overwrite changes to a document. - -You can test that this works by checking a todo item and refreshing the page. It should stay checked. - -{% include anchor.html class="h3" title="Delete an object" hash="delete_an_object" %} - -To delete an object you can call db.remove with the object. - -{% highlight js %} -function deleteButtonPressed(todo) { - db.remove(todo); -} -{% endhighlight %} - -Similiar to editing a document, both the `_id` and `_rev` properties are required. You may notice that we are passing around the full object that we previously read from the database. You can of course manually construct the object, like: `{_id: todo._id, _rev: todo._rev}`, but passing around the existing object is usually more convenient and less error prone. - -{% include anchor.html class="h3" title="Complete rest of the Todo UI" hash="complete_todo_ui" %} - -`todoBlurred` is called when the user edits a document. Here we'll delete the document if the user has entered a blank title, and we'll update it otherwise. - -{% highlight js %} -function todoBlurred(todo, event) { - var trimmedText = event.target.value.trim(); - if (!trimmedText) { - db.remove(todo); - } else { - todo.title = trimmedText; - db.put(todo); - } -} -{% endhighlight %} - -{% include anchor.html class="h3" title="Installing CouchDB" hash="installing_couchdb" %} - -Now we'll implement the syncing. You need to have a CouchDB instance, which you can either install yourself [CouchDB(1.3+) locally](http://couchdb.apache.org/) or use with an online provider like [IrisCouch](http://iriscouch.com). - -{% include anchor.html class="h3" title="Enabling CORS" hash="enabling_cors" %} - -To replicate directly with CouchDB, you need to make sure CORS is enabled. Only set the username and password if you have set them previously. By default, CouchDB will be installed in "Admin Party," where username and password are not needed. You will need to replace `myname.iriscouch.com` with your own host (`127.0.0.1:5984` if installed locally): - -You can enable CORS in CouchDB using `curl` or the Futon web interface, but we've saved you some time by making a Node script called [add-cors-to-couchdb](https://github.com/pouchdb/add-cors-to-couchdb). Just run: - -{% highlight bash %} -$ npm install -g add-cors-to-couchdb -$ add-cors-to-couchdb -{% endhighlight %} - -Or if your database is not at `127.0.0.1:5984`: - -{% highlight bash %} -$ add-cors-to-couchdb http://me.iriscouch.com -u myusername -p mypassword -{% endhighlight %} - -You can check that CORS is now enabled by visiting [http://localhost:5984/_utils/config.html](http://localhost:5984/_utils/config.html) in your browser. You should see something like this: - - - -{% include anchor.html class="h3" title="Implement basic two way sync" hash="basic_two_way_sync" %} - -Now we will have the todo list sync. Back in `app.js` we need to specify the address of the remote database. Remember to replace `user`, `pass` and `myname.iriscouch.com` with the credentials of your own CouchDB instance: - -{% highlight js %} -// EDITING STARTS HERE (you dont need to edit anything above this line) - -var db = new PouchDB('todos'); -var remoteCouch = 'http://user:pass@mname.iriscouch.com/todos'; -{% endhighlight %} - -Then we can implement the sync function like so: - -{% highlight js %} -function sync() { - syncDom.setAttribute('data-sync-state', 'syncing'); - var opts = {live: true}; - db.replicate.to(remoteCouch, opts, syncError); - db.replicate.from(remoteCouch, opts, syncError); -} -{% endhighlight %} - -`db.replicate()` tells PouchDB to transfer all the documents `to` or `from` the `remoteCouch`. This can either be a string identifier or a PouchDB object. We call this twice: once to receive remote updates, and once to push local changes. Again, the `live` flag is used to tell PouchDB to carry on doing this indefinitely. The callback will be called whenever this finishes. For live replication, this will mean an error has occured, like losing your connection or you canceled the replication. - -You should be able to open [the todo app](http://127.0.0.1:8000) in another browser and see that the two lists stay in sync with any changes you make to them. You may also want to look at your CouchDB's Futon administration page and see the populated database. - -{% include anchor.html class="h3" title="Congratulations!" hash="congratulations" %} - -You've completed your first PouchDB application. This is a basic example, and a real world application will need to integrate more error checking, user signup, etc. But you should now understand the basics you need to start working on your own PouchDB project. If you have any more questions, please get in touch on [IRC](irc://freenode.net#pouchdb) or the [mailing list](https://groups.google.com/forum/#!forum/pouchdb).
diff --git a/docs/gql.md b/docs/gql.md deleted file mode 100644 index d6d3b1d..0000000 --- a/docs/gql.md +++ /dev/null
@@ -1,285 +0,0 @@ ---- -layout: 2ColLeft -title: GQL Documentation -sidebar: nav.html ---- - -The Google Query Language (GQL) interface provides an alternative method for accessing data. -The version of GQL implemented here is based on the Google Visualization API Query Language -(https://developers.google.com/chart/interactive/docs/querylanguage). -The syntax of GQL queries should be familiar to those who have used SQL, -but the capabilities of GQL are much more limited. - -GQL queries are performed by passing a query object to the gql method along with a callback. -Callbacks are in the node.js idiom of `function(err, data)` Where the first argument will be undefined -unless there is an error, and further arguments specify the result. -Note that only identifiers and string literals are case-sensitive. - -### Language Syntax - - * [Select](#select) - * [Where](#where) - * [Group By](#groupBy) - * [Pivot](#pivot) - * [Label](#label) - * [Functions](#functions) - * [Aggregation Functions](#aggregation_functions) - * [Scalar Functions](#scalar_functions) - * [Arithmetic Operators](#arithmetic_operators) - * [Miscellaneous](#miscellaneous) - * [Literals](#literals) - * [Identifiers](#identifiers) - * [Reserved Words](#reserved_words) - -## Perform a Query - - db.gql(query, [options], [callback]) - -Although only the query is mandatory, the callback is required to access the query result. -Currently no query options are implemented. - - var pouchdb; - PouchDB('idb://test', function(err, db) { - pouchdb = db; - // Use pouchdb to call further functions - db.gql({select: "*", where: "type='Fire' and name is not null"}, function(err, result){ - if(!err){ - // Use the results of the query here - } - } - }) - -## Select - - db.gql({select: "`name!`, price-discount, upper(vendor)"}, callback) - -Select returns an object for each document in the database (unless limited by another clause). -Each of these objects will be populated with the properties specified in the select clause. -Arithmetic operators, aggregation functions, and scalar functions are all fair game. -Properties that are missing from an object in the database are assigned null. - -With these documents in the database - - {name!: "pencil", price: 2, discount: 0.7, vendor: "store1"}, - {name!: "pen", price:3, discount: 2, vendor: "store2"} - -The above query will return - - {name!: "pen", price - discount: 1, upper(vendor): "STORE2"}, - {name!: "pencil", price - discount: 1.3, upper(vendor): "STORE1"} - - -## Where - - db.gql({select: "*", where: "type='Fire' and name is not null"}, callback) - -Where allows filtering of the objects that are passed to the select clause. In this way, unwanted documents -can be excluded from the query result. The where clause is composed of conditions which are joined by the -logical operators AND and OR. An additional operator, NOT, provides negation. - -Comparison operators can be used in conditions to perform comparisons. The supported comparison operators are -<=, <, >, >=, !=, and <>. != and <> are equivalent. Null is treated slightly differently; to check if -something is null IS NULL is used. To check if something is not null, IS NOT NULL is used. - -With these documents in the database - - {name: "charmander", type: "Fire"}, - {type: "Fire", attack:"tail whip"}, - {name: "charizard", type: "Fire", attack:"slash"} - -The above query will return - - {_id: "0D715E2C-CEDD-46B4-A060-9C9C290BEBE8", _rev: "1-71d1e0f8ab00cf432306890a4116602b", - attack: "slash", name: "charizard", type: "Fire"}, - {_id: "3153F94B-0568-4D4C-BFA1-83EDF6185915" _rev: "1-d24f7405c5a63943391eaff9a260139c", - name: "charmander", type: "Fire"} - -Note the inclusion of the \_rev and \_id fields. This is the result of using 'select \*' instead of naming the -desired fields explicitly. - -## Group By - - db.gql({select: "max(charizard), charmeleon", groupBy: "charmeleon"}, callback) - -Group by creates one object for each unique combination of values in the group by clause. For the query above, -if every document in the database had the value "Level 22" for the property "charmeleon", only a single -object would be generated. - -If a group by clause is present, every identifier in the select clause must either be the argument of an -aggregation function or present in the group by clause. Otherwise, the composite objects formed by the group by -clause could have multiple values for some identifiers. - -With these documents in the database - - {charizard: 50, charmander: 24, charmeleon: 2, haunter:true}, - {charizard: 40, charmeleon: 2, charmander: 50}, - {charizard: 7, charmeleon: 20, charmander: 15} - -The above query will return - - {charmeleon: 2, max(charizard): 50} - {charmeleon: 20, max(charizard): 7} - -## Pivot - - db.gql({select: "max(charizard)", pivot: "charmeleon"}, callback) - -Pivot is essentially group by for properties. Each distinct value in the pivot clause gets its own property. -Unless used with group by, the result will have only a single document. - -The same restriction for group by applies here; every identifier in the select clause must either be the -argument of an aggregation function or preset in the group by clause. Additionally, identifiers in the pivot -clause may not be used in the group by clause. - -Note that using pivot will generate novel property names. See below for an example. - -With these documents in the database - - {charizard: 50, charmeleon: "hello"}, - {charizard: 40, charmeleon: "hello"}, - {charizard: 7, charmeleon: "world", charmander: 15} - -The above query will return - - {'hello max(charizard)': 50, 'world max(charizard)': 7} - -## Label - - db.gql({select: 'upper(dept), charizard', - label: "upper(dept) 'Department', charizard 'Maximum Charizard!'"}, callback) - -Label is used to transform cryptic identifiers into something that can be displayed directly to the end user. -Items in the label clause can be identifiers, aggregation functions, scalar functions, or operators. The label -clause is composed of any number of statement label pairs, where the statement corresponds to some statement in -the select clause and the label is a string literal. - -With these documents in the database - - {charizard: 50, dept: "eng", lunch:"2"}, - {charizard: 40, lunch: "1", dept: "market"},· - {charizard: 99, dept: "eng", lunch: 1}, - {charizard: 7, dept: "eng", lunch: 2} - -The above query will return - - {Department: "ENG", Maximum Charizard!: 7}, - {Department: "ENG", Maximum Charizard!: 99}, - {Department: "MARKET", Maximum Charizard!: 40}, - {Department: "ENG", Maximum Charizard!: 50} - -## Functions - -GQL contains a number of operators and functions that can operate on retrived documents. - -### Aggregation Functions - - db.gql({select: "max(charizard), min(charizard), average(charizard), count(charizard), sum(charizard)"}, - callback) - -The currently supported aggregation functions are avg, count, max, min, and sum. Each of these takes a single -statement as an argument. A statement can be composed of one or more identifiers joined by operators. -Avg and sum expect their arguments to evaluate to numbers; the other aggregators will accept any type of input. -Aggregation functions operate on entire identifiers, returning only a single property. Aggregation functions -may only appear in the select and label clauses. - -With these documents in the database - - {charizard: 50}, - {charizard: 40}, - {charizard: 7} - -The above query will return - - {average(charizard): 32.333333333333336, count(charizard): 3, max(charizard): 50, - min(charizard): 7, sum(charizard): 97} - -### Scalar Functions - - db.gql({select: "`name!`, price-discount, upper(vendor)"}, callback) - -Currently only two scalar functions are supported, upper and lower. These change the characters in their inputs -to uppercase and lowercase respectively. Unlike aggregator functions, scalar functions take only a single -identifier as their input. Scalar functions may only appear in the select and label clauses. - -With these documents in the database - - {name!: "pencil", price: 2, discount: 0.7, vender: "store1"}, - {name!: "pen", price:3, discount: 2, vendor: "store2"} - -The above query will return - - {name!: "pen", price - discount: 1, upper(vendor): "STORE2"}, - {name!: "pencil", price - discount: 1.3, upper(vendor): "STORE1"} - - -### Arithmetic Operators - - db.gql({select: "*", where: "charizard <=charmander * charmeleon + 2 and (charmander - 7 != 24/3)"}, - callback) - -Arithmetic operators are used to perform basic math on the values from documents. Their arguments must be -numbers. Arithmetic operators may only appear in the select, label, and where clauses. The arguments are -implicitly upcast to floats if necessary. The supported arithmetic operators are: - -* Addition: '+' -* Subtraction: '-' -* Multiplication: '\*' -* Division: '/' - - -With these documents in the database - - {charizard: 50, charmander: 24, charmeleon: 2, haunter:true}, - {charizard: 40, charmeleon: .5, charmander: 50}, - {charizard: 7, charmeleon: 20, charmander: 15} - -The above query will return - - {charizard: 50, charmander: 24, charmeleon: 2, haunter: true} - -## Miscellaneous - -Some features that are not covered in other sections. - -### Literals - -Literals are used for comparison or arithmetic. These are the supported literals: - -* string: Any characters surrounded by single or double quotes -* number: Numbers in regular decimal form. They may have a single period, a single negative sign, and no commas -* boolean: Either true or false - -### Identifiers - -Identifiers correspond to the properties of documents in the database. There are strict rules governing the -way that identifiers can be expressed in queries. If your identifier has spaces, is a reserved word, contains -any characters that are not letters or numbers or underscores, or starts with a digit, it must be surrounded -by backquotes \(\`identifier\`\). - -### Reserved Words - -This is the current list of reserved words. Because the GQL implementation is currently under development, -this list is likely to grow over time. - - and - asc - by - date - datetime - desc - false - format - group - label - limit - not - offset - options - or - order - pivot - select - timeofday - timestamp - true - where
diff --git a/docs/index.md b/docs/index.md deleted file mode 100644 index 950de91..0000000 --- a/docs/index.md +++ /dev/null
@@ -1,127 +0,0 @@ ---- -layout: default -title: PouchDB, the JavaScript Database that Syncs! ---- - -<div class="intro"> - - <div class="container"> - - <div class="row"> - - <div class='col-sm-6'> - - <h1>The Database that Syncs!</h1> - - <p>PouchDB is an open-source JavaScript database inspired by <a href="http://couchdb.apache.org/">Apache CouchDB</a> that is designed to run well within the browser.</p> - - <p>PouchDB was created to help web developers build applications that work as well offline as they do online.<br> - <p>It enables applications to store data locally while offline, then synchronize it with CouchDB and compatible servers when the application is back online, keeping the user's data in sync no matter where they next login.</p> - - <a href="{{ site.baseurl }}/learn.html" class="btn btn-primary btn-lg">Learn more</a> - - </div> - - <div class='col-sm-6'> - -{% highlight js %} -var db = new PouchDB('dbname'); - -db.put({ - _id: 'dave@gmail.com', - name: 'David', - age: 67 -}); - -db.changes().on('change', function() { - console.log('Ch-Ch-Changes'); -}); - -db.replicate.to('http://example.com/mydb'); -{% endhighlight %} - - </div> - - </div> - - </div> - -</div> - -<div class="infoblocks"> - - <div class="container"> - - <div class='row'> - - - <div class='block col-sm-6 col-md-3'> - - <div class="icon icon-node"></div> - - <h3>Cross Browser</h3> - <p>Works in Firefox, Chrome, Opera, Safari, IE and Node.js</p> - - </div> - - <div class='block col-sm-6 col-md-3'> - - <div class="icon icon-light"></div> - - <h3>Lightweight</h3> - <p>PouchDB is just a script tag and 34KB (gzipped) away in the browser, or <code>$ npm install pouchdb</code> away - in Node.</p> - - </div> - - <div class='block col-sm-6 col-md-3'> - - <div class="icon icon-learn"></div> - - <h3>Easy to Learn</h3> - <p>Requires some programming knowledge, however PouchDB is a piece of cake to learn.</p> - - </div> - - <div class='block col-sm-6 col-md-3'> - - <div class="icon icon-open"></div> - - <h3>Open Source</h3> - <p>Everything is developed out in the open on Github, contributors always welcome!</p> - - </div> - - </div> - </div> - -</div> - -<div class="blog"> - - <div class="container"> - - <h3>Latest</h3> - - <div class="row"> - -{% for post in site.posts limit:2 %} - -<div class="col-md-6"> - - - <p><a class='h4' href='{{ site.baseurl }}{{ post.url }}'>{{ post.title }}</a></p> - -{% include post_details.html %} - - </div> - -{% endfor %} - - </div> - - <a class="btn btn-primary btn-lg" href="/blog/index.html">View more</a> - - </div> - -</div>
diff --git a/docs/learn.md b/docs/learn.md deleted file mode 100644 index a75d39a..0000000 --- a/docs/learn.md +++ /dev/null
@@ -1,56 +0,0 @@ ---- -layout: 2ColLeft -title: About PouchDB -sidebar: nav.html ---- - -PouchDB was written to help web developers build applications that work offline as well as they do online. Applications save data locally, so the user can use all the features of an app even when they're offline. Plus, the data is synchronized between clients, so the user has up-to-date data wherever they go. - -PouchDB is a free open-source project, written in JavaScript by these [wonderful contributors](https://github.com/daleharvey/pouchdb/graphs/contributors) and inspired by <a href="http://couchdb.apache.org/">Apache CouchDB</a>. If you want to get involved then check out the [contributing guide](https://github.com/daleharvey/pouchdb/blob/master/CONTRIBUTING.md). - -{% include anchor.html class="h3" title="Browser Support" hash="browser_support" %} - -PouchDB uses various backends so it can work across different browsers and in Node.js. It uses IndexedDB in Firefox/Chrome/Opera/IE, WebSQL in Safari and most mobile browsers, and LevelDB in Node.js. It is currently tested and fully supported in: - - * Firefox latest stable (v29+) - * Chrome latest stable (v34+) - * Desktop Safari latest stable (v6+) - * Internet Explorer (v10+) - * Opera latest stable (v21+) - * Android 4.0+ - * iOS Safari latest stable (v7.1+) - * [Node.js](http://nodejs.org/) - -PouchDB is experimental on Android 2.x and various mobile browsers and environments including [Apache Cordova](http://cordova.apache.org/). It is known to work, but you may run into issues. As we resolve these issues we will update the fully supported list. - -PouchDB requires an ES5 environment. If your browser does not support this (IE <= 9, Android < 4.0, Opera Mini), then you will need to include the [es5-shim](https://github.com/es-shims/es5-shim) library. - -{% include anchor.html class="h3" title="Installing" hash="installing" %} - -PouchDB is designed to be a minimal library that is suitable for mobile devices, tablets, desktops — anything that runs Javascript. To start using PouchDB in your website, you simply [download][latest] it and include it in your webpage. - - [latest]: https://github.com/daleharvey/pouchdb/releases/download/{{ site.version }}/pouchdb-{{ site.version }}.min.js - -{% highlight html %} -<script src="pouchdb-{{ site.version }}.min.js"></script> -{% endhighlight %} - -#### Downloads - -Latest and greatest: [pouchdb-{{ site.version }}.min.js][latest] - -PouchDB is also hosted on [jsdelivr](http://www.jsdelivr.com/#!pouchdb) and [cdnjs](https://cdnjs.com/libraries/pouchdb). - -For past releases and changelog, check out the [Github releases page](https://github.com/daleharvey/pouchdb/releases). - -#### Node.js - -If you are using Node.js then run - -{% highlight bash %}$ npm install pouchdb{% endhighlight %} - -For an HTTP API to PouchDB check out [PouchDB Server](https://github.com/nick-thompson/pouchdb-server). - -{% include anchor.html class="h3" title="Using PouchDB" hash="using_pouchdb" %} - -To get started using PouchDB, check out our [Getting Started Tutorial](getting-started.html), [Guides](/guides/) and the [API Documentation](api.html). \ No newline at end of file
diff --git a/docs/manifest.appcache b/docs/manifest.appcache deleted file mode 100644 index 1d09794..0000000 --- a/docs/manifest.appcache +++ /dev/null
@@ -1,58 +0,0 @@ ---- ---- - -CACHE MANIFEST -# rev {{ site.time }} - -CACHE: -{% for page in site.pages %}{% if page.url != '/manifest.appcache' %}{{ page.url | replace:'index.html','' }}{% endif %} -{% endfor %} -{% for page in site.guides %}{{ page.url | replace:'index.html','' }} -{% endfor %} -{% for page in site.posts %}{{ page.url | replace:'index.html','' }} -{% endfor %} - -/static/css/pouchdb.css -/static/favicon.ico - -http://code.jquery.com/jquery.min.js -http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js - -http://fonts.googleapis.com/css?family=Lato:400,700|Open+Sans:400,700 -http://fonts.gstatic.com/s/lato/v11/8qcEw_nrk_5HEcCpYdJu8BTbgVql8nDJpwnrE27mub0.woff2 -http://fonts.gstatic.com/s/lato/v11/MDadn8DQ_3oT6kvnUq_2rxTbgVql8nDJpwnrE27mub0.woff2 -http://fonts.gstatic.com/s/lato/v11/rZPI2gHXi8zxUjnybc2ZQFKPGs1ZzpMvnHX-7fPOuAc.woff2 -http://fonts.gstatic.com/s/lato/v11/MgNNr5y1C_tIEuLEmicLm1KPGs1ZzpMvnHX-7fPOuAc.woff2 -http://fonts.gstatic.com/s/opensans/v10/u-WUoqrET9fUeobQW7jkRZBw1xU1rKptJj_0jans920.woff2 -http://fonts.gstatic.com/s/opensans/v10/cJZKeOuBrn4kERxqtaUH3ZBw1xU1rKptJj_0jans920.woff2 -http://fonts.gstatic.com/s/opensans/v10/k3k702ZOKiLJc3WVjuplzCYtBUPDK3WL7KRKS_3q7OE.woff2 -http://fonts.gstatic.com/s/opensans/v10/k3k702ZOKiLJc3WVjuplzBampu5_7CjHW5spxoeN3Vs.woff2 - -/static/img/apple-indexeddb.png -/static/img/cors_in_couchdb.png -/static/img/fauxton.png -/static/img/kittens.jpg -/static/img/logo.svg -/static/img/safari_popup.png -/static/img/dev_tools.png -/static/img/icons.svg -/static/img/kittens_small.jpg -/static/img/mark.svg -/static/img/screenshots/todo-1.png -/static/img/travis-screenshot.png - -/static/img/browser-logos/android_32x32.png -/static/img/browser-logos/chrome-android_32x32.png -/static/img/browser-logos/firefox_32x32.png -/static/img/browser-logos/internet-explorer_32x32.png -/static/img/browser-logos/safari-ios_32x32.png -/static/img/browser-logos/blackberry_32x32.png -/static/img/browser-logos/chrome_32x32.png -/static/img/browser-logos/internet-explorer-tile_32x32.png -/static/img/browser-logos/opera_32x32.png -/static/img/browser-logos/safari_32x32.png - -NETWORK: -* -http://* -https://* \ No newline at end of file
diff --git a/docs/static/assets/pouchdb-getting-started-todo.zip b/docs/static/assets/pouchdb-getting-started-todo.zip deleted file mode 100644 index 3ff9a51..0000000 --- a/docs/static/assets/pouchdb-getting-started-todo.zip +++ /dev/null Binary files differ
diff --git a/docs/static/favicon.ico b/docs/static/favicon.ico deleted file mode 100644 index 99c00b8..0000000 --- a/docs/static/favicon.ico +++ /dev/null Binary files differ
diff --git a/docs/static/img/apple-indexeddb.png b/docs/static/img/apple-indexeddb.png deleted file mode 100644 index 56e381d..0000000 --- a/docs/static/img/apple-indexeddb.png +++ /dev/null Binary files differ
diff --git a/docs/static/img/browser-logos/android_32x32.png b/docs/static/img/browser-logos/android_32x32.png deleted file mode 100644 index e22e823..0000000 --- a/docs/static/img/browser-logos/android_32x32.png +++ /dev/null Binary files differ
diff --git a/docs/static/img/browser-logos/blackberry_32x32.png b/docs/static/img/browser-logos/blackberry_32x32.png deleted file mode 100644 index 293f3b9..0000000 --- a/docs/static/img/browser-logos/blackberry_32x32.png +++ /dev/null Binary files differ
diff --git a/docs/static/img/browser-logos/chrome-android_32x32.png b/docs/static/img/browser-logos/chrome-android_32x32.png deleted file mode 100644 index f6bdc03..0000000 --- a/docs/static/img/browser-logos/chrome-android_32x32.png +++ /dev/null Binary files differ
diff --git a/docs/static/img/browser-logos/chrome_32x32.png b/docs/static/img/browser-logos/chrome_32x32.png deleted file mode 100644 index aee7b2c..0000000 --- a/docs/static/img/browser-logos/chrome_32x32.png +++ /dev/null Binary files differ
diff --git a/docs/static/img/browser-logos/firefox_32x32.png b/docs/static/img/browser-logos/firefox_32x32.png deleted file mode 100644 index d9ab1b8..0000000 --- a/docs/static/img/browser-logos/firefox_32x32.png +++ /dev/null Binary files differ
diff --git a/docs/static/img/browser-logos/internet-explorer-tile_32x32.png b/docs/static/img/browser-logos/internet-explorer-tile_32x32.png deleted file mode 100644 index d756425..0000000 --- a/docs/static/img/browser-logos/internet-explorer-tile_32x32.png +++ /dev/null Binary files differ
diff --git a/docs/static/img/browser-logos/internet-explorer_32x32.png b/docs/static/img/browser-logos/internet-explorer_32x32.png deleted file mode 100644 index 14d307a..0000000 --- a/docs/static/img/browser-logos/internet-explorer_32x32.png +++ /dev/null Binary files differ
diff --git a/docs/static/img/browser-logos/opera_32x32.png b/docs/static/img/browser-logos/opera_32x32.png deleted file mode 100644 index 6009cc6..0000000 --- a/docs/static/img/browser-logos/opera_32x32.png +++ /dev/null Binary files differ
diff --git a/docs/static/img/browser-logos/safari-ios_32x32.png b/docs/static/img/browser-logos/safari-ios_32x32.png deleted file mode 100644 index 92aebe1..0000000 --- a/docs/static/img/browser-logos/safari-ios_32x32.png +++ /dev/null Binary files differ
diff --git a/docs/static/img/browser-logos/safari_32x32.png b/docs/static/img/browser-logos/safari_32x32.png deleted file mode 100644 index d98bbec..0000000 --- a/docs/static/img/browser-logos/safari_32x32.png +++ /dev/null Binary files differ
diff --git a/docs/static/img/cors_in_couchdb.png b/docs/static/img/cors_in_couchdb.png deleted file mode 100644 index 353109d..0000000 --- a/docs/static/img/cors_in_couchdb.png +++ /dev/null Binary files differ
diff --git a/docs/static/img/debug_mode.png b/docs/static/img/debug_mode.png deleted file mode 100644 index 52b5edd..0000000 --- a/docs/static/img/debug_mode.png +++ /dev/null Binary files differ
diff --git a/docs/static/img/dev_tools.png b/docs/static/img/dev_tools.png deleted file mode 100644 index 54ff47c..0000000 --- a/docs/static/img/dev_tools.png +++ /dev/null Binary files differ
diff --git a/docs/static/img/fauxton.png b/docs/static/img/fauxton.png deleted file mode 100644 index a808445..0000000 --- a/docs/static/img/fauxton.png +++ /dev/null Binary files differ
diff --git a/docs/static/img/icons.svg b/docs/static/img/icons.svg deleted file mode 100644 index 0cfcc42..0000000 --- a/docs/static/img/icons.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" version="1.2" width="729.162" height="86.576"><path d="M30.99 7.92c1.113-.643 2.485-.643 3.598 0l28.651 16.749c1.115.643 1.801 1.831 1.801 3.118v31.037c0 1.286-.686 2.474-1.799 3.118l-28.649 16.685c-1.115.642-2.487.642-3.602 0l-6.981-4.281m-2.691-43.258v33.976c0 1.503-4.207 3.181-6.174 2.886-4.121-.829-8.312-3.459-12.476-5.909-1.114-.643-1.8-1.833-1.8-3.118v-31.139c0-1.287.686-2.474 1.801-3.117l28.32-16.749m20.659 29.368c-.705-7.353-7.872-6.97-11.986-6.95-3.794.019-9.143.821-9.219 6.677-.064 4.915 6.457 5.486 10.298 6.001 4.958.665 11.894 1.26 12.086 6.547.136 3.722-3.505 7.566-10.647 7.566-12.231 0-12.892-7.353-12.892-7.353m254.339-25.583h40.916m-40.916 9.223h40.916m-40.916 9.419h40.916m9.368-25.273c-6.569-6.964-17.361-11.51-29.577-11.51-20.023 0-36.255 12.205-36.255 27.27 0 10.151 7.375 19.003 18.31 23.7.487 1.592 1.696 4.727 3.133 6.751 1.593 2.244 5.925 5.755 5.925 5.755s.049-5.629.049-8.183c.327-.571.52-.797 1.166-.923 1.483 0 3.489.039 4.225.049 1.133.08 2.287.121 3.448.121 2.4 0 4.724-.175 6.994-.51m22.583-42.52c4.198 4.45 6.678 9.886 6.678 15.76 0 13.259-12.595 24.303-29.261 26.76 6.569 6.964 17.361 11.51 29.577 11.51 1.161 0 2.315-.041 3.448-.121.736-.01 2.743-.049 4.225-.049.646.126.839.351 1.166.923 0 2.555.049 8.183.049 8.183s4.332-3.511 5.925-5.755c1.437-2.024 2.646-5.158 3.133-6.751 10.934-4.697 18.31-13.549 18.31-23.7 0-15.065-16.232-27.27-36.255-27.27-2.4 0-4.724.175-6.994.51zm-260.318 66.383s2.774-5.474 4.362-8.096c2.632-4.346 5.497-8.585 8.54-12.626 7.201-9.561 15.882-18.062 25.179-25.601 4.34-3.519 10.795-8.292 16.474-12.032 10.087-6.645 31.187-18.45 31.187-18.45s-20.82 12.746-30.759 19.603c-5.607 3.868-11.916 9.003-16.161 12.507-9.288 7.667-18.092 16.125-25.392 25.704-2.925 3.837-5.548 7.77-8.017 11.851-1.487 2.458-4.081 7.591-4.081 7.591zm9.508-15.37c-2.436-2.821-4.572-4.207-4.572-4.207s1.902-.14 3.599 1.481c0 0-1.356-3.501-1.971-6.354-.607-2.817-.238-5.782-.07-6.563.55 1.595 2.676 5.39 2.676 5.39s-.577-5.447-.156-8.061c.421-2.612 1.243-7.246 1.654-7.754-.116 1.158 2.342 7.401 2.342 7.401s-.243-5.451.793-7.879c2.416-5.658 11.987-14.035 11.987-14.035s-.521 2.672-.614 4.026c-.196 2.834.39 6.023.39 6.023s.425-4.803 1.216-8.374c.29-1.313 1.188-3.854 1.188-3.854l.513 2.372s.919-2.198 1.678-3.091c3.893-4.576 14.256-11.029 14.256-11.029s-.61 3.033-.216 5.735c.391 2.682.789 5.306.821 5.115.028-.169.113-4.282.568-6.362.577-2.641 2.714-7.641 2.714-7.641l.175 1.629s.553-.83.929-1.147c2.091-1.769 7.154-4.043 7.154-4.043s.138 3.939.566 5.852c.215.959.995 2.774.995 2.774s-.115-1.938-.115-2.908c-.001-2.442.286-7.32.286-7.32s4.717-1.57 7.166-1.894c2.208-.292 6.681-.029 6.681-.029s.514 1.923.909 2.833c.242.557.886 1.59.886 1.59s.126-1.277.119-1.957c-.016-1.338.079-2.126.079-2.126s3.592-1.688 5.529-1.933c1.951-.246 5.877.503 5.877.503s-.334.895-.368 1.365c-.023.315-.304 1.22-.304 1.22s.819-.621 1.06-.72c.682-.28 2.177-.391 2.177-.391s2.068 2.374 2.436 3.846c.422 1.684-.385 5.193-.385 5.193s-1.55-.678-2.348-.957c-.576-.202-1.755-.517-1.755-.517s1.138.774 1.603 1.273c.567.609 1.41 2.06 1.41 2.06s-.725.964-1.124 1.417c-.353.401-1.12 1.147-1.12 1.147s-.982-.135-1.47-.088c-.287.028-.838.216-.838.216s.467.235.647.417c.223.224.507.801.507.801s-1.834 2.022-2.788 2.998c-3.283 3.358-10.098 9.823-10.098 9.823s-2.088-1.47-3.203-2.088c-.949-.527-2.952-1.374-2.952-1.374s1.759 1.24 2.561 1.953c1.057.939 2.952 3.047 2.952 3.047s-3.045 2.194-4.518 3.354c-.646.509-1.893 1.582-1.893 1.582s-.948-.01-1.409.083c-.422.085-1.219.43-1.219.43s1.056.236 1.553.442c.492.204 1.396.776 1.396.776s-8.141-.255-12.202-.022c-1.346.077-4.017.471-4.017.471s2.594.218 3.874.441c2.478.433 7.344 1.739 7.344 1.739s-4.456 3.836-6.911 5.439c-.761.497-2.405 1.282-2.405 1.282s-3.883-.81-5.995-1.09c-1.469-.194-4.433-.31-4.433-.31s2.984.582 4.405 1.104c1.304.479 3.737 2.331 3.737 2.331s-7.816.883-11.74.377c-1.81-.231-3.082-.329-3.082-.329s1.202.597 2.972 1.075c3.366.909 8.39 1.491 8.39 1.491s-7.244 3.444-12.493 3.911c-1.739.098-5.203.49-5.203.49s3.688.816 5.565.9c1.755.078 5.258-.375 5.258-.375s-3.091 2.696-6.054 3.228c-1.05.196-3.483-.034-3.483-.034s2.043 1.18 2.821 1.506c.568.239 1.599.929 1.599.929l.045.28c.002.121-.045.361-.045.361s-4.605-.386-7.682-.845c-1.142-.17-3.446-.343-3.446-.343s2.231.802 3.309 1.292c2.393 1.089 5.519 2.673 5.519 2.673s-2.164.584-3.275.661c-.881.061-2.646-.161-2.646-.161s1.4.75 1.669.961c.512.403 1.36 1.403 1.36 1.403s-3.784.796-5.691.677c-1.466-.092-3.851-.815-4.278-1.062 1.24.716 2.083 3.814 2.083 3.814s-4.133-2.872-6.392-3.956c-1.6-.768-3.17-.963-5.019-1.781zm108.727 8.289s15.634-17.201 23.36-25.883c6.278-7.055 18.253-20.439 18.685-21.296-3.078-2.293-3.406-17.705 2.408-21.432 14.417-9.139 21.737 1.728 21.737 1.728l-12.905 6.244 7.354 16.651s-4.7 2.577-7.216 3.469c-1.882.668-3.673 1.42-5.828 1.388l-35.384 48.289c-5.028-.025-9.382-1.439-12.211-9.158zm30.575-15.771l16.605 23.403c4.775-1.361 9.724-2.287 12.35-9.019l-22.241-23.778m-7.35-7.858l-12.592-13.462c-.744-.618-.964-2.023-.971-3.747l-6.799-7.771c2.455-12.251 9.842-14.965 17.761-16.651-7.605-4.2-17.928-.425-31.083 11.656-1.291 5.998-4.781 9.668-12.35 9.019l-4.44 3.885c1.376 3.672 2.096 7.522 7.909 9.991l5.689-4.163c.384-5.297 3.754-6.794 8.187-6.938l6.522 7.909c1.388.093 2.775-.237 4.163 1.249l11.42 16.096m26.738-19.217l4.302-2.012-4.093-9.575-4.44 2.22zm6.036-9.158l12.905-5.759s.633 4.951-.486 7.007c-1.768 3.25-8.881 6.661-8.881 6.661" stroke-width="1.111" stroke="#908f8f" fill="none"/><path d="M560.346 22.489c-11.776 0-21.326 9.548-21.326 21.326 0 9.422 6.11 17.416 14.584 20.236 1.066.197 1.457-.463 1.457-1.026 0-.509-.02-2.188-.029-3.97-5.933 1.29-7.185-2.516-7.185-2.516-.97-2.465-2.368-3.12-2.368-3.12-1.935-1.324.146-1.296.146-1.296 2.141.15 3.269 2.198 3.269 2.198 1.902 3.26 4.989 2.317 6.206 1.772.191-1.378.744-2.319 1.354-2.852-4.737-.539-9.716-2.368-9.716-10.539 0-2.328.833-4.231 2.197-5.724-.221-.537-.951-2.706.207-5.644 0 0 1.791-.573 5.866 2.186 1.701-.473 3.525-.709 5.338-.718 1.812.008 3.638.245 5.342.718 4.07-2.759 5.859-2.186 5.859-2.186 1.161 2.937.43 5.106.209 5.644 1.367 1.493 2.195 3.396 2.195 5.724 0 8.191-4.989 9.994-9.738 10.522.765.662 1.446 1.96 1.446 3.949 0 2.853-.025 5.15-.025 5.852 0 .568.384 1.232 1.465 1.023 8.469-2.823 14.572-10.814 14.572-20.233 0-11.778-9.548-21.326-21.325-21.326" fill-rule="evenodd" fill="#1b1817"/><path d="M523.655 35.099v-15.559h-74.559v15.559h-5.834v31.881h86.113v-31.881z" fill="#f00"/><path d="M441.707 67.709v-34.148h5.84v-15.574h77.747v15.574h5.726v34.148h-89.313zm2.435-1.226l84.128.074-.365-29.88h-5.728v-15.575h-71.516v15.575h-5.84l-.57 28.818-.11.989z" fill="#eb1019"/><path d="M455.639 28.461l7.812-2.652-.032-10.588-10.437 2.633v7.012z" fill="#fff"/><path d="M518.08 53.332l.011 13.905h-63.526l.035-13.616 17.628 3.983zm-11.017-9.58l-4.792-1.988-9.964-6.803-11.905 3.623-25.815-1.955v9.158l16.369 4.696 46.774-4.155v-9.553z" stroke-width=".412" stroke="#bd101d" fill="#bd101d"/><path d="M450.522 37.07l4.066-.001 7.526 11.332 2.775.757 3.769 15.617 1.955.811 1.383 5.714h10.905l-5.244-21.674 14.815-9.619 8.057 6.808 1.957-.767.743 2.024 14.502-1.302-1.259-3.213-8.159-1.995-14.774-12.037-16.098 6.106-4.946-6.51 7.452-7.576h7.102l2.802 2.361v-2.361h5.582l-1.348-3.133-16.351-2.589-15.094 9.667-15.106 5.064-2.951 3.121v8.369l4.166 1.773v-4.834l1.773 1.389z" fill="#fff"/><path d="M402.179 61.976c-5.329 0-10.289-1.562-14.464-4.239.738.087 1.489.132 2.251.132 4.421 0 8.489-1.509 11.719-4.039-4.129-.076-7.614-2.804-8.814-6.553.576.11 1.167.169 1.775.169.86 0 1.694-.115 2.486-.331-4.317-.867-7.569-4.681-7.569-9.252l.001-.119c1.272.707 2.727 1.131 4.274 1.18-2.532-1.692-4.198-4.58-4.198-7.854 0-1.729.465-3.35 1.277-4.744 4.654 5.709 11.607 9.465 19.449 9.859-.161-.691-.244-1.411-.244-2.15 0-5.211 4.225-9.436 9.436-9.436 2.714 0 5.166 1.146 6.888 2.98 2.149-.423 4.169-1.209 5.992-2.29-.705 2.203-2.201 4.053-4.149 5.221 1.909-.228 3.727-.735 5.42-1.486-1.265 1.892-2.865 3.554-4.708 4.885.018.405.027.812.027 1.221 0 12.469-9.491 26.847-26.847 26.847" fill="#6babe1"/><path d="M594.842 21.81h35.407c1.757 0 3.171 1.304 3.171 2.923v35.752c0 1.619-1.414 2.923-3.171 2.923h-35.407c-1.757 0-3.171-1.304-3.171-2.923v-35.752c0-1.619 1.414-2.923 3.171-2.923z" fill="#cc2b29"/><path d="M597.945 26.3v11.449h8.245v-3.365h1.899v15.771h-2.779v8.761h14.409v-8.761h-2.765v-15.771h1.913v3.365h8.28v-11.449h-29.203zm2.52 2.374h24.162v6.723h-3.4v-3.33h-6.793v20.678h2.981v3.798h-9.739v-3.798h2.904v-20.678h-6.716v3.33h-3.4v-6.723z" fill="#fff"/><path d="M729.162 63.407v-41.598h-38.34v41.598z"/><path d="M725.63 39.839v20.2h-31.277v-11.729h6.108c.046.002.084.02.092.074.189 6.409 4.095 9.791 8.462 10.026 6.323.341 8.925-4.334 9.123-8.709 0-4.381-3.407-6.687-7.494-8.579-2.451-1.299-4.91-3.152-4.848-5.627.063-2.499 1.89-5.43 5.174-5.43 3.284 0 5.097 2.999 5.151 7.101-.019 1.551 1.138 2.639 3.234 2.645 2.103 0 4.556.029 6.276.029z" fill="#f00"/><path d="M694.353 44.726v-19.548h31.277v11.077h-5.998c-.175-.036-.175-.086-.206-.222-.232-6.3-4.285-9.227-8.457-9.227-4.65 0-8.365 2.648-8.773 8.269-.278 3.825 3.057 7.127 7.144 9.019 2.451 1.299 5.274 3.11 5.218 5.606-.062 2.784-1.396 5.125-5.218 5.125-2.798 0-5.293-2.184-5.293-6.516 0-1.518-.958-3.584-3.209-3.584z" fill="#ff0"/><path d="M663.261 21.708c-10.235 0-15.413 2.91-16.027 5.242v29.975c.422 2.98 7.067 6.056 15.091 6.291 10.671.311 16.118-3.974 16.534-6.084v-30.181c-1.331-2.877-6.249-5.242-15.598-5.242zm-.009.799c8.988 0 13.717 2.27 14.996 5.036v29.021c-.401 2.029-5.631 6.152-15.89 5.852-7.714-.225-14.109-3.177-14.515-6.041v-28.832c.591-2.242 5.568-5.036 15.409-5.036zm-14.354 28.161l.028 5.723c.01 1.927 6.337 4.861 13.535 5.071 9.573.279 14.459-3.281 14.833-5.174v-5.792c-1.053.608-4.92 3.378-14.493 3.202-7.198-.132-12.58-1.708-13.903-3.031zm-.054-11.096v6.346c.379 2.673 6.337 4.323 13.535 4.533 9.573.279 14.459-2.516 14.833-4.409v-6.358c-.981.566-5.26 3.208-14.833 3.033-7.198-.132-12.534-2.143-13.535-3.144zm-.08-11.633v7.195c.379 2.673 8.835 3.855 13.535 3.967 3.219.077 6.379-.22 8.909-.733l.004-2.348s4.417.574 4.961.574c.65-.392.877-.665.959-1.081v-7.264c-.163.094-.502.312-.857.514-.305.174-6.935-1.02-10.542-1.568-1.195-.182-2.582-.305-2.582-.305s.405.355.709.48c1.582.647 6.376 2.479 7.514 3.154-.964.55-5.23 1.168-9.076 1.098-7.198-.132-12.421-2.228-13.535-3.682z" fill="#639a00"/></svg>
diff --git a/docs/static/img/kittens.jpg b/docs/static/img/kittens.jpg deleted file mode 100644 index be6e082..0000000 --- a/docs/static/img/kittens.jpg +++ /dev/null Binary files differ
diff --git a/docs/static/img/kittens_small.jpg b/docs/static/img/kittens_small.jpg deleted file mode 100644 index ddcf454..0000000 --- a/docs/static/img/kittens_small.jpg +++ /dev/null Binary files differ
diff --git a/docs/static/img/logo.svg b/docs/static/img/logo.svg deleted file mode 100644 index ab4cc3e..0000000 --- a/docs/static/img/logo.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="1124.731" height="351.571"><path d="M19.997 0l-19.997 97.532 57.353 54.113-37.263 66.426 75.823 133.5h82.951l76.147-133.5-37.587-66.426 55.409-54.113-18.238-97.532-77.998 103.878h-78.091z" fill="#6ccb94" fill-opacity=".996"/><path d="M57.353 151.645l80.028 66.426-38.877-114.192z" fill="#64c48c" fill-opacity=".996"/><path d="M255.01 218.07l-37.587-66.426-80.041 66.426z" fill="#6ecc95" fill-opacity=".996"/><path d="M95.912 351.57h82.951l-41.482-133.5z" fill="#5ebe86" fill-opacity=".996"/><path d="M217.423 151.645l-80.041 66.426 39.214-114.192z" fill="#76d29c" fill-opacity=".996"/><path d="M20.09 218.071l37.262-66.427 80.028 66.426z" fill="#5dbd85" fill-opacity=".996"/><path d="M254.593 0l18.238 97.532-55.409 54.113-40.828-47.767z" fill="#74d09b" fill-opacity=".996"/><path d="M137.381 218.07l41.482 133.5 76.147-133.5z" fill="#64c48c" fill-opacity=".996"/><path d="M137.381 218.07l-41.482 133.5-75.809-133.499z" fill="#58b880" fill-opacity=".996"/><path d="M19.997 0l-19.997 97.532 57.353 54.113 41.152-47.767z" fill="#5fbf87" fill-opacity=".996"/><path d="M137.381 218.07l39.214-114.192h-78.091z" fill="#6ecc95" fill-opacity=".996"/><path d="M331.274 300.22v-151.501h12.737c2.979 0 4.841 1.415 5.586 4.246l1.788 12.96c4.767-5.735 10.242-10.353 16.424-13.854 6.257-3.575 13.407-5.363 21.452-5.363 6.48 0 12.327 1.266 17.541 3.799 5.288 2.458 9.795 6.145 13.519 11.061 3.799 4.916 6.703 10.986 8.715 18.211 2.011 7.151 3.016 15.418 3.017 24.804 0 8.417-1.117 16.238-3.352 23.463-2.235 7.151-5.475 13.37-9.72 18.658-4.246 5.288-9.385 9.46-15.418 12.513-6.033 2.979-12.849 4.469-20.446 4.469-6.927 0-12.811-1.117-17.653-3.352-4.841-2.235-9.162-5.437-12.96-9.609v49.495h-21.228m51.059-136.418c-6.406 0-11.992 1.452-16.759 4.357-4.693 2.83-9.05 6.89-13.072 12.178v54.187c3.575 4.693 7.448 8.007 11.62 9.944 4.246 1.862 8.975 2.793 14.189 2.793 10.204 0 18.062-3.65 23.574-10.949 5.512-7.299 8.268-17.876 8.268-31.73 0-7.225-.633-13.407-1.899-18.547-1.266-5.139-3.091-9.348-5.475-12.625-2.384-3.352-5.289-5.773-8.715-7.262-3.426-1.564-7.337-2.346-11.731-2.346m115.224-16.871c8.342 0 15.865 1.378 22.569 4.134 6.704 2.681 12.402 6.555 17.094 11.62 4.693 5.065 8.305 11.21 10.838 18.435 2.532 7.151 3.799 15.195 3.799 24.133 0 8.938-1.266 17.02-3.799 24.245-2.533 7.225-6.145 13.37-10.838 18.435-4.692 5.065-10.391 8.975-17.094 11.731-6.704 2.681-14.227 4.022-22.569 4.022-8.342 0-15.903-1.341-22.681-4.022-6.704-2.756-12.439-6.666-17.206-11.731-4.692-5.065-8.305-11.21-10.837-18.435-2.533-7.225-3.799-15.307-3.799-24.245s1.266-16.982 3.799-24.133c2.532-7.225 6.145-13.37 10.837-18.435 4.767-5.065 10.502-8.938 17.206-11.62 6.778-2.756 14.338-4.134 22.681-4.134m0 100.219c10.875 0 18.993-3.65 24.356-10.949 5.363-7.299 8.044-17.578 8.044-30.837 0-13.184-2.681-23.463-8.044-30.837-5.363-7.374-13.482-11.061-24.356-11.061-11.024 0-19.254 3.687-24.692 11.061-5.363 7.374-8.044 17.653-8.044 30.837 0 13.258 2.681 23.537 8.044 30.837 5.437 7.299 13.668 10.949 24.692 10.949m89.306-98.431v72.287c0 8.193 1.899 14.599 5.698 19.217 3.799 4.544 9.571 6.815 17.318 6.815 5.661 0 10.949-1.303 15.865-3.91 4.99-2.681 9.608-6.368 13.854-11.061v-83.348h21.228v113.403h-12.737c-2.979 0-4.842-1.415-5.586-4.246l-1.676-11.731c-4.916 5.288-10.391 9.571-16.424 12.848-5.959 3.277-12.886 4.916-20.781 4.916-6.257 0-11.769-1.043-16.536-3.128-4.693-2.086-8.64-4.99-11.843-8.715-3.128-3.799-5.512-8.305-7.15-13.519-1.639-5.288-2.458-11.135-2.458-17.541v-72.287h21.228m179.506 20.892c-.596.819-1.229 1.452-1.899 1.899-.596.447-1.453.67-2.57.67-1.192 0-2.458-.447-3.799-1.341-1.341-.968-2.98-1.974-4.916-3.016-1.937-1.117-4.32-2.123-7.15-3.017-2.831-.968-6.294-1.452-10.391-1.452-5.437 0-10.242.968-14.413 2.905-4.171 1.937-7.672 4.73-10.502 8.38-2.756 3.65-4.841 8.044-6.257 13.184-1.415 5.14-2.123 10.949-2.123 17.43 0 6.704.745 12.662 2.235 17.876 1.564 5.214 3.724 9.609 6.48 13.184 2.83 3.575 6.219 6.294 10.167 8.156 4.022 1.862 8.491 2.793 13.407 2.793 4.767 0 8.677-.559 11.731-1.676 3.054-1.192 5.586-2.458 7.597-3.799 2.011-1.341 3.687-2.57 5.028-3.687 1.415-1.192 2.83-1.788 4.246-1.788 1.788 0 3.128.671 4.022 2.011l6.033 7.709c-2.607 3.128-5.512 5.81-8.715 8.044-3.203 2.235-6.629 4.059-10.279 5.475-3.65 1.415-7.449 2.458-11.396 3.128-3.948.67-7.97 1.006-12.066 1.006-7.076 0-13.668-1.304-19.776-3.91-6.108-2.607-11.433-6.406-15.977-11.396-4.469-4.99-8.007-11.098-10.614-18.323-2.533-7.299-3.799-15.567-3.799-24.803 0-8.417 1.154-16.163 3.463-23.239 2.384-7.151 5.847-13.333 10.391-18.547s10.13-9.273 16.759-12.178c6.704-2.905 14.375-4.357 23.016-4.357 8.119 0 15.232 1.303 21.34 3.91 6.182 2.607 11.619 6.257 16.312 10.949l-5.586 7.821m26.777 92.509v-164.797h21.228v65.919c4.767-4.916 10.055-8.864 15.865-11.843 5.81-2.979 12.513-4.469 20.111-4.469 6.182 0 11.619 1.043 16.312 3.128 4.767 2.086 8.752 5.028 11.955 8.827 3.203 3.724 5.623 8.231 7.262 13.519 1.639 5.214 2.455 11.024 2.458 17.429v72.287h-21.228v-72.287c0-8.193-1.899-14.562-5.698-19.105-3.799-4.618-9.571-6.927-17.318-6.927-5.735 0-11.061 1.341-15.977 4.022s-9.497 6.368-13.742 11.061v83.237h-21.228m201.032-.001c-2.98 0-4.841-1.415-5.586-4.246l-1.899-13.295c-2.384 2.905-4.953 5.549-7.709 7.933-2.756 2.309-5.698 4.32-8.826 6.033-3.128 1.639-6.443 2.905-9.944 3.799-3.501.894-7.262 1.341-11.284 1.341-6.48 0-12.364-1.229-17.653-3.687-5.214-2.532-9.72-6.257-13.519-11.173-3.724-4.916-6.592-10.949-8.603-18.1-2.011-7.225-3.017-15.53-3.017-24.915 0-8.417 1.117-16.2 3.352-23.351 2.235-7.225 5.475-13.482 9.72-18.77 4.246-5.288 9.385-9.422 15.418-12.402 6.033-3.054 12.849-4.581 20.446-4.581 6.853 0 12.7 1.155 17.541 3.464 4.916 2.235 9.273 5.4 13.072 9.497v-62.343h21.228v164.797h-12.737m-38.322-15.53c6.331 0 11.88-1.415 16.647-4.246 4.767-2.905 9.162-7.002 13.184-12.29v-54.076c-3.575-4.767-7.486-8.082-11.731-9.944-4.246-1.936-8.938-2.905-14.078-2.905-10.204 0-18.063 3.65-23.574 10.949-5.512 7.3-8.268 17.876-8.268 31.731 0 7.225.633 13.407 1.899 18.547 1.266 5.139 3.091 9.385 5.475 12.737 2.384 3.277 5.288 5.698 8.715 7.262 3.426 1.49 7.337 2.235 11.731 2.235m68.096 15.529v-164.797h21.228v67.371c4.693-5.437 10.018-9.757 15.977-12.96 6.033-3.203 12.886-4.804 20.558-4.804 6.629 0 12.588 1.303 17.876 3.91 5.363 2.532 9.906 6.182 13.631 10.949 3.724 4.767 6.554 10.614 8.491 17.541 2.011 6.853 3.016 14.562 3.017 23.127 0 9.162-1.155 17.504-3.464 25.027-2.235 7.523-5.475 13.966-9.72 19.329-4.171 5.363-9.273 9.534-15.307 12.513-5.959 2.905-12.7 4.357-20.223 4.357-7.448 0-13.705-1.378-18.77-4.134-4.991-2.83-9.385-6.704-13.184-11.62l-1.006 9.72c-.67 2.98-2.458 4.469-5.363 4.469h-13.742m50.724-98.32c-6.331 0-11.843 1.452-16.536 4.357-4.618 2.83-8.938 6.89-12.96 12.178v54.187c3.575 4.693 7.486 8.007 11.731 9.944 4.246 1.862 8.864 2.793 13.854 2.793 10.353 0 18.286-3.65 23.798-10.949 5.512-7.299 8.268-18.323 8.268-33.071 0-13.556-2.458-23.5-7.374-29.831-4.842-6.406-11.769-9.609-20.781-9.609" style="text-align:start;line-height:125%;-inkscape-font-specification:Lato Medium" font-size="144" font-weight="500" letter-spacing="-.153" word-spacing="0" fill="#3e3e3e" font-family="Lato"/></svg>
diff --git a/docs/static/img/mark.svg b/docs/static/img/mark.svg deleted file mode 100644 index a80f2be..0000000 --- a/docs/static/img/mark.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="272.833" height="351.571"><path d="M19.997 0l-19.997 97.532 57.353 54.113-37.263 66.426 75.823 133.5h82.951l76.147-133.5-37.587-66.426 55.409-54.113-18.238-97.532-77.998 103.878h-78.091z" fill="#6ccb94" fill-opacity=".996"/><path d="M20.09 218.071l37.262-66.426 80.028 66.426z" fill="#5dbd85" fill-opacity=".996"/><path d="M57.353 151.646l80.028 66.426-38.877-114.192z" fill="#64c48c" fill-opacity=".996"/><path d="M255.01 218.071l-37.587-66.426-80.041 66.426z" fill="#6ecc95" fill-opacity=".996"/><path d="M95.912 351.571h82.951l-41.482-133.5z" fill="#5ebe86" fill-opacity=".996"/><path d="M217.423 151.646l-80.041 66.426 39.214-114.192z" fill="#76d29c" fill-opacity=".996"/><path d="M254.593.001l18.238 97.532-55.409 54.113-40.828-47.767z" fill="#74d09b" fill-opacity=".996"/><path d="M137.381 218.071l41.482 133.5 76.147-133.5z" fill="#64c48c" fill-opacity=".996"/><path d="M137.381 218.071l-41.482 133.5-75.809-133.5z" fill="#58b880" fill-opacity=".996"/><path d="M19.997.001l-19.997 97.532 57.353 54.113 41.152-47.767z" fill="#5fbf87" fill-opacity=".996"/><path d="M137.381 218.071l39.214-114.192h-78.091z" fill="#6ecc95" fill-opacity=".996"/></svg> \ No newline at end of file
diff --git a/docs/static/img/safari_popup.png b/docs/static/img/safari_popup.png deleted file mode 100644 index e1d889e..0000000 --- a/docs/static/img/safari_popup.png +++ /dev/null Binary files differ
diff --git a/docs/static/img/screenshots/todo-1.png b/docs/static/img/screenshots/todo-1.png deleted file mode 100644 index c6b292f..0000000 --- a/docs/static/img/screenshots/todo-1.png +++ /dev/null Binary files differ
diff --git a/docs/static/img/travis-screenshot.png b/docs/static/img/travis-screenshot.png deleted file mode 100644 index 2433a10..0000000 --- a/docs/static/img/travis-screenshot.png +++ /dev/null Binary files differ
diff --git a/docs/static/less/bootstrap/alerts.less b/docs/static/less/bootstrap/alerts.less deleted file mode 100644 index 3eab066..0000000 --- a/docs/static/less/bootstrap/alerts.less +++ /dev/null
@@ -1,67 +0,0 @@ -// -// Alerts -// -------------------------------------------------- - - -// Base styles -// ------------------------- - -.alert { - padding: @alert-padding; - margin-bottom: @line-height-computed; - border: 1px solid transparent; - border-radius: @alert-border-radius; - - // Headings for larger alerts - h4 { - margin-top: 0; - // Specified for the h4 to prevent conflicts of changing @headings-color - color: inherit; - } - // Provide class for links that match alerts - .alert-link { - font-weight: @alert-link-font-weight; - } - - // Improve alignment and spacing of inner content - > p, - > ul { - margin-bottom: 0; - } - > p + p { - margin-top: 5px; - } -} - -// Dismissable alerts -// -// Expand the right padding and account for the close button's positioning. - -.alert-dismissable { - padding-right: (@alert-padding + 20); - - // Adjust close link position - .close { - position: relative; - top: -2px; - right: -21px; - color: inherit; - } -} - -// Alternate styles -// -// Generate contextual modifier classes for colorizing the alert. - -.alert-success { - .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text); -} -.alert-info { - .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text); -} -.alert-warning { - .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text); -} -.alert-danger { - .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text); -}
diff --git a/docs/static/less/bootstrap/badges.less b/docs/static/less/bootstrap/badges.less deleted file mode 100644 index 56828ca..0000000 --- a/docs/static/less/bootstrap/badges.less +++ /dev/null
@@ -1,55 +0,0 @@ -// -// Badges -// -------------------------------------------------- - - -// Base classes -.badge { - display: inline-block; - min-width: 10px; - padding: 3px 7px; - font-size: @font-size-small; - font-weight: @badge-font-weight; - color: @badge-color; - line-height: @badge-line-height; - vertical-align: baseline; - white-space: nowrap; - text-align: center; - background-color: @badge-bg; - border-radius: @badge-border-radius; - - // Empty badges collapse automatically (not available in IE8) - &:empty { - display: none; - } - - // Quick fix for badges in buttons - .btn & { - position: relative; - top: -1px; - } - .btn-xs & { - top: 0; - padding: 1px 5px; - } -} - -// Hover state, but only for links -a.badge { - &:hover, - &:focus { - color: @badge-link-hover-color; - text-decoration: none; - cursor: pointer; - } -} - -// Account for counters in navs -a.list-group-item.active > .badge, -.nav-pills > .active > a > .badge { - color: @badge-active-color; - background-color: @badge-active-bg; -} -.nav-pills > li > a > .badge { - margin-left: 3px; -}
diff --git a/docs/static/less/bootstrap/bootstrap.less b/docs/static/less/bootstrap/bootstrap.less deleted file mode 100644 index b368b87..0000000 --- a/docs/static/less/bootstrap/bootstrap.less +++ /dev/null
@@ -1,49 +0,0 @@ -// Core variables and mixins -@import "variables.less"; -@import "mixins.less"; - -// Reset -@import "normalize.less"; -@import "print.less"; - -// Core CSS -@import "scaffolding.less"; -@import "type.less"; -@import "code.less"; -@import "grid.less"; -@import "tables.less"; -@import "forms.less"; -@import "buttons.less"; - -// Components -@import "component-animations.less"; -@import "glyphicons.less"; -@import "dropdowns.less"; -@import "button-groups.less"; -@import "input-groups.less"; -@import "navs.less"; -@import "navbar.less"; -@import "breadcrumbs.less"; -@import "pagination.less"; -@import "pager.less"; -@import "labels.less"; -@import "badges.less"; -@import "jumbotron.less"; -@import "thumbnails.less"; -@import "alerts.less"; -@import "progress-bars.less"; -@import "media.less"; -@import "list-group.less"; -@import "panels.less"; -@import "wells.less"; -@import "close.less"; - -// Components w/ JavaScript -@import "modals.less"; -@import "tooltip.less"; -@import "popovers.less"; -@import "carousel.less"; - -// Utility classes -@import "utilities.less"; -@import "responsive-utilities.less";
diff --git a/docs/static/less/bootstrap/breadcrumbs.less b/docs/static/less/bootstrap/breadcrumbs.less deleted file mode 100644 index cb01d50..0000000 --- a/docs/static/less/bootstrap/breadcrumbs.less +++ /dev/null
@@ -1,26 +0,0 @@ -// -// Breadcrumbs -// -------------------------------------------------- - - -.breadcrumb { - padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal; - margin-bottom: @line-height-computed; - list-style: none; - background-color: @breadcrumb-bg; - border-radius: @border-radius-base; - - > li { - display: inline-block; - - + li:before { - content: "@{breadcrumb-separator}\00a0"; // Unicode space added since inline-block means non-collapsing white-space - padding: 0 5px; - color: @breadcrumb-color; - } - } - - > .active { - color: @breadcrumb-active-color; - } -}
diff --git a/docs/static/less/bootstrap/button-groups.less b/docs/static/less/bootstrap/button-groups.less deleted file mode 100644 index 27eb796..0000000 --- a/docs/static/less/bootstrap/button-groups.less +++ /dev/null
@@ -1,226 +0,0 @@ -// -// Button groups -// -------------------------------------------------- - -// Make the div behave like a button -.btn-group, -.btn-group-vertical { - position: relative; - display: inline-block; - vertical-align: middle; // match .btn alignment given font-size hack above - > .btn { - position: relative; - float: left; - // Bring the "active" button to the front - &:hover, - &:focus, - &:active, - &.active { - z-index: 2; - } - &:focus { - // Remove focus outline when dropdown JS adds it after closing the menu - outline: none; - } - } -} - -// Prevent double borders when buttons are next to each other -.btn-group { - .btn + .btn, - .btn + .btn-group, - .btn-group + .btn, - .btn-group + .btn-group { - margin-left: -1px; - } -} - -// Optional: Group multiple button groups together for a toolbar -.btn-toolbar { - margin-left: -5px; // Offset the first child's margin - &:extend(.clearfix all); - - .btn-group, - .input-group { - float: left; - } - > .btn, - > .btn-group, - > .input-group { - margin-left: 5px; - } -} - -.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { - border-radius: 0; -} - -// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match -.btn-group > .btn:first-child { - margin-left: 0; - &:not(:last-child):not(.dropdown-toggle) { - .border-right-radius(0); - } -} -// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it -.btn-group > .btn:last-child:not(:first-child), -.btn-group > .dropdown-toggle:not(:first-child) { - .border-left-radius(0); -} - -// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group) -.btn-group > .btn-group { - float: left; -} -.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { - border-radius: 0; -} -.btn-group > .btn-group:first-child { - > .btn:last-child, - > .dropdown-toggle { - .border-right-radius(0); - } -} -.btn-group > .btn-group:last-child > .btn:first-child { - .border-left-radius(0); -} - -// On active and open, don't show outline -.btn-group .dropdown-toggle:active, -.btn-group.open .dropdown-toggle { - outline: 0; -} - - -// Sizing -// -// Remix the default button sizing classes into new ones for easier manipulation. - -.btn-group-xs > .btn { &:extend(.btn-xs); } -.btn-group-sm > .btn { &:extend(.btn-sm); } -.btn-group-lg > .btn { &:extend(.btn-lg); } - - -// Split button dropdowns -// ---------------------- - -// Give the line between buttons some depth -.btn-group > .btn + .dropdown-toggle { - padding-left: 8px; - padding-right: 8px; -} -.btn-group > .btn-lg + .dropdown-toggle { - padding-left: 12px; - padding-right: 12px; -} - -// The clickable button for toggling the menu -// Remove the gradient and set the same inset shadow as the :active state -.btn-group.open .dropdown-toggle { - .box-shadow(inset 0 3px 5px rgba(0,0,0,.125)); - - // Show no shadow for `.btn-link` since it has no other button styles. - &.btn-link { - .box-shadow(none); - } -} - - -// Reposition the caret -.btn .caret { - margin-left: 0; -} -// Carets in other button sizes -.btn-lg .caret { - border-width: @caret-width-large @caret-width-large 0; - border-bottom-width: 0; -} -// Upside down carets for .dropup -.dropup .btn-lg .caret { - border-width: 0 @caret-width-large @caret-width-large; -} - - -// Vertical button groups -// ---------------------- - -.btn-group-vertical { - > .btn, - > .btn-group, - > .btn-group > .btn { - display: block; - float: none; - width: 100%; - max-width: 100%; - } - - // Clear floats so dropdown menus can be properly placed - > .btn-group { - &:extend(.clearfix all); - > .btn { - float: none; - } - } - - > .btn + .btn, - > .btn + .btn-group, - > .btn-group + .btn, - > .btn-group + .btn-group { - margin-top: -1px; - margin-left: 0; - } -} - -.btn-group-vertical > .btn { - &:not(:first-child):not(:last-child) { - border-radius: 0; - } - &:first-child:not(:last-child) { - border-top-right-radius: @border-radius-base; - .border-bottom-radius(0); - } - &:last-child:not(:first-child) { - border-bottom-left-radius: @border-radius-base; - .border-top-radius(0); - } -} -.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { - border-radius: 0; -} -.btn-group-vertical > .btn-group:first-child:not(:last-child) { - > .btn:last-child, - > .dropdown-toggle { - .border-bottom-radius(0); - } -} -.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { - .border-top-radius(0); -} - - - -// Justified button groups -// ---------------------- - -.btn-group-justified { - display: table; - width: 100%; - table-layout: fixed; - border-collapse: separate; - > .btn, - > .btn-group { - float: none; - display: table-cell; - width: 1%; - } - > .btn-group .btn { - width: 100%; - } -} - - -// Checkbox and radio options -[data-toggle="buttons"] > .btn > input[type="radio"], -[data-toggle="buttons"] > .btn > input[type="checkbox"] { - display: none; -}
diff --git a/docs/static/less/bootstrap/buttons.less b/docs/static/less/bootstrap/buttons.less deleted file mode 100644 index d4fc156..0000000 --- a/docs/static/less/bootstrap/buttons.less +++ /dev/null
@@ -1,159 +0,0 @@ -// -// Buttons -// -------------------------------------------------- - - -// Base styles -// -------------------------------------------------- - -.btn { - display: inline-block; - margin-bottom: 0; // For input.btn - font-weight: @btn-font-weight; - text-align: center; - vertical-align: middle; - cursor: pointer; - background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 - border: 1px solid transparent; - white-space: nowrap; - .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @border-radius-base); - .user-select(none); - - &, - &:active, - &.active { - &:focus { - .tab-focus(); - } - } - - &:hover, - &:focus { - color: @btn-default-color; - text-decoration: none; - } - - &:active, - &.active { - outline: 0; - background-image: none; - .box-shadow(inset 0 3px 5px rgba(0,0,0,.125)); - } - - &.disabled, - &[disabled], - fieldset[disabled] & { - cursor: not-allowed; - pointer-events: none; // Future-proof disabling of clicks - .opacity(.65); - .box-shadow(none); - } -} - - -// Alternate buttons -// -------------------------------------------------- - -.btn-default { - .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border); -} -.btn-primary { - .button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border); -} -// Success appears as green -.btn-success { - .button-variant(@btn-success-color; @btn-success-bg; @btn-success-border); -} -// Info appears as blue-green -.btn-info { - .button-variant(@btn-info-color; @btn-info-bg; @btn-info-border); -} -// Warning appears as orange -.btn-warning { - .button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border); -} -// Danger and error appear as red -.btn-danger { - .button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border); -} - - -// Link buttons -// ------------------------- - -// Make a button look and behave like a link -.btn-link { - color: @link-color; - font-weight: normal; - cursor: pointer; - border-radius: 0; - - &, - &:active, - &[disabled], - fieldset[disabled] & { - background-color: transparent; - .box-shadow(none); - } - &, - &:hover, - &:focus, - &:active { - border-color: transparent; - } - &:hover, - &:focus { - color: @link-hover-color; - text-decoration: underline; - background-color: transparent; - } - &[disabled], - fieldset[disabled] & { - &:hover, - &:focus { - color: @btn-link-disabled-color; - text-decoration: none; - } - } -} - - -// Button Sizes -// -------------------------------------------------- - -.btn-lg { - // line-height: ensure even-numbered height of button next to large input - .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large); -} -.btn-sm { - // line-height: ensure proper height of button next to small input - .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small); -} -.btn-xs { - .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @border-radius-small); -} - - -// Block button -// -------------------------------------------------- - -.btn-block { - display: block; - width: 100%; - padding-left: 0; - padding-right: 0; -} - -// Vertically space out multiple block buttons -.btn-block + .btn-block { - margin-top: 5px; -} - -// Specificity overrides -input[type="submit"], -input[type="reset"], -input[type="button"] { - &.btn-block { - width: 100%; - } -}
diff --git a/docs/static/less/bootstrap/carousel.less b/docs/static/less/bootstrap/carousel.less deleted file mode 100644 index e3fb8a2..0000000 --- a/docs/static/less/bootstrap/carousel.less +++ /dev/null
@@ -1,232 +0,0 @@ -// -// Carousel -// -------------------------------------------------- - - -// Wrapper for the slide container and indicators -.carousel { - position: relative; -} - -.carousel-inner { - position: relative; - overflow: hidden; - width: 100%; - - > .item { - display: none; - position: relative; - .transition(.6s ease-in-out left); - - // Account for jankitude on images - > img, - > a > img { - &:extend(.img-responsive); - line-height: 1; - } - } - - > .active, - > .next, - > .prev { display: block; } - - > .active { - left: 0; - } - - > .next, - > .prev { - position: absolute; - top: 0; - width: 100%; - } - - > .next { - left: 100%; - } - > .prev { - left: -100%; - } - > .next.left, - > .prev.right { - left: 0; - } - - > .active.left { - left: -100%; - } - > .active.right { - left: 100%; - } - -} - -// Left/right controls for nav -// --------------------------- - -.carousel-control { - position: absolute; - top: 0; - left: 0; - bottom: 0; - width: @carousel-control-width; - .opacity(@carousel-control-opacity); - font-size: @carousel-control-font-size; - color: @carousel-control-color; - text-align: center; - text-shadow: @carousel-text-shadow; - // We can't have this transition here because WebKit cancels the carousel - // animation if you trip this while in the middle of another animation. - - // Set gradients for backgrounds - &.left { - #gradient > .horizontal(@start-color: rgba(0,0,0,.5); @end-color: rgba(0,0,0,.0001)); - } - &.right { - left: auto; - right: 0; - #gradient > .horizontal(@start-color: rgba(0,0,0,.0001); @end-color: rgba(0,0,0,.5)); - } - - // Hover/focus state - &:hover, - &:focus { - outline: none; - color: @carousel-control-color; - text-decoration: none; - .opacity(.9); - } - - // Toggles - .icon-prev, - .icon-next, - .glyphicon-chevron-left, - .glyphicon-chevron-right { - position: absolute; - top: 50%; - z-index: 5; - display: inline-block; - } - .icon-prev, - .glyphicon-chevron-left { - left: 50%; - } - .icon-next, - .glyphicon-chevron-right { - right: 50%; - } - .icon-prev, - .icon-next { - width: 20px; - height: 20px; - margin-top: -10px; - margin-left: -10px; - font-family: serif; - } - - .icon-prev { - &:before { - content: '\2039';// SINGLE LEFT-POINTING ANGLE QUOTATION MARK (U+2039) - } - } - .icon-next { - &:before { - content: '\203a';// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (U+203A) - } - } -} - -// Optional indicator pips -// -// Add an unordered list with the following class and add a list item for each -// slide your carousel holds. - -.carousel-indicators { - position: absolute; - bottom: 10px; - left: 50%; - z-index: 15; - width: 60%; - margin-left: -30%; - padding-left: 0; - list-style: none; - text-align: center; - - li { - display: inline-block; - width: 10px; - height: 10px; - margin: 1px; - text-indent: -999px; - border: 1px solid @carousel-indicator-border-color; - border-radius: 10px; - cursor: pointer; - - // IE8-9 hack for event handling - // - // Internet Explorer 8-9 does not support clicks on elements without a set - // `background-color`. We cannot use `filter` since that's not viewed as a - // background color by the browser. Thus, a hack is needed. - // - // For IE8, we set solid black as it doesn't support `rgba()`. For IE9, we - // set alpha transparency for the best results possible. - background-color: #000 \9; // IE8 - background-color: rgba(0,0,0,0); // IE9 - } - .active { - margin: 0; - width: 12px; - height: 12px; - background-color: @carousel-indicator-active-bg; - } -} - -// Optional captions -// ----------------------------- -// Hidden by default for smaller viewports -.carousel-caption { - position: absolute; - left: 15%; - right: 15%; - bottom: 20px; - z-index: 10; - padding-top: 20px; - padding-bottom: 20px; - color: @carousel-caption-color; - text-align: center; - text-shadow: @carousel-text-shadow; - & .btn { - text-shadow: none; // No shadow for button elements in carousel-caption - } -} - - -// Scale up controls for tablets and up -@media screen and (min-width: @screen-sm-min) { - - // Scale up the controls a smidge - .carousel-control { - .glyphicon-chevron-left, - .glyphicon-chevron-right, - .icon-prev, - .icon-next { - width: 30px; - height: 30px; - margin-top: -15px; - margin-left: -15px; - font-size: 30px; - } - } - - // Show and left align the captions - .carousel-caption { - left: 20%; - right: 20%; - padding-bottom: 30px; - } - - // Move up the indicators - .carousel-indicators { - bottom: 20px; - } -}
diff --git a/docs/static/less/bootstrap/close.less b/docs/static/less/bootstrap/close.less deleted file mode 100644 index 9b4e74f..0000000 --- a/docs/static/less/bootstrap/close.less +++ /dev/null
@@ -1,33 +0,0 @@ -// -// Close icons -// -------------------------------------------------- - - -.close { - float: right; - font-size: (@font-size-base * 1.5); - font-weight: @close-font-weight; - line-height: 1; - color: @close-color; - text-shadow: @close-text-shadow; - .opacity(.2); - - &:hover, - &:focus { - color: @close-color; - text-decoration: none; - cursor: pointer; - .opacity(.5); - } - - // Additional properties for button version - // iOS requires the button element instead of an anchor tag. - // If you want the anchor version, it requires `href="#"`. - button& { - padding: 0; - cursor: pointer; - background: transparent; - border: 0; - -webkit-appearance: none; - } -}
diff --git a/docs/static/less/bootstrap/code.less b/docs/static/less/bootstrap/code.less deleted file mode 100644 index 3eed26c..0000000 --- a/docs/static/less/bootstrap/code.less +++ /dev/null
@@ -1,63 +0,0 @@ -// -// Code (inline and block) -// -------------------------------------------------- - - -// Inline and block code styles -code, -kbd, -pre, -samp { - font-family: @font-family-monospace; -} - -// Inline code -code { - padding: 2px 4px; - font-size: 90%; - color: @code-color; - background-color: @code-bg; - white-space: nowrap; - border-radius: @border-radius-base; -} - -// User input typically entered via keyboard -kbd { - padding: 2px 4px; - font-size: 90%; - color: @kbd-color; - background-color: @kbd-bg; - border-radius: @border-radius-small; - box-shadow: inset 0 -1px 0 rgba(0,0,0,.25); -} - -// Blocks of code -pre { - display: block; - padding: ((@line-height-computed - 1) / 2); - margin: 0 0 (@line-height-computed / 2); - font-size: (@font-size-base - 1); // 14px to 13px - line-height: @line-height-base; - word-break: break-all; - word-wrap: break-word; - color: @pre-color; - background-color: @pre-bg; - border: 1px solid @pre-border-color; - border-radius: @border-radius-base; - - // Account for some code outputs that place code tags in pre tags - code { - padding: 0; - font-size: inherit; - color: inherit; - white-space: pre-wrap; - background-color: transparent; - border-radius: 0; - } -} - -// Enable scrollable blocks of code -.pre-scrollable { - max-height: @pre-scrollable-max-height; - overflow-y: scroll; -}
diff --git a/docs/static/less/bootstrap/component-animations.less b/docs/static/less/bootstrap/component-animations.less deleted file mode 100644 index 1efe45e..0000000 --- a/docs/static/less/bootstrap/component-animations.less +++ /dev/null
@@ -1,29 +0,0 @@ -// -// Component animations -// -------------------------------------------------- - -// Heads up! -// -// We don't use the `.opacity()` mixin here since it causes a bug with text -// fields in IE7-8. Source: https://github.com/twitter/bootstrap/pull/3552. - -.fade { - opacity: 0; - .transition(opacity .15s linear); - &.in { - opacity: 1; - } -} - -.collapse { - display: none; - &.in { - display: block; - } -} -.collapsing { - position: relative; - height: 0; - overflow: hidden; - .transition(height .35s ease); -}
diff --git a/docs/static/less/bootstrap/dropdowns.less b/docs/static/less/bootstrap/dropdowns.less deleted file mode 100644 index f165165..0000000 --- a/docs/static/less/bootstrap/dropdowns.less +++ /dev/null
@@ -1,213 +0,0 @@ -// -// Dropdown menus -// -------------------------------------------------- - - -// Dropdown arrow/caret -.caret { - display: inline-block; - width: 0; - height: 0; - margin-left: 2px; - vertical-align: middle; - border-top: @caret-width-base solid; - border-right: @caret-width-base solid transparent; - border-left: @caret-width-base solid transparent; -} - -// The dropdown wrapper (div) -.dropdown { - position: relative; -} - -// Prevent the focus on the dropdown toggle when closing dropdowns -.dropdown-toggle:focus { - outline: 0; -} - -// The dropdown menu (ul) -.dropdown-menu { - position: absolute; - top: 100%; - left: 0; - z-index: @zindex-dropdown; - display: none; // none by default, but block on "open" of the menu - float: left; - min-width: 160px; - padding: 5px 0; - margin: 2px 0 0; // override default ul - list-style: none; - font-size: @font-size-base; - background-color: @dropdown-bg; - border: 1px solid @dropdown-fallback-border; // IE8 fallback - border: 1px solid @dropdown-border; - border-radius: @border-radius-base; - .box-shadow(0 6px 12px rgba(0,0,0,.175)); - background-clip: padding-box; - - // Aligns the dropdown menu to right - // - // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]` - &.pull-right { - right: 0; - left: auto; - } - - // Dividers (basically an hr) within the dropdown - .divider { - .nav-divider(@dropdown-divider-bg); - } - - // Links within the dropdown menu - > li > a { - display: block; - padding: 3px 20px; - clear: both; - font-weight: normal; - line-height: @line-height-base; - color: @dropdown-link-color; - white-space: nowrap; // prevent links from randomly breaking onto new lines - } -} - -// Hover/Focus state -.dropdown-menu > li > a { - &:hover, - &:focus { - text-decoration: none; - color: @dropdown-link-hover-color; - background-color: @dropdown-link-hover-bg; - } -} - -// Active state -.dropdown-menu > .active > a { - &, - &:hover, - &:focus { - color: @dropdown-link-active-color; - text-decoration: none; - outline: 0; - background-color: @dropdown-link-active-bg; - } -} - -// Disabled state -// -// Gray out text and ensure the hover/focus state remains gray - -.dropdown-menu > .disabled > a { - &, - &:hover, - &:focus { - color: @dropdown-link-disabled-color; - } -} -// Nuke hover/focus effects -.dropdown-menu > .disabled > a { - &:hover, - &:focus { - text-decoration: none; - background-color: transparent; - background-image: none; // Remove CSS gradient - .reset-filter(); - cursor: not-allowed; - } -} - -// Open state for the dropdown -.open { - // Show the menu - > .dropdown-menu { - display: block; - } - - // Remove the outline when :focus is triggered - > a { - outline: 0; - } -} - -// Menu positioning -// -// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown -// menu with the parent. -.dropdown-menu-right { - left: auto; // Reset the default from `.dropdown-menu` - right: 0; -} -// With v3, we enabled auto-flipping if you have a dropdown within a right -// aligned nav component. To enable the undoing of that, we provide an override -// to restore the default dropdown menu alignment. -// -// This is only for left-aligning a dropdown menu within a `.navbar-right` or -// `.pull-right` nav component. -.dropdown-menu-left { - left: 0; - right: auto; -} - -// Dropdown section headers -.dropdown-header { - display: block; - padding: 3px 20px; - font-size: @font-size-small; - line-height: @line-height-base; - color: @dropdown-header-color; -} - -// Backdrop to catch body clicks on mobile, etc. -.dropdown-backdrop { - position: fixed; - left: 0; - right: 0; - bottom: 0; - top: 0; - z-index: (@zindex-dropdown - 10); -} - -// Right aligned dropdowns -.pull-right > .dropdown-menu { - right: 0; - left: auto; -} - -// Allow for dropdowns to go bottom up (aka, dropup-menu) -// -// Just add .dropup after the standard .dropdown class and you're set, bro. -// TODO: abstract this so that the navbar fixed styles are not placed here? - -.dropup, -.navbar-fixed-bottom .dropdown { - // Reverse the caret - .caret { - border-top: 0; - border-bottom: @caret-width-base solid; - content: ""; - } - // Different positioning for bottom up menu - .dropdown-menu { - top: auto; - bottom: 100%; - margin-bottom: 1px; - } -} - - -// Component alignment -// -// Reiterate per navbar.less and the modified component alignment there. - -@media (min-width: @grid-float-breakpoint) { - .navbar-right { - .dropdown-menu { - .dropdown-menu-right(); - } - // Necessary for overrides of the default right aligned menu. - // Will remove come v4 in all likelihood. - .dropdown-menu-left { - .dropdown-menu-left(); - } - } -} -
diff --git a/docs/static/less/bootstrap/forms.less b/docs/static/less/bootstrap/forms.less deleted file mode 100644 index f607b85..0000000 --- a/docs/static/less/bootstrap/forms.less +++ /dev/null
@@ -1,438 +0,0 @@ -// -// Forms -// -------------------------------------------------- - - -// Normalize non-controls -// -// Restyle and baseline non-control form elements. - -fieldset { - padding: 0; - margin: 0; - border: 0; - // Chrome and Firefox set a `min-width: -webkit-min-content;` on fieldsets, - // so we reset that to ensure it behaves more like a standard block element. - // See https://github.com/twbs/bootstrap/issues/12359. - min-width: 0; -} - -legend { - display: block; - width: 100%; - padding: 0; - margin-bottom: @line-height-computed; - font-size: (@font-size-base * 1.5); - line-height: inherit; - color: @legend-color; - border: 0; - border-bottom: 1px solid @legend-border-color; -} - -label { - display: inline-block; - margin-bottom: 5px; - font-weight: bold; -} - - -// Normalize form controls -// -// While most of our form styles require extra classes, some basic normalization -// is required to ensure optimum display with or without those classes to better -// address browser inconsistencies. - -// Override content-box in Normalize (* isn't specific enough) -input[type="search"] { - .box-sizing(border-box); -} - -// Position radios and checkboxes better -input[type="radio"], -input[type="checkbox"] { - margin: 4px 0 0; - margin-top: 1px \9; /* IE8-9 */ - line-height: normal; -} - -// Set the height of file controls to match text inputs -input[type="file"] { - display: block; -} - -// Make range inputs behave like textual form controls -input[type="range"] { - display: block; - width: 100%; -} - -// Make multiple select elements height not fixed -select[multiple], -select[size] { - height: auto; -} - -// Focus for file, radio, and checkbox -input[type="file"]:focus, -input[type="radio"]:focus, -input[type="checkbox"]:focus { - .tab-focus(); -} - -// Adjust output element -output { - display: block; - padding-top: (@padding-base-vertical + 1); - font-size: @font-size-base; - line-height: @line-height-base; - color: @input-color; -} - - -// Common form controls -// -// Shared size and type resets for form controls. Apply `.form-control` to any -// of the following form controls: -// -// select -// textarea -// input[type="text"] -// input[type="password"] -// input[type="datetime"] -// input[type="datetime-local"] -// input[type="date"] -// input[type="month"] -// input[type="time"] -// input[type="week"] -// input[type="number"] -// input[type="email"] -// input[type="url"] -// input[type="search"] -// input[type="tel"] -// input[type="color"] - -.form-control { - display: block; - width: 100%; - height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border) - padding: @padding-base-vertical @padding-base-horizontal; - font-size: @font-size-base; - line-height: @line-height-base; - color: @input-color; - background-color: @input-bg; - background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 - border: 1px solid @input-border; - border-radius: @input-border-radius; - .box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); - .transition(~"border-color ease-in-out .15s, box-shadow ease-in-out .15s"); - - // Customize the `:focus` state to imitate native WebKit styles. - .form-control-focus(); - - // Placeholder - .placeholder(); - - // Disabled and read-only inputs - // - // HTML5 says that controls under a fieldset > legend:first-child won't be - // disabled if the fieldset is disabled. Due to implementation difficulty, we - // don't honor that edge case; we style them as disabled anyway. - &[disabled], - &[readonly], - fieldset[disabled] & { - cursor: not-allowed; - background-color: @input-bg-disabled; - opacity: 1; // iOS fix for unreadable disabled content - } - - // Reset height for `textarea`s - textarea& { - height: auto; - } -} - - -// Search inputs in iOS -// -// This overrides the extra rounded corners on search inputs in iOS so that our -// `.form-control` class can properly style them. Note that this cannot simply -// be added to `.form-control` as it's not specific enough. For details, see -// https://github.com/twbs/bootstrap/issues/11586. - -input[type="search"] { - -webkit-appearance: none; -} - - -// Special styles for iOS date input -// -// In Mobile Safari, date inputs require a pixel line-height that matches the -// given height of the input. - -input[type="date"] { - line-height: @input-height-base; -} - - -// Form groups -// -// Designed to help with the organization and spacing of vertical forms. For -// horizontal forms, use the predefined grid classes. - -.form-group { - margin-bottom: 15px; -} - - -// Checkboxes and radios -// -// Indent the labels to position radios/checkboxes as hanging controls. - -.radio, -.checkbox { - display: block; - min-height: @line-height-computed; // clear the floating input if there is no label text - margin-top: 10px; - margin-bottom: 10px; - padding-left: 20px; - label { - display: inline; - font-weight: normal; - cursor: pointer; - } -} -.radio input[type="radio"], -.radio-inline input[type="radio"], -.checkbox input[type="checkbox"], -.checkbox-inline input[type="checkbox"] { - float: left; - margin-left: -20px; -} -.radio + .radio, -.checkbox + .checkbox { - margin-top: -5px; // Move up sibling radios or checkboxes for tighter spacing -} - -// Radios and checkboxes on same line -.radio-inline, -.checkbox-inline { - display: inline-block; - padding-left: 20px; - margin-bottom: 0; - vertical-align: middle; - font-weight: normal; - cursor: pointer; -} -.radio-inline + .radio-inline, -.checkbox-inline + .checkbox-inline { - margin-top: 0; - margin-left: 10px; // space out consecutive inline controls -} - -// Apply same disabled cursor tweak as for inputs -// -// Note: Neither radios nor checkboxes can be readonly. -input[type="radio"], -input[type="checkbox"], -.radio, -.radio-inline, -.checkbox, -.checkbox-inline { - &[disabled], - fieldset[disabled] & { - cursor: not-allowed; - } -} - - -// Form control sizing -// -// Build on `.form-control` with modifier classes to decrease or increase the -// height and font-size of form controls. - -.input-sm { - .input-size(@input-height-small; @padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small); -} - -.input-lg { - .input-size(@input-height-large; @padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large); -} - - -// Form control feedback states -// -// Apply contextual and semantic states to individual form controls. - -.has-feedback { - // Enable absolute positioning - position: relative; - - // Ensure icons don't overlap text - .form-control { - padding-right: (@input-height-base * 1.25); - } - - // Feedback icon (requires .glyphicon classes) - .form-control-feedback { - position: absolute; - top: (@line-height-computed + 5); // Height of the `label` and its margin - right: 0; - display: block; - width: @input-height-base; - height: @input-height-base; - line-height: @input-height-base; - text-align: center; - } -} - -// Feedback states -.has-success { - .form-control-validation(@state-success-text; @state-success-text; @state-success-bg); -} -.has-warning { - .form-control-validation(@state-warning-text; @state-warning-text; @state-warning-bg); -} -.has-error { - .form-control-validation(@state-danger-text; @state-danger-text; @state-danger-bg); -} - - -// Static form control text -// -// Apply class to a `p` element to make any string of text align with labels in -// a horizontal form layout. - -.form-control-static { - margin-bottom: 0; // Remove default margin from `p` -} - - -// Help text -// -// Apply to any element you wish to create light text for placement immediately -// below a form control. Use for general help, formatting, or instructional text. - -.help-block { - display: block; // account for any element using help-block - margin-top: 5px; - margin-bottom: 10px; - color: lighten(@text-color, 25%); // lighten the text some for contrast -} - - - -// Inline forms -// -// Make forms appear inline(-block) by adding the `.form-inline` class. Inline -// forms begin stacked on extra small (mobile) devices and then go inline when -// viewports reach <768px. -// -// Requires wrapping inputs and labels with `.form-group` for proper display of -// default HTML form controls and our custom form controls (e.g., input groups). -// -// Heads up! This is mixin-ed into `.navbar-form` in navbars.less. - -.form-inline { - - // Kick in the inline - @media (min-width: @screen-sm-min) { - // Inline-block all the things for "inline" - .form-group { - display: inline-block; - margin-bottom: 0; - vertical-align: middle; - } - - // In navbar-form, allow folks to *not* use `.form-group` - .form-control { - display: inline-block; - width: auto; // Prevent labels from stacking above inputs in `.form-group` - vertical-align: middle; - } - // Input groups need that 100% width though - .input-group > .form-control { - width: 100%; - } - - .control-label { - margin-bottom: 0; - vertical-align: middle; - } - - // Remove default margin on radios/checkboxes that were used for stacking, and - // then undo the floating of radios and checkboxes to match (which also avoids - // a bug in WebKit: https://github.com/twbs/bootstrap/issues/1969). - .radio, - .checkbox { - display: inline-block; - margin-top: 0; - margin-bottom: 0; - padding-left: 0; - vertical-align: middle; - } - .radio input[type="radio"], - .checkbox input[type="checkbox"] { - float: none; - margin-left: 0; - } - - // Validation states - // - // Reposition the icon because it's now within a grid column and columns have - // `position: relative;` on them. Also accounts for the grid gutter padding. - .has-feedback .form-control-feedback { - top: 0; - } - } -} - - -// Horizontal forms -// -// Horizontal forms are built on grid classes and allow you to create forms with -// labels on the left and inputs on the right. - -.form-horizontal { - - // Consistent vertical alignment of labels, radios, and checkboxes - .control-label, - .radio, - .checkbox, - .radio-inline, - .checkbox-inline { - margin-top: 0; - margin-bottom: 0; - padding-top: (@padding-base-vertical + 1); // Default padding plus a border - } - // Account for padding we're adding to ensure the alignment and of help text - // and other content below items - .radio, - .checkbox { - min-height: (@line-height-computed + (@padding-base-vertical + 1)); - } - - // Make form groups behave like rows - .form-group { - .make-row(); - } - - .form-control-static { - padding-top: (@padding-base-vertical + 1); - } - - // Only right align form labels here when the columns stop stacking - @media (min-width: @screen-sm-min) { - .control-label { - text-align: right; - } - } - - // Validation states - // - // Reposition the icon because it's now within a grid column and columns have - // `position: relative;` on them. Also accounts for the grid gutter padding. - .has-feedback .form-control-feedback { - top: 0; - right: (@grid-gutter-width / 2); - } -}
diff --git a/docs/static/less/bootstrap/glyphicons.less b/docs/static/less/bootstrap/glyphicons.less deleted file mode 100644 index 789c5e7..0000000 --- a/docs/static/less/bootstrap/glyphicons.less +++ /dev/null
@@ -1,233 +0,0 @@ -// -// Glyphicons for Bootstrap -// -// Since icons are fonts, they can be placed anywhere text is placed and are -// thus automatically sized to match the surrounding child. To use, create an -// inline element with the appropriate classes, like so: -// -// <a href="#"><span class="glyphicon glyphicon-star"></span> Star</a> - -// Import the fonts -@font-face { - font-family: 'Glyphicons Halflings'; - src: ~"url('@{icon-font-path}@{icon-font-name}.eot')"; - src: ~"url('@{icon-font-path}@{icon-font-name}.eot?#iefix') format('embedded-opentype')", - ~"url('@{icon-font-path}@{icon-font-name}.woff') format('woff')", - ~"url('@{icon-font-path}@{icon-font-name}.ttf') format('truetype')", - ~"url('@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}') format('svg')"; -} - -// Catchall baseclass -.glyphicon { - position: relative; - top: 1px; - display: inline-block; - font-family: 'Glyphicons Halflings'; - font-style: normal; - font-weight: normal; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -// Individual icons -.glyphicon-asterisk { &:before { content: "\2a"; } } -.glyphicon-plus { &:before { content: "\2b"; } } -.glyphicon-euro { &:before { content: "\20ac"; } } -.glyphicon-minus { &:before { content: "\2212"; } } -.glyphicon-cloud { &:before { content: "\2601"; } } -.glyphicon-envelope { &:before { content: "\2709"; } } -.glyphicon-pencil { &:before { content: "\270f"; } } -.glyphicon-glass { &:before { content: "\e001"; } } -.glyphicon-music { &:before { content: "\e002"; } } -.glyphicon-search { &:before { content: "\e003"; } } -.glyphicon-heart { &:before { content: "\e005"; } } -.glyphicon-star { &:before { content: "\e006"; } } -.glyphicon-star-empty { &:before { content: "\e007"; } } -.glyphicon-user { &:before { content: "\e008"; } } -.glyphicon-film { &:before { content: "\e009"; } } -.glyphicon-th-large { &:before { content: "\e010"; } } -.glyphicon-th { &:before { content: "\e011"; } } -.glyphicon-th-list { &:before { content: "\e012"; } } -.glyphicon-ok { &:before { content: "\e013"; } } -.glyphicon-remove { &:before { content: "\e014"; } } -.glyphicon-zoom-in { &:before { content: "\e015"; } } -.glyphicon-zoom-out { &:before { content: "\e016"; } } -.glyphicon-off { &:before { content: "\e017"; } } -.glyphicon-signal { &:before { content: "\e018"; } } -.glyphicon-cog { &:before { content: "\e019"; } } -.glyphicon-trash { &:before { content: "\e020"; } } -.glyphicon-home { &:before { content: "\e021"; } } -.glyphicon-file { &:before { content: "\e022"; } } -.glyphicon-time { &:before { content: "\e023"; } } -.glyphicon-road { &:before { content: "\e024"; } } -.glyphicon-download-alt { &:before { content: "\e025"; } } -.glyphicon-download { &:before { content: "\e026"; } } -.glyphicon-upload { &:before { content: "\e027"; } } -.glyphicon-inbox { &:before { content: "\e028"; } } -.glyphicon-play-circle { &:before { content: "\e029"; } } -.glyphicon-repeat { &:before { content: "\e030"; } } -.glyphicon-refresh { &:before { content: "\e031"; } } -.glyphicon-list-alt { &:before { content: "\e032"; } } -.glyphicon-lock { &:before { content: "\e033"; } } -.glyphicon-flag { &:before { content: "\e034"; } } -.glyphicon-headphones { &:before { content: "\e035"; } } -.glyphicon-volume-off { &:before { content: "\e036"; } } -.glyphicon-volume-down { &:before { content: "\e037"; } } -.glyphicon-volume-up { &:before { content: "\e038"; } } -.glyphicon-qrcode { &:before { content: "\e039"; } } -.glyphicon-barcode { &:before { content: "\e040"; } } -.glyphicon-tag { &:before { content: "\e041"; } } -.glyphicon-tags { &:before { content: "\e042"; } } -.glyphicon-book { &:before { content: "\e043"; } } -.glyphicon-bookmark { &:before { content: "\e044"; } } -.glyphicon-print { &:before { content: "\e045"; } } -.glyphicon-camera { &:before { content: "\e046"; } } -.glyphicon-font { &:before { content: "\e047"; } } -.glyphicon-bold { &:before { content: "\e048"; } } -.glyphicon-italic { &:before { content: "\e049"; } } -.glyphicon-text-height { &:before { content: "\e050"; } } -.glyphicon-text-width { &:before { content: "\e051"; } } -.glyphicon-align-left { &:before { content: "\e052"; } } -.glyphicon-align-center { &:before { content: "\e053"; } } -.glyphicon-align-right { &:before { content: "\e054"; } } -.glyphicon-align-justify { &:before { content: "\e055"; } } -.glyphicon-list { &:before { content: "\e056"; } } -.glyphicon-indent-left { &:before { content: "\e057"; } } -.glyphicon-indent-right { &:before { content: "\e058"; } } -.glyphicon-facetime-video { &:before { content: "\e059"; } } -.glyphicon-picture { &:before { content: "\e060"; } } -.glyphicon-map-marker { &:before { content: "\e062"; } } -.glyphicon-adjust { &:before { content: "\e063"; } } -.glyphicon-tint { &:before { content: "\e064"; } } -.glyphicon-edit { &:before { content: "\e065"; } } -.glyphicon-share { &:before { content: "\e066"; } } -.glyphicon-check { &:before { content: "\e067"; } } -.glyphicon-move { &:before { content: "\e068"; } } -.glyphicon-step-backward { &:before { content: "\e069"; } } -.glyphicon-fast-backward { &:before { content: "\e070"; } } -.glyphicon-backward { &:before { content: "\e071"; } } -.glyphicon-play { &:before { content: "\e072"; } } -.glyphicon-pause { &:before { content: "\e073"; } } -.glyphicon-stop { &:before { content: "\e074"; } } -.glyphicon-forward { &:before { content: "\e075"; } } -.glyphicon-fast-forward { &:before { content: "\e076"; } } -.glyphicon-step-forward { &:before { content: "\e077"; } } -.glyphicon-eject { &:before { content: "\e078"; } } -.glyphicon-chevron-left { &:before { content: "\e079"; } } -.glyphicon-chevron-right { &:before { content: "\e080"; } } -.glyphicon-plus-sign { &:before { content: "\e081"; } } -.glyphicon-minus-sign { &:before { content: "\e082"; } } -.glyphicon-remove-sign { &:before { content: "\e083"; } } -.glyphicon-ok-sign { &:before { content: "\e084"; } } -.glyphicon-question-sign { &:before { content: "\e085"; } } -.glyphicon-info-sign { &:before { content: "\e086"; } } -.glyphicon-screenshot { &:before { content: "\e087"; } } -.glyphicon-remove-circle { &:before { content: "\e088"; } } -.glyphicon-ok-circle { &:before { content: "\e089"; } } -.glyphicon-ban-circle { &:before { content: "\e090"; } } -.glyphicon-arrow-left { &:before { content: "\e091"; } } -.glyphicon-arrow-right { &:before { content: "\e092"; } } -.glyphicon-arrow-up { &:before { content: "\e093"; } } -.glyphicon-arrow-down { &:before { content: "\e094"; } } -.glyphicon-share-alt { &:before { content: "\e095"; } } -.glyphicon-resize-full { &:before { content: "\e096"; } } -.glyphicon-resize-small { &:before { content: "\e097"; } } -.glyphicon-exclamation-sign { &:before { content: "\e101"; } } -.glyphicon-gift { &:before { content: "\e102"; } } -.glyphicon-leaf { &:before { content: "\e103"; } } -.glyphicon-fire { &:before { content: "\e104"; } } -.glyphicon-eye-open { &:before { content: "\e105"; } } -.glyphicon-eye-close { &:before { content: "\e106"; } } -.glyphicon-warning-sign { &:before { content: "\e107"; } } -.glyphicon-plane { &:before { content: "\e108"; } } -.glyphicon-calendar { &:before { content: "\e109"; } } -.glyphicon-random { &:before { content: "\e110"; } } -.glyphicon-comment { &:before { content: "\e111"; } } -.glyphicon-magnet { &:before { content: "\e112"; } } -.glyphicon-chevron-up { &:before { content: "\e113"; } } -.glyphicon-chevron-down { &:before { content: "\e114"; } } -.glyphicon-retweet { &:before { content: "\e115"; } } -.glyphicon-shopping-cart { &:before { content: "\e116"; } } -.glyphicon-folder-close { &:before { content: "\e117"; } } -.glyphicon-folder-open { &:before { content: "\e118"; } } -.glyphicon-resize-vertical { &:before { content: "\e119"; } } -.glyphicon-resize-horizontal { &:before { content: "\e120"; } } -.glyphicon-hdd { &:before { content: "\e121"; } } -.glyphicon-bullhorn { &:before { content: "\e122"; } } -.glyphicon-bell { &:before { content: "\e123"; } } -.glyphicon-certificate { &:before { content: "\e124"; } } -.glyphicon-thumbs-up { &:before { content: "\e125"; } } -.glyphicon-thumbs-down { &:before { content: "\e126"; } } -.glyphicon-hand-right { &:before { content: "\e127"; } } -.glyphicon-hand-left { &:before { content: "\e128"; } } -.glyphicon-hand-up { &:before { content: "\e129"; } } -.glyphicon-hand-down { &:before { content: "\e130"; } } -.glyphicon-circle-arrow-right { &:before { content: "\e131"; } } -.glyphicon-circle-arrow-left { &:before { content: "\e132"; } } -.glyphicon-circle-arrow-up { &:before { content: "\e133"; } } -.glyphicon-circle-arrow-down { &:before { content: "\e134"; } } -.glyphicon-globe { &:before { content: "\e135"; } } -.glyphicon-wrench { &:before { content: "\e136"; } } -.glyphicon-tasks { &:before { content: "\e137"; } } -.glyphicon-filter { &:before { content: "\e138"; } } -.glyphicon-briefcase { &:before { content: "\e139"; } } -.glyphicon-fullscreen { &:before { content: "\e140"; } } -.glyphicon-dashboard { &:before { content: "\e141"; } } -.glyphicon-paperclip { &:before { content: "\e142"; } } -.glyphicon-heart-empty { &:before { content: "\e143"; } } -.glyphicon-link { &:before { content: "\e144"; } } -.glyphicon-phone { &:before { content: "\e145"; } } -.glyphicon-pushpin { &:before { content: "\e146"; } } -.glyphicon-usd { &:before { content: "\e148"; } } -.glyphicon-gbp { &:before { content: "\e149"; } } -.glyphicon-sort { &:before { content: "\e150"; } } -.glyphicon-sort-by-alphabet { &:before { content: "\e151"; } } -.glyphicon-sort-by-alphabet-alt { &:before { content: "\e152"; } } -.glyphicon-sort-by-order { &:before { content: "\e153"; } } -.glyphicon-sort-by-order-alt { &:before { content: "\e154"; } } -.glyphicon-sort-by-attributes { &:before { content: "\e155"; } } -.glyphicon-sort-by-attributes-alt { &:before { content: "\e156"; } } -.glyphicon-unchecked { &:before { content: "\e157"; } } -.glyphicon-expand { &:before { content: "\e158"; } } -.glyphicon-collapse-down { &:before { content: "\e159"; } } -.glyphicon-collapse-up { &:before { content: "\e160"; } } -.glyphicon-log-in { &:before { content: "\e161"; } } -.glyphicon-flash { &:before { content: "\e162"; } } -.glyphicon-log-out { &:before { content: "\e163"; } } -.glyphicon-new-window { &:before { content: "\e164"; } } -.glyphicon-record { &:before { content: "\e165"; } } -.glyphicon-save { &:before { content: "\e166"; } } -.glyphicon-open { &:before { content: "\e167"; } } -.glyphicon-saved { &:before { content: "\e168"; } } -.glyphicon-import { &:before { content: "\e169"; } } -.glyphicon-export { &:before { content: "\e170"; } } -.glyphicon-send { &:before { content: "\e171"; } } -.glyphicon-floppy-disk { &:before { content: "\e172"; } } -.glyphicon-floppy-saved { &:before { content: "\e173"; } } -.glyphicon-floppy-remove { &:before { content: "\e174"; } } -.glyphicon-floppy-save { &:before { content: "\e175"; } } -.glyphicon-floppy-open { &:before { content: "\e176"; } } -.glyphicon-credit-card { &:before { content: "\e177"; } } -.glyphicon-transfer { &:before { content: "\e178"; } } -.glyphicon-cutlery { &:before { content: "\e179"; } } -.glyphicon-header { &:before { content: "\e180"; } } -.glyphicon-compressed { &:before { content: "\e181"; } } -.glyphicon-earphone { &:before { content: "\e182"; } } -.glyphicon-phone-alt { &:before { content: "\e183"; } } -.glyphicon-tower { &:before { content: "\e184"; } } -.glyphicon-stats { &:before { content: "\e185"; } } -.glyphicon-sd-video { &:before { content: "\e186"; } } -.glyphicon-hd-video { &:before { content: "\e187"; } } -.glyphicon-subtitles { &:before { content: "\e188"; } } -.glyphicon-sound-stereo { &:before { content: "\e189"; } } -.glyphicon-sound-dolby { &:before { content: "\e190"; } } -.glyphicon-sound-5-1 { &:before { content: "\e191"; } } -.glyphicon-sound-6-1 { &:before { content: "\e192"; } } -.glyphicon-sound-7-1 { &:before { content: "\e193"; } } -.glyphicon-copyright-mark { &:before { content: "\e194"; } } -.glyphicon-registration-mark { &:before { content: "\e195"; } } -.glyphicon-cloud-download { &:before { content: "\e197"; } } -.glyphicon-cloud-upload { &:before { content: "\e198"; } } -.glyphicon-tree-conifer { &:before { content: "\e199"; } } -.glyphicon-tree-deciduous { &:before { content: "\e200"; } }
diff --git a/docs/static/less/bootstrap/grid.less b/docs/static/less/bootstrap/grid.less deleted file mode 100644 index e100655..0000000 --- a/docs/static/less/bootstrap/grid.less +++ /dev/null
@@ -1,84 +0,0 @@ -// -// Grid system -// -------------------------------------------------- - - -// Container widths -// -// Set the container width, and override it for fixed navbars in media queries. - -.container { - .container-fixed(); - - @media (min-width: @screen-sm-min) { - width: @container-sm; - } - @media (min-width: @screen-md-min) { - width: @container-md; - } - @media (min-width: @screen-lg-min) { - width: @container-lg; - } -} - - -// Fluid container -// -// Utilizes the mixin meant for fixed width containers, but without any defined -// width for fluid, full width layouts. - -.container-fluid { - .container-fixed(); -} - - -// Row -// -// Rows contain and clear the floats of your columns. - -.row { - .make-row(); -} - - -// Columns -// -// Common styles for small and large grid columns - -.make-grid-columns(); - - -// Extra small grid -// -// Columns, offsets, pushes, and pulls for extra small devices like -// smartphones. - -.make-grid(xs); - - -// Small grid -// -// Columns, offsets, pushes, and pulls for the small device range, from phones -// to tablets. - -@media (min-width: @screen-sm-min) { - .make-grid(sm); -} - - -// Medium grid -// -// Columns, offsets, pushes, and pulls for the desktop device range. - -@media (min-width: @screen-md-min) { - .make-grid(md); -} - - -// Large grid -// -// Columns, offsets, pushes, and pulls for the large desktop device range. - -@media (min-width: @screen-lg-min) { - .make-grid(lg); -}
diff --git a/docs/static/less/bootstrap/input-groups.less b/docs/static/less/bootstrap/input-groups.less deleted file mode 100644 index a111474..0000000 --- a/docs/static/less/bootstrap/input-groups.less +++ /dev/null
@@ -1,162 +0,0 @@ -// -// Input groups -// -------------------------------------------------- - -// Base styles -// ------------------------- -.input-group { - position: relative; // For dropdowns - display: table; - border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table - - // Undo padding and float of grid classes - &[class*="col-"] { - float: none; - padding-left: 0; - padding-right: 0; - } - - .form-control { - // Ensure that the input is always above the *appended* addon button for - // proper border colors. - position: relative; - z-index: 2; - - // IE9 fubars the placeholder attribute in text inputs and the arrows on - // select elements in input groups. To fix it, we float the input. Details: - // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855 - float: left; - - width: 100%; - margin-bottom: 0; - } -} - -// Sizing options -// -// Remix the default form control sizing classes into new ones for easier -// manipulation. - -.input-group-lg > .form-control, -.input-group-lg > .input-group-addon, -.input-group-lg > .input-group-btn > .btn { .input-lg(); } -.input-group-sm > .form-control, -.input-group-sm > .input-group-addon, -.input-group-sm > .input-group-btn > .btn { .input-sm(); } - - -// Display as table-cell -// ------------------------- -.input-group-addon, -.input-group-btn, -.input-group .form-control { - display: table-cell; - - &:not(:first-child):not(:last-child) { - border-radius: 0; - } -} -// Addon and addon wrapper for buttons -.input-group-addon, -.input-group-btn { - width: 1%; - white-space: nowrap; - vertical-align: middle; // Match the inputs -} - -// Text input groups -// ------------------------- -.input-group-addon { - padding: @padding-base-vertical @padding-base-horizontal; - font-size: @font-size-base; - font-weight: normal; - line-height: 1; - color: @input-color; - text-align: center; - background-color: @input-group-addon-bg; - border: 1px solid @input-group-addon-border-color; - border-radius: @border-radius-base; - - // Sizing - &.input-sm { - padding: @padding-small-vertical @padding-small-horizontal; - font-size: @font-size-small; - border-radius: @border-radius-small; - } - &.input-lg { - padding: @padding-large-vertical @padding-large-horizontal; - font-size: @font-size-large; - border-radius: @border-radius-large; - } - - // Nuke default margins from checkboxes and radios to vertically center within. - input[type="radio"], - input[type="checkbox"] { - margin-top: 0; - } -} - -// Reset rounded corners -.input-group .form-control:first-child, -.input-group-addon:first-child, -.input-group-btn:first-child > .btn, -.input-group-btn:first-child > .btn-group > .btn, -.input-group-btn:first-child > .dropdown-toggle, -.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), -.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { - .border-right-radius(0); -} -.input-group-addon:first-child { - border-right: 0; -} -.input-group .form-control:last-child, -.input-group-addon:last-child, -.input-group-btn:last-child > .btn, -.input-group-btn:last-child > .btn-group > .btn, -.input-group-btn:last-child > .dropdown-toggle, -.input-group-btn:first-child > .btn:not(:first-child), -.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { - .border-left-radius(0); -} -.input-group-addon:last-child { - border-left: 0; -} - -// Button input groups -// ------------------------- -.input-group-btn { - position: relative; - // Jankily prevent input button groups from wrapping with `white-space` and - // `font-size` in combination with `inline-block` on buttons. - font-size: 0; - white-space: nowrap; - - // Negative margin for spacing, position for bringing hovered/focused/actived - // element above the siblings. - > .btn { - position: relative; - + .btn { - margin-left: -1px; - } - // Bring the "active" button to the front - &:hover, - &:focus, - &:active { - z-index: 2; - } - } - - // Negative margin to only have a 1px border between the two - &:first-child { - > .btn, - > .btn-group { - margin-right: -1px; - } - } - &:last-child { - > .btn, - > .btn-group { - margin-left: -1px; - } - } -}
diff --git a/docs/static/less/bootstrap/jumbotron.less b/docs/static/less/bootstrap/jumbotron.less deleted file mode 100644 index a15e169..0000000 --- a/docs/static/less/bootstrap/jumbotron.less +++ /dev/null
@@ -1,44 +0,0 @@ -// -// Jumbotron -// -------------------------------------------------- - - -.jumbotron { - padding: @jumbotron-padding; - margin-bottom: @jumbotron-padding; - color: @jumbotron-color; - background-color: @jumbotron-bg; - - h1, - .h1 { - color: @jumbotron-heading-color; - } - p { - margin-bottom: (@jumbotron-padding / 2); - font-size: @jumbotron-font-size; - font-weight: 200; - } - - .container & { - border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container - } - - .container { - max-width: 100%; - } - - @media screen and (min-width: @screen-sm-min) { - padding-top: (@jumbotron-padding * 1.6); - padding-bottom: (@jumbotron-padding * 1.6); - - .container & { - padding-left: (@jumbotron-padding * 2); - padding-right: (@jumbotron-padding * 2); - } - - h1, - .h1 { - font-size: (@font-size-base * 4.5); - } - } -}
diff --git a/docs/static/less/bootstrap/labels.less b/docs/static/less/bootstrap/labels.less deleted file mode 100644 index 5db1ed1..0000000 --- a/docs/static/less/bootstrap/labels.less +++ /dev/null
@@ -1,64 +0,0 @@ -// -// Labels -// -------------------------------------------------- - -.label { - display: inline; - padding: .2em .6em .3em; - font-size: 75%; - font-weight: bold; - line-height: 1; - color: @label-color; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - border-radius: .25em; - - // Add hover effects, but only for links - &[href] { - &:hover, - &:focus { - color: @label-link-hover-color; - text-decoration: none; - cursor: pointer; - } - } - - // Empty labels collapse automatically (not available in IE8) - &:empty { - display: none; - } - - // Quick fix for labels in buttons - .btn & { - position: relative; - top: -1px; - } -} - -// Colors -// Contextual variations (linked labels get darker on :hover) - -.label-default { - .label-variant(@label-default-bg); -} - -.label-primary { - .label-variant(@label-primary-bg); -} - -.label-success { - .label-variant(@label-success-bg); -} - -.label-info { - .label-variant(@label-info-bg); -} - -.label-warning { - .label-variant(@label-warning-bg); -} - -.label-danger { - .label-variant(@label-danger-bg); -}
diff --git a/docs/static/less/bootstrap/list-group.less b/docs/static/less/bootstrap/list-group.less deleted file mode 100644 index 3343f8e..0000000 --- a/docs/static/less/bootstrap/list-group.less +++ /dev/null
@@ -1,110 +0,0 @@ -// -// List groups -// -------------------------------------------------- - - -// Base class -// -// Easily usable on <ul>, <ol>, or <div>. - -.list-group { - // No need to set list-style: none; since .list-group-item is block level - margin-bottom: 20px; - padding-left: 0; // reset padding because ul and ol -} - - -// Individual list items -// -// Use on `li`s or `div`s within the `.list-group` parent. - -.list-group-item { - position: relative; - display: block; - padding: 10px 15px; - // Place the border on the list items and negative margin up for better styling - margin-bottom: -1px; - background-color: @list-group-bg; - border: 1px solid @list-group-border; - - // Round the first and last items - &:first-child { - .border-top-radius(@list-group-border-radius); - } - &:last-child { - margin-bottom: 0; - .border-bottom-radius(@list-group-border-radius); - } - - // Align badges within list items - > .badge { - float: right; - } - > .badge + .badge { - margin-right: 5px; - } -} - - -// Linked list items -// -// Use anchor elements instead of `li`s or `div`s to create linked list items. -// Includes an extra `.active` modifier class for showing selected items. - -a.list-group-item { - color: @list-group-link-color; - - .list-group-item-heading { - color: @list-group-link-heading-color; - } - - // Hover state - &:hover, - &:focus { - text-decoration: none; - background-color: @list-group-hover-bg; - } - - // Active class on item itself, not parent - &.active, - &.active:hover, - &.active:focus { - z-index: 2; // Place active items above their siblings for proper border styling - color: @list-group-active-color; - background-color: @list-group-active-bg; - border-color: @list-group-active-border; - - // Force color to inherit for custom content - .list-group-item-heading { - color: inherit; - } - .list-group-item-text { - color: @list-group-active-text-color; - } - } -} - - -// Contextual variants -// -// Add modifier classes to change text and background color on individual items. -// Organizationally, this must come after the `:hover` states. - -.list-group-item-variant(success; @state-success-bg; @state-success-text); -.list-group-item-variant(info; @state-info-bg; @state-info-text); -.list-group-item-variant(warning; @state-warning-bg; @state-warning-text); -.list-group-item-variant(danger; @state-danger-bg; @state-danger-text); - - -// Custom content options -// -// Extra classes for creating well-formatted content within `.list-group-item`s. - -.list-group-item-heading { - margin-top: 0; - margin-bottom: 5px; -} -.list-group-item-text { - margin-bottom: 0; - line-height: 1.3; -}
diff --git a/docs/static/less/bootstrap/media.less b/docs/static/less/bootstrap/media.less deleted file mode 100644 index 5ad22cd..0000000 --- a/docs/static/less/bootstrap/media.less +++ /dev/null
@@ -1,56 +0,0 @@ -// Media objects -// Source: http://stubbornella.org/content/?p=497 -// -------------------------------------------------- - - -// Common styles -// ------------------------- - -// Clear the floats -.media, -.media-body { - overflow: hidden; - zoom: 1; -} - -// Proper spacing between instances of .media -.media, -.media .media { - margin-top: 15px; -} -.media:first-child { - margin-top: 0; -} - -// For images and videos, set to block -.media-object { - display: block; -} - -// Reset margins on headings for tighter default spacing -.media-heading { - margin: 0 0 5px; -} - - -// Media image alignment -// ------------------------- - -.media { - > .pull-left { - margin-right: 10px; - } - > .pull-right { - margin-left: 10px; - } -} - - -// Media list variation -// ------------------------- - -// Undo default ul/ol styles -.media-list { - padding-left: 0; - list-style: none; -}
diff --git a/docs/static/less/bootstrap/mixins.less b/docs/static/less/bootstrap/mixins.less deleted file mode 100644 index 71723db..0000000 --- a/docs/static/less/bootstrap/mixins.less +++ /dev/null
@@ -1,929 +0,0 @@ -// -// Mixins -// -------------------------------------------------- - - -// Utilities -// ------------------------- - -// Clearfix -// Source: http://nicolasgallagher.com/micro-clearfix-hack/ -// -// For modern browsers -// 1. The space content is one way to avoid an Opera bug when the -// contenteditable attribute is included anywhere else in the document. -// Otherwise it causes space to appear at the top and bottom of elements -// that are clearfixed. -// 2. The use of `table` rather than `block` is only necessary if using -// `:before` to contain the top-margins of child elements. -.clearfix() { - &:before, - &:after { - content: " "; // 1 - display: table; // 2 - } - &:after { - clear: both; - } -} - -// WebKit-style focus -.tab-focus() { - // Default - outline: thin dotted; - // WebKit - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} - -// Center-align a block level element -.center-block() { - display: block; - margin-left: auto; - margin-right: auto; -} - -// Sizing shortcuts -.size(@width; @height) { - width: @width; - height: @height; -} -.square(@size) { - .size(@size; @size); -} - -// Placeholder text -.placeholder(@color: @input-color-placeholder) { - &::-moz-placeholder { color: @color; // Firefox - opacity: 1; } // See https://github.com/twbs/bootstrap/pull/11526 - &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+ - &::-webkit-input-placeholder { color: @color; } // Safari and Chrome -} - -// Text overflow -// Requires inline-block or block for proper styling -.text-overflow() { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -// CSS image replacement -// -// Heads up! v3 launched with with only `.hide-text()`, but per our pattern for -// mixins being reused as classes with the same name, this doesn't hold up. As -// of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`. Note -// that we cannot chain the mixins together in Less, so they are repeated. -// -// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757 - -// Deprecated as of v3.0.1 (will be removed in v4) -.hide-text() { - font: ~"0/0" a; - color: transparent; - text-shadow: none; - background-color: transparent; - border: 0; -} -// New mixin to use as of v3.0.1 -.text-hide() { - .hide-text(); -} - - - -// CSS3 PROPERTIES -// -------------------------------------------------- - -// Single side border-radius -.border-top-radius(@radius) { - border-top-right-radius: @radius; - border-top-left-radius: @radius; -} -.border-right-radius(@radius) { - border-bottom-right-radius: @radius; - border-top-right-radius: @radius; -} -.border-bottom-radius(@radius) { - border-bottom-right-radius: @radius; - border-bottom-left-radius: @radius; -} -.border-left-radius(@radius) { - border-bottom-left-radius: @radius; - border-top-left-radius: @radius; -} - -// Drop shadows -// -// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's -// supported browsers that have box shadow capabilities now support the -// standard `box-shadow` property. -.box-shadow(@shadow) { - -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1 - box-shadow: @shadow; -} - -// Transitions -.transition(@transition) { - -webkit-transition: @transition; - transition: @transition; -} -.transition-property(@transition-property) { - -webkit-transition-property: @transition-property; - transition-property: @transition-property; -} -.transition-delay(@transition-delay) { - -webkit-transition-delay: @transition-delay; - transition-delay: @transition-delay; -} -.transition-duration(@transition-duration) { - -webkit-transition-duration: @transition-duration; - transition-duration: @transition-duration; -} -.transition-transform(@transition) { - -webkit-transition: -webkit-transform @transition; - -moz-transition: -moz-transform @transition; - -o-transition: -o-transform @transition; - transition: transform @transition; -} - -// Transformations -.rotate(@degrees) { - -webkit-transform: rotate(@degrees); - -ms-transform: rotate(@degrees); // IE9 only - transform: rotate(@degrees); -} -.scale(@ratio; @ratio-y...) { - -webkit-transform: scale(@ratio, @ratio-y); - -ms-transform: scale(@ratio, @ratio-y); // IE9 only - transform: scale(@ratio, @ratio-y); -} -.translate(@x; @y) { - -webkit-transform: translate(@x, @y); - -ms-transform: translate(@x, @y); // IE9 only - transform: translate(@x, @y); -} -.skew(@x; @y) { - -webkit-transform: skew(@x, @y); - -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+ - transform: skew(@x, @y); -} -.translate3d(@x; @y; @z) { - -webkit-transform: translate3d(@x, @y, @z); - transform: translate3d(@x, @y, @z); -} - -.rotateX(@degrees) { - -webkit-transform: rotateX(@degrees); - -ms-transform: rotateX(@degrees); // IE9 only - transform: rotateX(@degrees); -} -.rotateY(@degrees) { - -webkit-transform: rotateY(@degrees); - -ms-transform: rotateY(@degrees); // IE9 only - transform: rotateY(@degrees); -} -.perspective(@perspective) { - -webkit-perspective: @perspective; - -moz-perspective: @perspective; - perspective: @perspective; -} -.perspective-origin(@perspective) { - -webkit-perspective-origin: @perspective; - -moz-perspective-origin: @perspective; - perspective-origin: @perspective; -} -.transform-origin(@origin) { - -webkit-transform-origin: @origin; - -moz-transform-origin: @origin; - -ms-transform-origin: @origin; // IE9 only - transform-origin: @origin; -} - -// Animations -.animation(@animation) { - -webkit-animation: @animation; - animation: @animation; -} -.animation-name(@name) { - -webkit-animation-name: @name; - animation-name: @name; -} -.animation-duration(@duration) { - -webkit-animation-duration: @duration; - animation-duration: @duration; -} -.animation-timing-function(@timing-function) { - -webkit-animation-timing-function: @timing-function; - animation-timing-function: @timing-function; -} -.animation-delay(@delay) { - -webkit-animation-delay: @delay; - animation-delay: @delay; -} -.animation-iteration-count(@iteration-count) { - -webkit-animation-iteration-count: @iteration-count; - animation-iteration-count: @iteration-count; -} -.animation-direction(@direction) { - -webkit-animation-direction: @direction; - animation-direction: @direction; -} - -// Backface visibility -// Prevent browsers from flickering when using CSS 3D transforms. -// Default value is `visible`, but can be changed to `hidden` -.backface-visibility(@visibility){ - -webkit-backface-visibility: @visibility; - -moz-backface-visibility: @visibility; - backface-visibility: @visibility; -} - -// Box sizing -.box-sizing(@boxmodel) { - -webkit-box-sizing: @boxmodel; - -moz-box-sizing: @boxmodel; - box-sizing: @boxmodel; -} - -// User select -// For selecting text on the page -.user-select(@select) { - -webkit-user-select: @select; - -moz-user-select: @select; - -ms-user-select: @select; // IE10+ - user-select: @select; -} - -// Resize anything -.resizable(@direction) { - resize: @direction; // Options: horizontal, vertical, both - overflow: auto; // Safari fix -} - -// CSS3 Content Columns -.content-columns(@column-count; @column-gap: @grid-gutter-width) { - -webkit-column-count: @column-count; - -moz-column-count: @column-count; - column-count: @column-count; - -webkit-column-gap: @column-gap; - -moz-column-gap: @column-gap; - column-gap: @column-gap; -} - -// Optional hyphenation -.hyphens(@mode: auto) { - word-wrap: break-word; - -webkit-hyphens: @mode; - -moz-hyphens: @mode; - -ms-hyphens: @mode; // IE10+ - -o-hyphens: @mode; - hyphens: @mode; -} - -// Opacity -.opacity(@opacity) { - opacity: @opacity; - // IE8 filter - @opacity-ie: (@opacity * 100); - filter: ~"alpha(opacity=@{opacity-ie})"; -} - - - -// GRADIENTS -// -------------------------------------------------- - -#gradient { - - // Horizontal gradient, from left to right - // - // Creates two color stops, start and end, by specifying a color and position for each color stop. - // Color stops are not available in IE9 and below. - .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) { - background-image: -webkit-linear-gradient(left, color-stop(@start-color @start-percent), color-stop(@end-color @end-percent)); // Safari 5.1-6, Chrome 10+ - background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+ - background-repeat: repeat-x; - filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)",argb(@start-color),argb(@end-color))); // IE9 and down - } - - // Vertical gradient, from top to bottom - // - // Creates two color stops, start and end, by specifying a color and position for each color stop. - // Color stops are not available in IE9 and below. - .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) { - background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+ - background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+ - background-repeat: repeat-x; - filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",argb(@start-color),argb(@end-color))); // IE9 and down - } - - .directional(@start-color: #555; @end-color: #333; @deg: 45deg) { - background-repeat: repeat-x; - background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+ - background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+ - } - .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) { - background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color); - background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color); - background-repeat: no-repeat; - filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback - } - .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) { - background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color); - background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color); - background-repeat: no-repeat; - filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback - } - .radial(@inner-color: #555; @outer-color: #333) { - background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color); - background-image: radial-gradient(circle, @inner-color, @outer-color); - background-repeat: no-repeat; - } - .striped(@color: rgba(255,255,255,.15); @angle: 45deg) { - background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent); - background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent); - } -} - -// Reset filters for IE -// -// When you need to remove a gradient background, do not forget to use this to reset -// the IE filter for IE9 and below. -.reset-filter() { - filter: e(%("progid:DXImageTransform.Microsoft.gradient(enabled = false)")); -} - - - -// Retina images -// -// Short retina mixin for setting background-image and -size - -.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) { - background-image: url("@{file-1x}"); - - @media - only screen and (-webkit-min-device-pixel-ratio: 2), - only screen and ( min--moz-device-pixel-ratio: 2), - only screen and ( -o-min-device-pixel-ratio: 2/1), - only screen and ( min-device-pixel-ratio: 2), - only screen and ( min-resolution: 192dpi), - only screen and ( min-resolution: 2dppx) { - background-image: url("@{file-2x}"); - background-size: @width-1x @height-1x; - } -} - - -// Responsive image -// -// Keep images from scaling beyond the width of their parents. - -.img-responsive(@display: block) { - display: @display; - max-width: 100%; // Part 1: Set a maximum relative to the parent - height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching -} - - -// COMPONENT MIXINS -// -------------------------------------------------- - -// Horizontal dividers -// ------------------------- -// Dividers (basically an hr) within dropdowns and nav lists -.nav-divider(@color: #e5e5e5) { - height: 1px; - margin: ((@line-height-computed / 2) - 1) 0; - overflow: hidden; - background-color: @color; -} - -// Panels -// ------------------------- -.panel-variant(@border; @heading-text-color; @heading-bg-color; @heading-border) { - border-color: @border; - - & > .panel-heading { - color: @heading-text-color; - background-color: @heading-bg-color; - border-color: @heading-border; - - + .panel-collapse .panel-body { - border-top-color: @border; - } - } - & > .panel-footer { - + .panel-collapse .panel-body { - border-bottom-color: @border; - } - } -} - -// Alerts -// ------------------------- -.alert-variant(@background; @border; @text-color) { - background-color: @background; - border-color: @border; - color: @text-color; - - hr { - border-top-color: darken(@border, 5%); - } - .alert-link { - color: darken(@text-color, 10%); - } -} - -// Tables -// ------------------------- -.table-row-variant(@state; @background) { - // Exact selectors below required to override `.table-striped` and prevent - // inheritance to nested tables. - .table > thead > tr, - .table > tbody > tr, - .table > tfoot > tr { - > td.@{state}, - > th.@{state}, - &.@{state} > td, - &.@{state} > th { - background-color: @background; - } - } - - // Hover states for `.table-hover` - // Note: this is not available for cells or rows within `thead` or `tfoot`. - .table-hover > tbody > tr { - > td.@{state}:hover, - > th.@{state}:hover, - &.@{state}:hover > td, - &.@{state}:hover > th { - background-color: darken(@background, 5%); - } - } -} - -// List Groups -// ------------------------- -.list-group-item-variant(@state; @background; @color) { - .list-group-item-@{state} { - color: @color; - background-color: @background; - - a& { - color: @color; - - .list-group-item-heading { color: inherit; } - - &:hover, - &:focus { - color: @color; - background-color: darken(@background, 5%); - } - &.active, - &.active:hover, - &.active:focus { - color: #fff; - background-color: @color; - border-color: @color; - } - } - } -} - -// Button variants -// ------------------------- -// Easily pump out default styles, as well as :hover, :focus, :active, -// and disabled options for all buttons -.button-variant(@color; @background; @border) { - color: @color; - background-color: @background; - border-color: @border; - - &:hover, - &:focus, - &:active, - &.active, - .open .dropdown-toggle& { - color: @color; - background-color: darken(@background, 8%); - border-color: darken(@border, 12%); - } - &:active, - &.active, - .open .dropdown-toggle& { - background-image: none; - } - &.disabled, - &[disabled], - fieldset[disabled] & { - &, - &:hover, - &:focus, - &:active, - &.active { - background-color: @background; - border-color: @border; - } - } - - .badge { - color: @background; - background-color: @color; - } -} - -// Button sizes -// ------------------------- -.button-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) { - padding: @padding-vertical @padding-horizontal; - font-size: @font-size; - line-height: @line-height; - border-radius: @border-radius; -} - -// Pagination -// ------------------------- -.pagination-size(@padding-vertical; @padding-horizontal; @font-size; @border-radius) { - > li { - > a, - > span { - padding: @padding-vertical @padding-horizontal; - font-size: @font-size; - } - &:first-child { - > a, - > span { - .border-left-radius(@border-radius); - } - } - &:last-child { - > a, - > span { - .border-right-radius(@border-radius); - } - } - } -} - -// Labels -// ------------------------- -.label-variant(@color) { - background-color: @color; - &[href] { - &:hover, - &:focus { - background-color: darken(@color, 10%); - } - } -} - -// Contextual backgrounds -// ------------------------- -.bg-variant(@color) { - background-color: @color; - a&:hover { - background-color: darken(@color, 10%); - } -} - -// Typography -// ------------------------- -.text-emphasis-variant(@color) { - color: @color; - a&:hover { - color: darken(@color, 10%); - } -} - -// Navbar vertical align -// ------------------------- -// Vertically center elements in the navbar. -// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin. -.navbar-vertical-align(@element-height) { - margin-top: ((@navbar-height - @element-height) / 2); - margin-bottom: ((@navbar-height - @element-height) / 2); -} - -// Progress bars -// ------------------------- -.progress-bar-variant(@color) { - background-color: @color; - .progress-striped & { - #gradient > .striped(); - } -} - -// Responsive utilities -// ------------------------- -// More easily include all the states for responsive-utilities.less. -.responsive-visibility() { - display: block !important; - table& { display: table; } - tr& { display: table-row !important; } - th&, - td& { display: table-cell !important; } -} - -.responsive-invisibility() { - display: none !important; -} - - -// Grid System -// ----------- - -// Centered container element -.container-fixed() { - margin-right: auto; - margin-left: auto; - padding-left: (@grid-gutter-width / 2); - padding-right: (@grid-gutter-width / 2); - &:extend(.clearfix all); -} - -// Creates a wrapper for a series of columns -.make-row(@gutter: @grid-gutter-width) { - margin-left: (@gutter / -2); - margin-right: (@gutter / -2); - &:extend(.clearfix all); -} - -// Generate the extra small columns -.make-xs-column(@columns; @gutter: @grid-gutter-width) { - position: relative; - float: left; - width: percentage((@columns / @grid-columns)); - min-height: 1px; - padding-left: (@gutter / 2); - padding-right: (@gutter / 2); -} -.make-xs-column-offset(@columns) { - @media (min-width: @screen-xs-min) { - margin-left: percentage((@columns / @grid-columns)); - } -} -.make-xs-column-push(@columns) { - @media (min-width: @screen-xs-min) { - left: percentage((@columns / @grid-columns)); - } -} -.make-xs-column-pull(@columns) { - @media (min-width: @screen-xs-min) { - right: percentage((@columns / @grid-columns)); - } -} - - -// Generate the small columns -.make-sm-column(@columns; @gutter: @grid-gutter-width) { - position: relative; - min-height: 1px; - padding-left: (@gutter / 2); - padding-right: (@gutter / 2); - - @media (min-width: @screen-sm-min) { - float: left; - width: percentage((@columns / @grid-columns)); - } -} -.make-sm-column-offset(@columns) { - @media (min-width: @screen-sm-min) { - margin-left: percentage((@columns / @grid-columns)); - } -} -.make-sm-column-push(@columns) { - @media (min-width: @screen-sm-min) { - left: percentage((@columns / @grid-columns)); - } -} -.make-sm-column-pull(@columns) { - @media (min-width: @screen-sm-min) { - right: percentage((@columns / @grid-columns)); - } -} - - -// Generate the medium columns -.make-md-column(@columns; @gutter: @grid-gutter-width) { - position: relative; - min-height: 1px; - padding-left: (@gutter / 2); - padding-right: (@gutter / 2); - - @media (min-width: @screen-md-min) { - float: left; - width: percentage((@columns / @grid-columns)); - } -} -.make-md-column-offset(@columns) { - @media (min-width: @screen-md-min) { - margin-left: percentage((@columns / @grid-columns)); - } -} -.make-md-column-push(@columns) { - @media (min-width: @screen-md-min) { - left: percentage((@columns / @grid-columns)); - } -} -.make-md-column-pull(@columns) { - @media (min-width: @screen-md-min) { - right: percentage((@columns / @grid-columns)); - } -} - - -// Generate the large columns -.make-lg-column(@columns; @gutter: @grid-gutter-width) { - position: relative; - min-height: 1px; - padding-left: (@gutter / 2); - padding-right: (@gutter / 2); - - @media (min-width: @screen-lg-min) { - float: left; - width: percentage((@columns / @grid-columns)); - } -} -.make-lg-column-offset(@columns) { - @media (min-width: @screen-lg-min) { - margin-left: percentage((@columns / @grid-columns)); - } -} -.make-lg-column-push(@columns) { - @media (min-width: @screen-lg-min) { - left: percentage((@columns / @grid-columns)); - } -} -.make-lg-column-pull(@columns) { - @media (min-width: @screen-lg-min) { - right: percentage((@columns / @grid-columns)); - } -} - - -// Framework grid generation -// -// Used only by Bootstrap to generate the correct number of grid classes given -// any value of `@grid-columns`. - -.make-grid-columns() { - // Common styles for all sizes of grid columns, widths 1-12 - .col(@index) when (@index = 1) { // initial - @item: ~".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}"; - .col((@index + 1), @item); - } - .col(@index, @list) when (@index =< @grid-columns) { // general; "=<" isn't a typo - @item: ~".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}"; - .col((@index + 1), ~"@{list}, @{item}"); - } - .col(@index, @list) when (@index > @grid-columns) { // terminal - @{list} { - position: relative; - // Prevent columns from collapsing when empty - min-height: 1px; - // Inner gutter via padding - padding-left: (@grid-gutter-width / 2); - padding-right: (@grid-gutter-width / 2); - } - } - .col(1); // kickstart it -} - -.float-grid-columns(@class) { - .col(@index) when (@index = 1) { // initial - @item: ~".col-@{class}-@{index}"; - .col((@index + 1), @item); - } - .col(@index, @list) when (@index =< @grid-columns) { // general - @item: ~".col-@{class}-@{index}"; - .col((@index + 1), ~"@{list}, @{item}"); - } - .col(@index, @list) when (@index > @grid-columns) { // terminal - @{list} { - float: left; - } - } - .col(1); // kickstart it -} - -.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) { - .col-@{class}-@{index} { - width: percentage((@index / @grid-columns)); - } -} -.calc-grid-column(@index, @class, @type) when (@type = push) { - .col-@{class}-push-@{index} { - left: percentage((@index / @grid-columns)); - } -} -.calc-grid-column(@index, @class, @type) when (@type = pull) { - .col-@{class}-pull-@{index} { - right: percentage((@index / @grid-columns)); - } -} -.calc-grid-column(@index, @class, @type) when (@type = offset) { - .col-@{class}-offset-@{index} { - margin-left: percentage((@index / @grid-columns)); - } -} - -// Basic looping in LESS -.loop-grid-columns(@index, @class, @type) when (@index >= 0) { - .calc-grid-column(@index, @class, @type); - // next iteration - .loop-grid-columns((@index - 1), @class, @type); -} - -// Create grid for specific class -.make-grid(@class) { - .float-grid-columns(@class); - .loop-grid-columns(@grid-columns, @class, width); - .loop-grid-columns(@grid-columns, @class, pull); - .loop-grid-columns(@grid-columns, @class, push); - .loop-grid-columns(@grid-columns, @class, offset); -} - -// Form validation states -// -// Used in forms.less to generate the form validation CSS for warnings, errors, -// and successes. - -.form-control-validation(@text-color: #555; @border-color: #ccc; @background-color: #f5f5f5) { - // Color the label and help text - .help-block, - .control-label, - .radio, - .checkbox, - .radio-inline, - .checkbox-inline { - color: @text-color; - } - // Set the border and box shadow on specific inputs to match - .form-control { - border-color: @border-color; - .box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work - &:focus { - border-color: darken(@border-color, 10%); - @shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten(@border-color, 20%); - .box-shadow(@shadow); - } - } - // Set validation states also for addons - .input-group-addon { - color: @text-color; - border-color: @border-color; - background-color: @background-color; - } - // Optional feedback icon - .form-control-feedback { - color: @text-color; - } -} - -// Form control focus state -// -// Generate a customized focus state and for any input with the specified color, -// which defaults to the `@input-focus-border` variable. -// -// We highly encourage you to not customize the default value, but instead use -// this to tweak colors on an as-needed basis. This aesthetic change is based on -// WebKit's default styles, but applicable to a wider range of browsers. Its -// usability and accessibility should be taken into account with any change. -// -// Example usage: change the default blue border and shadow to white for better -// contrast against a dark gray background. - -.form-control-focus(@color: @input-border-focus) { - @color-rgba: rgba(red(@color), green(@color), blue(@color), .6); - &:focus { - border-color: @color; - outline: 0; - .box-shadow(~"inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px @{color-rgba}"); - } -} - -// Form control sizing -// -// Relative text size, padding, and border-radii changes for form controls. For -// horizontal sizing, wrap controls in the predefined grid classes. `<select>` -// element gets special love because it's special, and that's a fact! - -.input-size(@input-height; @padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) { - height: @input-height; - padding: @padding-vertical @padding-horizontal; - font-size: @font-size; - line-height: @line-height; - border-radius: @border-radius; - - select& { - height: @input-height; - line-height: @input-height; - } - - textarea&, - select[multiple]& { - height: auto; - } -}
diff --git a/docs/static/less/bootstrap/modals.less b/docs/static/less/bootstrap/modals.less deleted file mode 100644 index 21cdee0..0000000 --- a/docs/static/less/bootstrap/modals.less +++ /dev/null
@@ -1,139 +0,0 @@ -// -// Modals -// -------------------------------------------------- - -// .modal-open - body class for killing the scroll -// .modal - container to scroll within -// .modal-dialog - positioning shell for the actual modal -// .modal-content - actual modal w/ bg and corners and shit - -// Kill the scroll on the body -.modal-open { - overflow: hidden; -} - -// Container that the modal scrolls within -.modal { - display: none; - overflow: auto; - overflow-y: scroll; - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: @zindex-modal; - -webkit-overflow-scrolling: touch; - - // Prevent Chrome on Windows from adding a focus outline. For details, see - // https://github.com/twbs/bootstrap/pull/10951. - outline: 0; - - // When fading in the modal, animate it to slide down - &.fade .modal-dialog { - .translate(0, -25%); - .transition-transform(~"0.3s ease-out"); - } - &.in .modal-dialog { .translate(0, 0)} -} - -// Shell div to position the modal with bottom padding -.modal-dialog { - position: relative; - width: auto; - margin: 10px; -} - -// Actual modal -.modal-content { - position: relative; - background-color: @modal-content-bg; - border: 1px solid @modal-content-fallback-border-color; //old browsers fallback (ie8 etc) - border: 1px solid @modal-content-border-color; - border-radius: @border-radius-large; - .box-shadow(0 3px 9px rgba(0,0,0,.5)); - background-clip: padding-box; - // Remove focus outline from opened modal - outline: none; -} - -// Modal background -.modal-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: @zindex-modal-background; - background-color: @modal-backdrop-bg; - // Fade for backdrop - &.fade { .opacity(0); } - &.in { .opacity(@modal-backdrop-opacity); } -} - -// Modal header -// Top section of the modal w/ title and dismiss -.modal-header { - padding: @modal-title-padding; - border-bottom: 1px solid @modal-header-border-color; - min-height: (@modal-title-padding + @modal-title-line-height); -} -// Close icon -.modal-header .close { - margin-top: -2px; -} - -// Title text within header -.modal-title { - margin: 0; - line-height: @modal-title-line-height; -} - -// Modal body -// Where all modal content resides (sibling of .modal-header and .modal-footer) -.modal-body { - position: relative; - padding: @modal-inner-padding; -} - -// Footer (for actions) -.modal-footer { - margin-top: 15px; - padding: (@modal-inner-padding - 1) @modal-inner-padding @modal-inner-padding; - text-align: right; // right align buttons - border-top: 1px solid @modal-footer-border-color; - &:extend(.clearfix all); // clear it in case folks use .pull-* classes on buttons - - // Properly space out buttons - .btn + .btn { - margin-left: 5px; - margin-bottom: 0; // account for input[type="submit"] which gets the bottom margin like all other inputs - } - // but override that for button groups - .btn-group .btn + .btn { - margin-left: -1px; - } - // and override it for block buttons as well - .btn-block + .btn-block { - margin-left: 0; - } -} - -// Scale up the modal -@media (min-width: @screen-sm-min) { - // Automatically set modal's width for larger viewports - .modal-dialog { - width: @modal-md; - margin: 30px auto; - } - .modal-content { - .box-shadow(0 5px 15px rgba(0,0,0,.5)); - } - - // Modal sizes - .modal-sm { width: @modal-sm; } -} - -@media (min-width: @screen-md-min) { - .modal-lg { width: @modal-lg; } -}
diff --git a/docs/static/less/bootstrap/navbar.less b/docs/static/less/bootstrap/navbar.less deleted file mode 100644 index 8c4c210..0000000 --- a/docs/static/less/bootstrap/navbar.less +++ /dev/null
@@ -1,616 +0,0 @@ -// -// Navbars -// -------------------------------------------------- - - -// Wrapper and base class -// -// Provide a static navbar from which we expand to create full-width, fixed, and -// other navbar variations. - -.navbar { - position: relative; - min-height: @navbar-height; // Ensure a navbar always shows (e.g., without a .navbar-brand in collapsed mode) - margin-bottom: @navbar-margin-bottom; - border: 1px solid transparent; - - // Prevent floats from breaking the navbar - &:extend(.clearfix all); - - @media (min-width: @grid-float-breakpoint) { - border-radius: @navbar-border-radius; - } -} - - -// Navbar heading -// -// Groups `.navbar-brand` and `.navbar-toggle` into a single component for easy -// styling of responsive aspects. - -.navbar-header { - &:extend(.clearfix all); - - @media (min-width: @grid-float-breakpoint) { - float: left; - } -} - - -// Navbar collapse (body) -// -// Group your navbar content into this for easy collapsing and expanding across -// various device sizes. By default, this content is collapsed when <768px, but -// will expand past that for a horizontal display. -// -// To start (on mobile devices) the navbar links, forms, and buttons are stacked -// vertically and include a `max-height` to overflow in case you have too much -// content for the user's viewport. - -.navbar-collapse { - max-height: @navbar-collapse-max-height; - overflow-x: visible; - padding-right: @navbar-padding-horizontal; - padding-left: @navbar-padding-horizontal; - border-top: 1px solid transparent; - box-shadow: inset 0 1px 0 rgba(255,255,255,.1); - &:extend(.clearfix all); - -webkit-overflow-scrolling: touch; - - &.in { - overflow-y: auto; - } - - @media (min-width: @grid-float-breakpoint) { - width: auto; - border-top: 0; - box-shadow: none; - - &.collapse { - display: block !important; - height: auto !important; - padding-bottom: 0; // Override default setting - overflow: visible !important; - } - - &.in { - overflow-y: visible; - } - - // Undo the collapse side padding for navbars with containers to ensure - // alignment of right-aligned contents. - .navbar-fixed-top &, - .navbar-static-top &, - .navbar-fixed-bottom & { - padding-left: 0; - padding-right: 0; - } - } -} - - -// Both navbar header and collapse -// -// When a container is present, change the behavior of the header and collapse. - -.container, -.container-fluid { - > .navbar-header, - > .navbar-collapse { - margin-right: -@navbar-padding-horizontal; - margin-left: -@navbar-padding-horizontal; - - @media (min-width: @grid-float-breakpoint) { - margin-right: 0; - margin-left: 0; - } - } -} - - -// -// Navbar alignment options -// -// Display the navbar across the entirety of the page or fixed it to the top or -// bottom of the page. - -// Static top (unfixed, but 100% wide) navbar -.navbar-static-top { - z-index: @zindex-navbar; - border-width: 0 0 1px; - - @media (min-width: @grid-float-breakpoint) { - border-radius: 0; - } -} - -// Fix the top/bottom navbars when screen real estate supports it -.navbar-fixed-top, -.navbar-fixed-bottom { - position: fixed; - right: 0; - left: 0; - z-index: @zindex-navbar-fixed; - - // Undo the rounded corners - @media (min-width: @grid-float-breakpoint) { - border-radius: 0; - } -} -.navbar-fixed-top { - top: 0; - border-width: 0 0 1px; -} -.navbar-fixed-bottom { - bottom: 0; - margin-bottom: 0; // override .navbar defaults - border-width: 1px 0 0; -} - - -// Brand/project name - -.navbar-brand { - float: left; - padding: @navbar-padding-vertical @navbar-padding-horizontal; - font-size: @font-size-large; - line-height: @line-height-computed; - height: @navbar-height; - - &:hover, - &:focus { - text-decoration: none; - } - - @media (min-width: @grid-float-breakpoint) { - .navbar > .container &, - .navbar > .container-fluid & { - margin-left: -@navbar-padding-horizontal; - } - } -} - - -// Navbar toggle -// -// Custom button for toggling the `.navbar-collapse`, powered by the collapse -// JavaScript plugin. - -.navbar-toggle { - position: relative; - float: right; - margin-right: @navbar-padding-horizontal; - padding: 9px 10px; - .navbar-vertical-align(34px); - background-color: transparent; - background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 - border: 1px solid transparent; - border-radius: @border-radius-base; - - // We remove the `outline` here, but later compensate by attaching `:hover` - // styles to `:focus`. - &:focus { - outline: none; - } - - // Bars - .icon-bar { - display: block; - width: 22px; - height: 2px; - border-radius: 1px; - } - .icon-bar + .icon-bar { - margin-top: 4px; - } - - @media (min-width: @grid-float-breakpoint) { - display: none; - } -} - - -// Navbar nav links -// -// Builds on top of the `.nav` components with its own modifier class to make -// the nav the full height of the horizontal nav (above 768px). - -.navbar-nav { - margin: (@navbar-padding-vertical / 2) -@navbar-padding-horizontal; - - > li > a { - padding-top: 10px; - padding-bottom: 10px; - line-height: @line-height-computed; - } - - @media (max-width: @grid-float-breakpoint-max) { - // Dropdowns get custom display when collapsed - .open .dropdown-menu { - position: static; - float: none; - width: auto; - margin-top: 0; - background-color: transparent; - border: 0; - box-shadow: none; - > li > a, - .dropdown-header { - padding: 5px 15px 5px 25px; - } - > li > a { - line-height: @line-height-computed; - &:hover, - &:focus { - background-image: none; - } - } - } - } - - // Uncollapse the nav - @media (min-width: @grid-float-breakpoint) { - float: left; - margin: 0; - - > li { - float: left; - > a { - padding-top: @navbar-padding-vertical; - padding-bottom: @navbar-padding-vertical; - } - } - - &.navbar-right:last-child { - margin-right: -@navbar-padding-horizontal; - } - } -} - - -// Component alignment -// -// Repurpose the pull utilities as their own navbar utilities to avoid specificity -// issues with parents and chaining. Only do this when the navbar is uncollapsed -// though so that navbar contents properly stack and align in mobile. - -@media (min-width: @grid-float-breakpoint) { - .navbar-left { .pull-left(); } - .navbar-right { .pull-right(); } -} - - -// Navbar form -// -// Extension of the `.form-inline` with some extra flavor for optimum display in -// our navbars. - -.navbar-form { - margin-left: -@navbar-padding-horizontal; - margin-right: -@navbar-padding-horizontal; - padding: 10px @navbar-padding-horizontal; - border-top: 1px solid transparent; - border-bottom: 1px solid transparent; - @shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1); - .box-shadow(@shadow); - - // Mixin behavior for optimum display - .form-inline(); - - .form-group { - @media (max-width: @grid-float-breakpoint-max) { - margin-bottom: 5px; - } - } - - // Vertically center in expanded, horizontal navbar - .navbar-vertical-align(@input-height-base); - - // Undo 100% width for pull classes - @media (min-width: @grid-float-breakpoint) { - width: auto; - border: 0; - margin-left: 0; - margin-right: 0; - padding-top: 0; - padding-bottom: 0; - .box-shadow(none); - - // Outdent the form if last child to line up with content down the page - &.navbar-right:last-child { - margin-right: -@navbar-padding-horizontal; - } - } -} - - -// Dropdown menus - -// Menu position and menu carets -.navbar-nav > li > .dropdown-menu { - margin-top: 0; - .border-top-radius(0); -} -// Menu position and menu caret support for dropups via extra dropup class -.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { - .border-bottom-radius(0); -} - - -// Buttons in navbars -// -// Vertically center a button within a navbar (when *not* in a form). - -.navbar-btn { - .navbar-vertical-align(@input-height-base); - - &.btn-sm { - .navbar-vertical-align(@input-height-small); - } - &.btn-xs { - .navbar-vertical-align(22); - } -} - - -// Text in navbars -// -// Add a class to make any element properly align itself vertically within the navbars. - -.navbar-text { - .navbar-vertical-align(@line-height-computed); - - @media (min-width: @grid-float-breakpoint) { - float: left; - margin-left: @navbar-padding-horizontal; - margin-right: @navbar-padding-horizontal; - - // Outdent the form if last child to line up with content down the page - &.navbar-right:last-child { - margin-right: 0; - } - } -} - -// Alternate navbars -// -------------------------------------------------- - -// Default navbar -.navbar-default { - background-color: @navbar-default-bg; - border-color: @navbar-default-border; - - .navbar-brand { - color: @navbar-default-brand-color; - &:hover, - &:focus { - color: @navbar-default-brand-hover-color; - background-color: @navbar-default-brand-hover-bg; - } - } - - .navbar-text { - color: @navbar-default-color; - } - - .navbar-nav { - > li > a { - color: @navbar-default-link-color; - - &:hover, - &:focus { - color: @navbar-default-link-hover-color; - background-color: @navbar-default-link-hover-bg; - } - } - > .active > a { - &, - &:hover, - &:focus { - color: @navbar-default-link-active-color; - background-color: @navbar-default-link-active-bg; - } - } - > .disabled > a { - &, - &:hover, - &:focus { - color: @navbar-default-link-disabled-color; - background-color: @navbar-default-link-disabled-bg; - } - } - } - - .navbar-toggle { - border-color: @navbar-default-toggle-border-color; - &:hover, - &:focus { - background-color: @navbar-default-toggle-hover-bg; - } - .icon-bar { - background-color: @navbar-default-toggle-icon-bar-bg; - } - } - - .navbar-collapse, - .navbar-form { - border-color: @navbar-default-border; - } - - // Dropdown menu items - .navbar-nav { - // Remove background color from open dropdown - > .open > a { - &, - &:hover, - &:focus { - background-color: @navbar-default-link-active-bg; - color: @navbar-default-link-active-color; - } - } - - @media (max-width: @grid-float-breakpoint-max) { - // Dropdowns get custom display when collapsed - .open .dropdown-menu { - > li > a { - color: @navbar-default-link-color; - &:hover, - &:focus { - color: @navbar-default-link-hover-color; - background-color: @navbar-default-link-hover-bg; - } - } - > .active > a { - &, - &:hover, - &:focus { - color: @navbar-default-link-active-color; - background-color: @navbar-default-link-active-bg; - } - } - > .disabled > a { - &, - &:hover, - &:focus { - color: @navbar-default-link-disabled-color; - background-color: @navbar-default-link-disabled-bg; - } - } - } - } - } - - - // Links in navbars - // - // Add a class to ensure links outside the navbar nav are colored correctly. - - .navbar-link { - color: @navbar-default-link-color; - &:hover { - color: @navbar-default-link-hover-color; - } - } - -} - -// Inverse navbar - -.navbar-inverse { - background-color: @navbar-inverse-bg; - border-color: @navbar-inverse-border; - - .navbar-brand { - color: @navbar-inverse-brand-color; - &:hover, - &:focus { - color: @navbar-inverse-brand-hover-color; - background-color: @navbar-inverse-brand-hover-bg; - } - } - - .navbar-text { - color: @navbar-inverse-color; - } - - .navbar-nav { - > li > a { - color: @navbar-inverse-link-color; - - &:hover, - &:focus { - color: @navbar-inverse-link-hover-color; - background-color: @navbar-inverse-link-hover-bg; - } - } - > .active > a { - &, - &:hover, - &:focus { - color: @navbar-inverse-link-active-color; - background-color: @navbar-inverse-link-active-bg; - } - } - > .disabled > a { - &, - &:hover, - &:focus { - color: @navbar-inverse-link-disabled-color; - background-color: @navbar-inverse-link-disabled-bg; - } - } - } - - // Darken the responsive nav toggle - .navbar-toggle { - border-color: @navbar-inverse-toggle-border-color; - &:hover, - &:focus { - background-color: @navbar-inverse-toggle-hover-bg; - } - .icon-bar { - background-color: @navbar-inverse-toggle-icon-bar-bg; - } - } - - .navbar-collapse, - .navbar-form { - border-color: darken(@navbar-inverse-bg, 7%); - } - - // Dropdowns - .navbar-nav { - > .open > a { - &, - &:hover, - &:focus { - background-color: @navbar-inverse-link-active-bg; - color: @navbar-inverse-link-active-color; - } - } - - @media (max-width: @grid-float-breakpoint-max) { - // Dropdowns get custom display - .open .dropdown-menu { - > .dropdown-header { - border-color: @navbar-inverse-border; - } - .divider { - background-color: @navbar-inverse-border; - } - > li > a { - color: @navbar-inverse-link-color; - &:hover, - &:focus { - color: @navbar-inverse-link-hover-color; - background-color: @navbar-inverse-link-hover-bg; - } - } - > .active > a { - &, - &:hover, - &:focus { - color: @navbar-inverse-link-active-color; - background-color: @navbar-inverse-link-active-bg; - } - } - > .disabled > a { - &, - &:hover, - &:focus { - color: @navbar-inverse-link-disabled-color; - background-color: @navbar-inverse-link-disabled-bg; - } - } - } - } - } - - .navbar-link { - color: @navbar-inverse-link-color; - &:hover { - color: @navbar-inverse-link-hover-color; - } - } - -}
diff --git a/docs/static/less/bootstrap/navs.less b/docs/static/less/bootstrap/navs.less deleted file mode 100644 index 9e729b3..0000000 --- a/docs/static/less/bootstrap/navs.less +++ /dev/null
@@ -1,242 +0,0 @@ -// -// Navs -// -------------------------------------------------- - - -// Base class -// -------------------------------------------------- - -.nav { - margin-bottom: 0; - padding-left: 0; // Override default ul/ol - list-style: none; - &:extend(.clearfix all); - - > li { - position: relative; - display: block; - - > a { - position: relative; - display: block; - padding: @nav-link-padding; - &:hover, - &:focus { - text-decoration: none; - background-color: @nav-link-hover-bg; - } - } - - // Disabled state sets text to gray and nukes hover/tab effects - &.disabled > a { - color: @nav-disabled-link-color; - - &:hover, - &:focus { - color: @nav-disabled-link-hover-color; - text-decoration: none; - background-color: transparent; - cursor: not-allowed; - } - } - } - - // Open dropdowns - .open > a { - &, - &:hover, - &:focus { - background-color: @nav-link-hover-bg; - border-color: @link-color; - } - } - - // Nav dividers (deprecated with v3.0.1) - // - // This should have been removed in v3 with the dropping of `.nav-list`, but - // we missed it. We don't currently support this anywhere, but in the interest - // of maintaining backward compatibility in case you use it, it's deprecated. - .nav-divider { - .nav-divider(); - } - - // Prevent IE8 from misplacing imgs - // - // See https://github.com/h5bp/html5-boilerplate/issues/984#issuecomment-3985989 - > li > a > img { - max-width: none; - } -} - - -// Tabs -// ------------------------- - -// Give the tabs something to sit on -.nav-tabs { - border-bottom: 1px solid @nav-tabs-border-color; - > li { - float: left; - // Make the list-items overlay the bottom border - margin-bottom: -1px; - - // Actual tabs (as links) - > a { - margin-right: 2px; - line-height: @line-height-base; - border: 1px solid transparent; - border-radius: @border-radius-base @border-radius-base 0 0; - &:hover { - border-color: @nav-tabs-link-hover-border-color @nav-tabs-link-hover-border-color @nav-tabs-border-color; - } - } - - // Active state, and its :hover to override normal :hover - &.active > a { - &, - &:hover, - &:focus { - color: @nav-tabs-active-link-hover-color; - background-color: @nav-tabs-active-link-hover-bg; - border: 1px solid @nav-tabs-active-link-hover-border-color; - border-bottom-color: transparent; - cursor: default; - } - } - } - // pulling this in mainly for less shorthand - &.nav-justified { - .nav-justified(); - .nav-tabs-justified(); - } -} - - -// Pills -// ------------------------- -.nav-pills { - > li { - float: left; - - // Links rendered as pills - > a { - border-radius: @nav-pills-border-radius; - } - + li { - margin-left: 2px; - } - - // Active state - &.active > a { - &, - &:hover, - &:focus { - color: @nav-pills-active-link-hover-color; - background-color: @nav-pills-active-link-hover-bg; - } - } - } -} - - -// Stacked pills -.nav-stacked { - > li { - float: none; - + li { - margin-top: 2px; - margin-left: 0; // no need for this gap between nav items - } - } -} - - -// Nav variations -// -------------------------------------------------- - -// Justified nav links -// ------------------------- - -.nav-justified { - width: 100%; - - > li { - float: none; - > a { - text-align: center; - margin-bottom: 5px; - } - } - - > .dropdown .dropdown-menu { - top: auto; - left: auto; - } - - @media (min-width: @screen-sm-min) { - > li { - display: table-cell; - width: 1%; - > a { - margin-bottom: 0; - } - } - } -} - -// Move borders to anchors instead of bottom of list -// -// Mixin for adding on top the shared `.nav-justified` styles for our tabs -.nav-tabs-justified { - border-bottom: 0; - - > li > a { - // Override margin from .nav-tabs - margin-right: 0; - border-radius: @border-radius-base; - } - - > .active > a, - > .active > a:hover, - > .active > a:focus { - border: 1px solid @nav-tabs-justified-link-border-color; - } - - @media (min-width: @screen-sm-min) { - > li > a { - border-bottom: 1px solid @nav-tabs-justified-link-border-color; - border-radius: @border-radius-base @border-radius-base 0 0; - } - > .active > a, - > .active > a:hover, - > .active > a:focus { - border-bottom-color: @nav-tabs-justified-active-link-border-color; - } - } -} - - -// Tabbable tabs -// ------------------------- - -// Hide tabbable panes to start, show them when `.active` -.tab-content { - > .tab-pane { - display: none; - } - > .active { - display: block; - } -} - - -// Dropdowns -// ------------------------- - -// Specific dropdowns -.nav-tabs .dropdown-menu { - // make dropdown border overlap tab border - margin-top: -1px; - // Remove the top rounded corners here since there is a hard edge above the menu - .border-top-radius(0); -}
diff --git a/docs/static/less/bootstrap/normalize.less b/docs/static/less/bootstrap/normalize.less deleted file mode 100644 index 024e257..0000000 --- a/docs/static/less/bootstrap/normalize.less +++ /dev/null
@@ -1,423 +0,0 @@ -/*! normalize.css v3.0.0 | MIT License | git.io/normalize */ - -// -// 1. Set default font family to sans-serif. -// 2. Prevent iOS text size adjust after orientation change, without disabling -// user zoom. -// - -html { - font-family: sans-serif; // 1 - -ms-text-size-adjust: 100%; // 2 - -webkit-text-size-adjust: 100%; // 2 -} - -// -// Remove default margin. -// - -body { - margin: 0; -} - -// HTML5 display definitions -// ========================================================================== - -// -// Correct `block` display not defined in IE 8/9. -// - -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -main, -nav, -section, -summary { - display: block; -} - -// -// 1. Correct `inline-block` display not defined in IE 8/9. -// 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. -// - -audio, -canvas, -progress, -video { - display: inline-block; // 1 - vertical-align: baseline; // 2 -} - -// -// Prevent modern browsers from displaying `audio` without controls. -// Remove excess height in iOS 5 devices. -// - -audio:not([controls]) { - display: none; - height: 0; -} - -// -// Address `[hidden]` styling not present in IE 8/9. -// Hide the `template` element in IE, Safari, and Firefox < 22. -// - -[hidden], -template { - display: none; -} - -// Links -// ========================================================================== - -// -// Remove the gray background color from active links in IE 10. -// - -a { - background: transparent; -} - -// -// Improve readability when focused and also mouse hovered in all browsers. -// - -a:active, -a:hover { - outline: 0; -} - -// Text-level semantics -// ========================================================================== - -// -// Address styling not present in IE 8/9, Safari 5, and Chrome. -// - -abbr[title] { - border-bottom: 1px dotted; -} - -// -// Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. -// - -b, -strong { - font-weight: bold; -} - -// -// Address styling not present in Safari 5 and Chrome. -// - -dfn { - font-style: italic; -} - -// -// Address variable `h1` font-size and margin within `section` and `article` -// contexts in Firefox 4+, Safari 5, and Chrome. -// - -h1 { - font-size: 2em; - margin: 0.67em 0; -} - -// -// Address styling not present in IE 8/9. -// - -mark { - background: #ff0; - color: #000; -} - -// -// Address inconsistent and variable font size in all browsers. -// - -small { - font-size: 80%; -} - -// -// Prevent `sub` and `sup` affecting `line-height` in all browsers. -// - -sub, -sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; -} - -sup { - top: -0.5em; -} - -sub { - bottom: -0.25em; -} - -// Embedded content -// ========================================================================== - -// -// Remove border when inside `a` element in IE 8/9. -// - -img { - border: 0; -} - -// -// Correct overflow displayed oddly in IE 9. -// - -svg:not(:root) { - overflow: hidden; -} - -// Grouping content -// ========================================================================== - -// -// Address margin not present in IE 8/9 and Safari 5. -// - -figure { - margin: 1em 40px; -} - -// -// Address differences between Firefox and other browsers. -// - -hr { - -moz-box-sizing: content-box; - box-sizing: content-box; - height: 0; -} - -// -// Contain overflow in all browsers. -// - -pre { - overflow: auto; -} - -// -// Address odd `em`-unit font size rendering in all browsers. -// - -code, -kbd, -pre, -samp { - font-family: monospace, monospace; - font-size: 1em; -} - -// Forms -// ========================================================================== - -// -// Known limitation: by default, Chrome and Safari on OS X allow very limited -// styling of `select`, unless a `border` property is set. -// - -// -// 1. Correct color not being inherited. -// Known issue: affects color of disabled elements. -// 2. Correct font properties not being inherited. -// 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. -// - -button, -input, -optgroup, -select, -textarea { - color: inherit; // 1 - font: inherit; // 2 - margin: 0; // 3 -} - -// -// Address `overflow` set to `hidden` in IE 8/9/10. -// - -button { - overflow: visible; -} - -// -// Address inconsistent `text-transform` inheritance for `button` and `select`. -// All other form control elements do not inherit `text-transform` values. -// Correct `button` style inheritance in Firefox, IE 8+, and Opera -// Correct `select` style inheritance in Firefox. -// - -button, -select { - text-transform: none; -} - -// -// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` -// and `video` controls. -// 2. Correct inability to style clickable `input` types in iOS. -// 3. Improve usability and consistency of cursor style between image-type -// `input` and others. -// - -button, -html input[type="button"], // 1 -input[type="reset"], -input[type="submit"] { - -webkit-appearance: button; // 2 - cursor: pointer; // 3 -} - -// -// Re-set default cursor for disabled elements. -// - -button[disabled], -html input[disabled] { - cursor: default; -} - -// -// Remove inner padding and border in Firefox 4+. -// - -button::-moz-focus-inner, -input::-moz-focus-inner { - border: 0; - padding: 0; -} - -// -// Address Firefox 4+ setting `line-height` on `input` using `!important` in -// the UA stylesheet. -// - -input { - line-height: normal; -} - -// -// It's recommended that you don't attempt to style these elements. -// Firefox's implementation doesn't respect box-sizing, padding, or width. -// -// 1. Address box sizing set to `content-box` in IE 8/9/10. -// 2. Remove excess padding in IE 8/9/10. -// - -input[type="checkbox"], -input[type="radio"] { - box-sizing: border-box; // 1 - padding: 0; // 2 -} - -// -// Fix the cursor style for Chrome's increment/decrement buttons. For certain -// `font-size` values of the `input`, it causes the cursor style of the -// decrement button to change from `default` to `text`. -// - -input[type="number"]::-webkit-inner-spin-button, -input[type="number"]::-webkit-outer-spin-button { - height: auto; -} - -// -// 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. -// 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome -// (include `-moz` to future-proof). -// - -input[type="search"] { - -webkit-appearance: textfield; // 1 - -moz-box-sizing: content-box; - -webkit-box-sizing: content-box; // 2 - box-sizing: content-box; -} - -// -// Remove inner padding and search cancel button in Safari and Chrome on OS X. -// Safari (but not Chrome) clips the cancel button when the search input has -// padding (and `textfield` appearance). -// - -input[type="search"]::-webkit-search-cancel-button, -input[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; -} - -// -// Define consistent border, margin, and padding. -// - -fieldset { - border: 1px solid #c0c0c0; - margin: 0 2px; - padding: 0.35em 0.625em 0.75em; -} - -// -// 1. Correct `color` not being inherited in IE 8/9. -// 2. Remove padding so people aren't caught out if they zero out fieldsets. -// - -legend { - border: 0; // 1 - padding: 0; // 2 -} - -// -// Remove default vertical scrollbar in IE 8/9. -// - -textarea { - overflow: auto; -} - -// -// Don't inherit the `font-weight` (applied by a rule above). -// NOTE: the default cannot safely be changed in Chrome and Safari on OS X. -// - -optgroup { - font-weight: bold; -} - -// Tables -// ========================================================================== - -// -// Remove most spacing between table cells. -// - -table { - border-collapse: collapse; - border-spacing: 0; -} - -td, -th { - padding: 0; -} \ No newline at end of file
diff --git a/docs/static/less/bootstrap/pager.less b/docs/static/less/bootstrap/pager.less deleted file mode 100644 index 59103f4..0000000 --- a/docs/static/less/bootstrap/pager.less +++ /dev/null
@@ -1,55 +0,0 @@ -// -// Pager pagination -// -------------------------------------------------- - - -.pager { - padding-left: 0; - margin: @line-height-computed 0; - list-style: none; - text-align: center; - &:extend(.clearfix all); - li { - display: inline; - > a, - > span { - display: inline-block; - padding: 5px 14px; - background-color: @pager-bg; - border: 1px solid @pager-border; - border-radius: @pager-border-radius; - } - - > a:hover, - > a:focus { - text-decoration: none; - background-color: @pager-hover-bg; - } - } - - .next { - > a, - > span { - float: right; - } - } - - .previous { - > a, - > span { - float: left; - } - } - - .disabled { - > a, - > a:hover, - > a:focus, - > span { - color: @pager-disabled-color; - background-color: @pager-bg; - cursor: not-allowed; - } - } - -}
diff --git a/docs/static/less/bootstrap/pagination.less b/docs/static/less/bootstrap/pagination.less deleted file mode 100644 index b2856ae..0000000 --- a/docs/static/less/bootstrap/pagination.less +++ /dev/null
@@ -1,88 +0,0 @@ -// -// Pagination (multiple pages) -// -------------------------------------------------- -.pagination { - display: inline-block; - padding-left: 0; - margin: @line-height-computed 0; - border-radius: @border-radius-base; - - > li { - display: inline; // Remove list-style and block-level defaults - > a, - > span { - position: relative; - float: left; // Collapse white-space - padding: @padding-base-vertical @padding-base-horizontal; - line-height: @line-height-base; - text-decoration: none; - color: @pagination-color; - background-color: @pagination-bg; - border: 1px solid @pagination-border; - margin-left: -1px; - } - &:first-child { - > a, - > span { - margin-left: 0; - .border-left-radius(@border-radius-base); - } - } - &:last-child { - > a, - > span { - .border-right-radius(@border-radius-base); - } - } - } - - > li > a, - > li > span { - &:hover, - &:focus { - color: @pagination-hover-color; - background-color: @pagination-hover-bg; - border-color: @pagination-hover-border; - } - } - - > .active > a, - > .active > span { - &, - &:hover, - &:focus { - z-index: 2; - color: @pagination-active-color; - background-color: @pagination-active-bg; - border-color: @pagination-active-border; - cursor: default; - } - } - - > .disabled { - > span, - > span:hover, - > span:focus, - > a, - > a:hover, - > a:focus { - color: @pagination-disabled-color; - background-color: @pagination-disabled-bg; - border-color: @pagination-disabled-border; - cursor: not-allowed; - } - } -} - -// Sizing -// -------------------------------------------------- - -// Large -.pagination-lg { - .pagination-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @border-radius-large); -} - -// Small -.pagination-sm { - .pagination-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @border-radius-small); -}
diff --git a/docs/static/less/bootstrap/panels.less b/docs/static/less/bootstrap/panels.less deleted file mode 100644 index 20dd149..0000000 --- a/docs/static/less/bootstrap/panels.less +++ /dev/null
@@ -1,241 +0,0 @@ -// -// Panels -// -------------------------------------------------- - - -// Base class -.panel { - margin-bottom: @line-height-computed; - background-color: @panel-bg; - border: 1px solid transparent; - border-radius: @panel-border-radius; - .box-shadow(0 1px 1px rgba(0,0,0,.05)); -} - -// Panel contents -.panel-body { - padding: @panel-body-padding; - &:extend(.clearfix all); -} - -// Optional heading -.panel-heading { - padding: 10px 15px; - border-bottom: 1px solid transparent; - .border-top-radius((@panel-border-radius - 1)); - - > .dropdown .dropdown-toggle { - color: inherit; - } -} - -// Within heading, strip any `h*` tag of its default margins for spacing. -.panel-title { - margin-top: 0; - margin-bottom: 0; - font-size: ceil((@font-size-base * 1.125)); - color: inherit; - - > a { - color: inherit; - } -} - -// Optional footer (stays gray in every modifier class) -.panel-footer { - padding: 10px 15px; - background-color: @panel-footer-bg; - border-top: 1px solid @panel-inner-border; - .border-bottom-radius((@panel-border-radius - 1)); -} - - -// List groups in panels -// -// By default, space out list group content from panel headings to account for -// any kind of custom content between the two. - -.panel { - > .list-group { - margin-bottom: 0; - - .list-group-item { - border-width: 1px 0; - border-radius: 0; - } - - // Add border top radius for first one - &:first-child { - .list-group-item:first-child { - border-top: 0; - .border-top-radius((@panel-border-radius - 1)); - } - } - // Add border bottom radius for last one - &:last-child { - .list-group-item:last-child { - border-bottom: 0; - .border-bottom-radius((@panel-border-radius - 1)); - } - } - } -} -// Collapse space between when there's no additional content. -.panel-heading + .list-group { - .list-group-item:first-child { - border-top-width: 0; - } -} - - -// Tables in panels -// -// Place a non-bordered `.table` within a panel (not within a `.panel-body`) and -// watch it go full width. - -.panel { - > .table, - > .table-responsive > .table { - margin-bottom: 0; - } - // Add border top radius for first one - > .table:first-child, - > .table-responsive:first-child > .table:first-child { - .border-top-radius((@panel-border-radius - 1)); - - > thead:first-child, - > tbody:first-child { - > tr:first-child { - td:first-child, - th:first-child { - border-top-left-radius: (@panel-border-radius - 1); - } - td:last-child, - th:last-child { - border-top-right-radius: (@panel-border-radius - 1); - } - } - } - } - // Add border bottom radius for last one - > .table:last-child, - > .table-responsive:last-child > .table:last-child { - .border-bottom-radius((@panel-border-radius - 1)); - - > tbody:last-child, - > tfoot:last-child { - > tr:last-child { - td:first-child, - th:first-child { - border-bottom-left-radius: (@panel-border-radius - 1); - } - td:last-child, - th:last-child { - border-bottom-right-radius: (@panel-border-radius - 1); - } - } - } - } - > .panel-body + .table, - > .panel-body + .table-responsive { - border-top: 1px solid @table-border-color; - } - > .table > tbody:first-child > tr:first-child th, - > .table > tbody:first-child > tr:first-child td { - border-top: 0; - } - > .table-bordered, - > .table-responsive > .table-bordered { - border: 0; - > thead, - > tbody, - > tfoot { - > tr { - > th:first-child, - > td:first-child { - border-left: 0; - } - > th:last-child, - > td:last-child { - border-right: 0; - } - } - } - > thead, - > tbody { - > tr:first-child { - > td, - > th { - border-bottom: 0; - } - } - } - > tbody, - > tfoot { - > tr:last-child { - > td, - > th { - border-bottom: 0; - } - } - } - } - > .table-responsive { - border: 0; - margin-bottom: 0; - } -} - - -// Collapsable panels (aka, accordion) -// -// Wrap a series of panels in `.panel-group` to turn them into an accordion with -// the help of our collapse JavaScript plugin. - -.panel-group { - margin-bottom: @line-height-computed; - - // Tighten up margin so it's only between panels - .panel { - margin-bottom: 0; - border-radius: @panel-border-radius; - overflow: hidden; // crop contents when collapsed - + .panel { - margin-top: 5px; - } - } - - .panel-heading { - border-bottom: 0; - + .panel-collapse .panel-body { - border-top: 1px solid @panel-inner-border; - } - } - .panel-footer { - border-top: 0; - + .panel-collapse .panel-body { - border-bottom: 1px solid @panel-inner-border; - } - } -} - - -// Contextual variations -.panel-default { - .panel-variant(@panel-default-border; @panel-default-text; @panel-default-heading-bg; @panel-default-border); -} -.panel-primary { - .panel-variant(@panel-primary-border; @panel-primary-text; @panel-primary-heading-bg; @panel-primary-border); -} -.panel-success { - .panel-variant(@panel-success-border; @panel-success-text; @panel-success-heading-bg; @panel-success-border); -} -.panel-info { - .panel-variant(@panel-info-border; @panel-info-text; @panel-info-heading-bg; @panel-info-border); -} -.panel-warning { - .panel-variant(@panel-warning-border; @panel-warning-text; @panel-warning-heading-bg; @panel-warning-border); -} -.panel-danger { - .panel-variant(@panel-danger-border; @panel-danger-text; @panel-danger-heading-bg; @panel-danger-border); -}
diff --git a/docs/static/less/bootstrap/popovers.less b/docs/static/less/bootstrap/popovers.less deleted file mode 100644 index 696d74c..0000000 --- a/docs/static/less/bootstrap/popovers.less +++ /dev/null
@@ -1,133 +0,0 @@ -// -// Popovers -// -------------------------------------------------- - - -.popover { - position: absolute; - top: 0; - left: 0; - z-index: @zindex-popover; - display: none; - max-width: @popover-max-width; - padding: 1px; - text-align: left; // Reset given new insertion method - background-color: @popover-bg; - background-clip: padding-box; - border: 1px solid @popover-fallback-border-color; - border: 1px solid @popover-border-color; - border-radius: @border-radius-large; - .box-shadow(0 5px 10px rgba(0,0,0,.2)); - - // Overrides for proper insertion - white-space: normal; - - // Offset the popover to account for the popover arrow - &.top { margin-top: -@popover-arrow-width; } - &.right { margin-left: @popover-arrow-width; } - &.bottom { margin-top: @popover-arrow-width; } - &.left { margin-left: -@popover-arrow-width; } -} - -.popover-title { - margin: 0; // reset heading margin - padding: 8px 14px; - font-size: @font-size-base; - font-weight: normal; - line-height: 18px; - background-color: @popover-title-bg; - border-bottom: 1px solid darken(@popover-title-bg, 5%); - border-radius: 5px 5px 0 0; -} - -.popover-content { - padding: 9px 14px; -} - -// Arrows -// -// .arrow is outer, .arrow:after is inner - -.popover > .arrow { - &, - &:after { - position: absolute; - display: block; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; - } -} -.popover > .arrow { - border-width: @popover-arrow-outer-width; -} -.popover > .arrow:after { - border-width: @popover-arrow-width; - content: ""; -} - -.popover { - &.top > .arrow { - left: 50%; - margin-left: -@popover-arrow-outer-width; - border-bottom-width: 0; - border-top-color: @popover-arrow-outer-fallback-color; // IE8 fallback - border-top-color: @popover-arrow-outer-color; - bottom: -@popover-arrow-outer-width; - &:after { - content: " "; - bottom: 1px; - margin-left: -@popover-arrow-width; - border-bottom-width: 0; - border-top-color: @popover-arrow-color; - } - } - &.right > .arrow { - top: 50%; - left: -@popover-arrow-outer-width; - margin-top: -@popover-arrow-outer-width; - border-left-width: 0; - border-right-color: @popover-arrow-outer-fallback-color; // IE8 fallback - border-right-color: @popover-arrow-outer-color; - &:after { - content: " "; - left: 1px; - bottom: -@popover-arrow-width; - border-left-width: 0; - border-right-color: @popover-arrow-color; - } - } - &.bottom > .arrow { - left: 50%; - margin-left: -@popover-arrow-outer-width; - border-top-width: 0; - border-bottom-color: @popover-arrow-outer-fallback-color; // IE8 fallback - border-bottom-color: @popover-arrow-outer-color; - top: -@popover-arrow-outer-width; - &:after { - content: " "; - top: 1px; - margin-left: -@popover-arrow-width; - border-top-width: 0; - border-bottom-color: @popover-arrow-color; - } - } - - &.left > .arrow { - top: 50%; - right: -@popover-arrow-outer-width; - margin-top: -@popover-arrow-outer-width; - border-right-width: 0; - border-left-color: @popover-arrow-outer-fallback-color; // IE8 fallback - border-left-color: @popover-arrow-outer-color; - &:after { - content: " "; - right: 1px; - border-right-width: 0; - border-left-color: @popover-arrow-color; - bottom: -@popover-arrow-width; - } - } - -}
diff --git a/docs/static/less/bootstrap/print.less b/docs/static/less/bootstrap/print.less deleted file mode 100644 index 3655d03..0000000 --- a/docs/static/less/bootstrap/print.less +++ /dev/null
@@ -1,101 +0,0 @@ -// -// Basic print styles -// -------------------------------------------------- -// Source: https://github.com/h5bp/html5-boilerplate/blob/master/css/main.css - -@media print { - - * { - text-shadow: none !important; - color: #000 !important; // Black prints faster: h5bp.com/s - background: transparent !important; - box-shadow: none !important; - } - - a, - a:visited { - text-decoration: underline; - } - - a[href]:after { - content: " (" attr(href) ")"; - } - - abbr[title]:after { - content: " (" attr(title) ")"; - } - - // Don't show links for images, or javascript/internal links - a[href^="javascript:"]:after, - a[href^="#"]:after { - content: ""; - } - - pre, - blockquote { - border: 1px solid #999; - page-break-inside: avoid; - } - - thead { - display: table-header-group; // h5bp.com/t - } - - tr, - img { - page-break-inside: avoid; - } - - img { - max-width: 100% !important; - } - - p, - h2, - h3 { - orphans: 3; - widows: 3; - } - - h2, - h3 { - page-break-after: avoid; - } - - // Chrome (OSX) fix for https://github.com/twbs/bootstrap/issues/11245 - // Once fixed, we can just straight up remove this. - select { - background: #fff !important; - } - - // Bootstrap components - .navbar { - display: none; - } - .table { - td, - th { - background-color: #fff !important; - } - } - .btn, - .dropup > .btn { - > .caret { - border-top-color: #000 !important; - } - } - .label { - border: 1px solid #000; - } - - .table { - border-collapse: collapse !important; - } - .table-bordered { - th, - td { - border: 1px solid #ddd !important; - } - } - -}
diff --git a/docs/static/less/bootstrap/progress-bars.less b/docs/static/less/bootstrap/progress-bars.less deleted file mode 100644 index 76c87be..0000000 --- a/docs/static/less/bootstrap/progress-bars.less +++ /dev/null
@@ -1,80 +0,0 @@ -// -// Progress bars -// -------------------------------------------------- - - -// Bar animations -// ------------------------- - -// WebKit -@-webkit-keyframes progress-bar-stripes { - from { background-position: 40px 0; } - to { background-position: 0 0; } -} - -// Spec and IE10+ -@keyframes progress-bar-stripes { - from { background-position: 40px 0; } - to { background-position: 0 0; } -} - - - -// Bar itself -// ------------------------- - -// Outer container -.progress { - overflow: hidden; - height: @line-height-computed; - margin-bottom: @line-height-computed; - background-color: @progress-bg; - border-radius: @border-radius-base; - .box-shadow(inset 0 1px 2px rgba(0,0,0,.1)); -} - -// Bar of progress -.progress-bar { - float: left; - width: 0%; - height: 100%; - font-size: @font-size-small; - line-height: @line-height-computed; - color: @progress-bar-color; - text-align: center; - background-color: @progress-bar-bg; - .box-shadow(inset 0 -1px 0 rgba(0,0,0,.15)); - .transition(width .6s ease); -} - -// Striped bars -.progress-striped .progress-bar { - #gradient > .striped(); - background-size: 40px 40px; -} - -// Call animation for the active one -.progress.active .progress-bar { - .animation(progress-bar-stripes 2s linear infinite); -} - - - -// Variations -// ------------------------- - -.progress-bar-success { - .progress-bar-variant(@progress-bar-success-bg); -} - -.progress-bar-info { - .progress-bar-variant(@progress-bar-info-bg); -} - -.progress-bar-warning { - .progress-bar-variant(@progress-bar-warning-bg); -} - -.progress-bar-danger { - .progress-bar-variant(@progress-bar-danger-bg); -}
diff --git a/docs/static/less/bootstrap/responsive-utilities.less b/docs/static/less/bootstrap/responsive-utilities.less deleted file mode 100644 index 027a264..0000000 --- a/docs/static/less/bootstrap/responsive-utilities.less +++ /dev/null
@@ -1,92 +0,0 @@ -// -// Responsive: Utility classes -// -------------------------------------------------- - - -// IE10 in Windows (Phone) 8 -// -// Support for responsive views via media queries is kind of borked in IE10, for -// Surface/desktop in split view and for Windows Phone 8. This particular fix -// must be accompanied by a snippet of JavaScript to sniff the user agent and -// apply some conditional CSS to *only* the Surface/desktop Windows 8. Look at -// our Getting Started page for more information on this bug. -// -// For more information, see the following: -// -// Issue: https://github.com/twbs/bootstrap/issues/10497 -// Docs: http://getbootstrap.com/getting-started/#browsers -// Source: http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/ - -@-ms-viewport { - width: device-width; -} - - -// Visibility utilities -.visible-xs, -.visible-sm, -.visible-md, -.visible-lg { - .responsive-invisibility(); -} - -.visible-xs { - @media (max-width: @screen-xs-max) { - .responsive-visibility(); - } -} -.visible-sm { - @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) { - .responsive-visibility(); - } -} -.visible-md { - @media (min-width: @screen-md-min) and (max-width: @screen-md-max) { - .responsive-visibility(); - } -} -.visible-lg { - @media (min-width: @screen-lg-min) { - .responsive-visibility(); - } -} - -.hidden-xs { - @media (max-width: @screen-xs-max) { - .responsive-invisibility(); - } -} -.hidden-sm { - @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) { - .responsive-invisibility(); - } -} -.hidden-md { - @media (min-width: @screen-md-min) and (max-width: @screen-md-max) { - .responsive-invisibility(); - } -} -.hidden-lg { - @media (min-width: @screen-lg-min) { - .responsive-invisibility(); - } -} - - -// Print utilities -// -// Media queries are placed on the inside to be mixin-friendly. - -.visible-print { - .responsive-invisibility(); - - @media print { - .responsive-visibility(); - } -} - -.hidden-print { - @media print { - .responsive-invisibility(); - } -}
diff --git a/docs/static/less/bootstrap/scaffolding.less b/docs/static/less/bootstrap/scaffolding.less deleted file mode 100644 index fe29f2d..0000000 --- a/docs/static/less/bootstrap/scaffolding.less +++ /dev/null
@@ -1,134 +0,0 @@ -// -// Scaffolding -// -------------------------------------------------- - - -// Reset the box-sizing -// -// Heads up! This reset may cause conflicts with some third-party widgets. -// For recommendations on resolving such conflicts, see -// http://getbootstrap.com/getting-started/#third-box-sizing -* { - .box-sizing(border-box); -} -*:before, -*:after { - .box-sizing(border-box); -} - - -// Body reset - -html { - font-size: 62.5%; - -webkit-tap-highlight-color: rgba(0,0,0,0); -} - -body { - font-family: @font-family-base; - font-size: @font-size-base; - line-height: @line-height-base; - color: @text-color; - background-color: @body-bg; -} - -// Reset fonts for relevant elements -input, -button, -select, -textarea { - font-family: inherit; - font-size: inherit; - line-height: inherit; -} - - -// Links - -a { - color: @link-color; - text-decoration: none; - - &:hover, - &:focus { - color: @link-hover-color; - text-decoration: underline; - } - - &:focus { - .tab-focus(); - } -} - - -// Figures -// -// We reset this here because previously Normalize had no `figure` margins. This -// ensures we don't break anyone's use of the element. - -figure { - margin: 0; -} - - -// Images - -img { - vertical-align: middle; -} - -// Responsive images (ensure images don't scale beyond their parents) -.img-responsive { - .img-responsive(); -} - -// Rounded corners -.img-rounded { - border-radius: @border-radius-large; -} - -// Image thumbnails -// -// Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`. -.img-thumbnail { - padding: @thumbnail-padding; - line-height: @line-height-base; - background-color: @thumbnail-bg; - border: 1px solid @thumbnail-border; - border-radius: @thumbnail-border-radius; - .transition(all .2s ease-in-out); - - // Keep them at most 100% wide - .img-responsive(inline-block); -} - -// Perfect circle -.img-circle { - border-radius: 50%; // set radius in percents -} - - -// Horizontal rules - -hr { - margin-top: @line-height-computed; - margin-bottom: @line-height-computed; - border: 0; - border-top: 1px solid @hr-border; -} - - -// Only display content to screen readers -// -// See: http://a11yproject.com/posts/how-to-hide-content/ - -.sr-only { - position: absolute; - width: 1px; - height: 1px; - margin: -1px; - padding: 0; - overflow: hidden; - clip: rect(0,0,0,0); - border: 0; -}
diff --git a/docs/static/less/bootstrap/tables.less b/docs/static/less/bootstrap/tables.less deleted file mode 100644 index c41989c..0000000 --- a/docs/static/less/bootstrap/tables.less +++ /dev/null
@@ -1,233 +0,0 @@ -// -// Tables -// -------------------------------------------------- - - -table { - max-width: 100%; - background-color: @table-bg; -} -th { - text-align: left; -} - - -// Baseline styles - -.table { - width: 100%; - margin-bottom: @line-height-computed; - // Cells - > thead, - > tbody, - > tfoot { - > tr { - > th, - > td { - padding: @table-cell-padding; - line-height: @line-height-base; - vertical-align: top; - border-top: 1px solid @table-border-color; - } - } - } - // Bottom align for column headings - > thead > tr > th { - vertical-align: bottom; - border-bottom: 2px solid @table-border-color; - } - // Remove top border from thead by default - > caption + thead, - > colgroup + thead, - > thead:first-child { - > tr:first-child { - > th, - > td { - border-top: 0; - } - } - } - // Account for multiple tbody instances - > tbody + tbody { - border-top: 2px solid @table-border-color; - } - - // Nesting - .table { - background-color: @body-bg; - } -} - - -// Condensed table w/ half padding - -.table-condensed { - > thead, - > tbody, - > tfoot { - > tr { - > th, - > td { - padding: @table-condensed-cell-padding; - } - } - } -} - - -// Bordered version -// -// Add borders all around the table and between all the columns. - -.table-bordered { - border: 1px solid @table-border-color; - > thead, - > tbody, - > tfoot { - > tr { - > th, - > td { - border: 1px solid @table-border-color; - } - } - } - > thead > tr { - > th, - > td { - border-bottom-width: 2px; - } - } -} - - -// Zebra-striping -// -// Default zebra-stripe styles (alternating gray and transparent backgrounds) - -.table-striped { - > tbody > tr:nth-child(odd) { - > td, - > th { - background-color: @table-bg-accent; - } - } -} - - -// Hover effect -// -// Placed here since it has to come after the potential zebra striping - -.table-hover { - > tbody > tr:hover { - > td, - > th { - background-color: @table-bg-hover; - } - } -} - - -// Table cell sizing -// -// Reset default table behavior - -table col[class*="col-"] { - position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623) - float: none; - display: table-column; -} -table { - td, - th { - &[class*="col-"] { - position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623) - float: none; - display: table-cell; - } - } -} - - -// Table backgrounds -// -// Exact selectors below required to override `.table-striped` and prevent -// inheritance to nested tables. - -// Generate the contextual variants -.table-row-variant(active; @table-bg-active); -.table-row-variant(success; @state-success-bg); -.table-row-variant(info; @state-info-bg); -.table-row-variant(warning; @state-warning-bg); -.table-row-variant(danger; @state-danger-bg); - - -// Responsive tables -// -// Wrap your tables in `.table-responsive` and we'll make them mobile friendly -// by enabling horizontal scrolling. Only applies <768px. Everything above that -// will display normally. - -@media (max-width: @screen-xs-max) { - .table-responsive { - width: 100%; - margin-bottom: (@line-height-computed * 0.75); - overflow-y: hidden; - overflow-x: scroll; - -ms-overflow-style: -ms-autohiding-scrollbar; - border: 1px solid @table-border-color; - -webkit-overflow-scrolling: touch; - - // Tighten up spacing - > .table { - margin-bottom: 0; - - // Ensure the content doesn't wrap - > thead, - > tbody, - > tfoot { - > tr { - > th, - > td { - white-space: nowrap; - } - } - } - } - - // Special overrides for the bordered tables - > .table-bordered { - border: 0; - - // Nuke the appropriate borders so that the parent can handle them - > thead, - > tbody, - > tfoot { - > tr { - > th:first-child, - > td:first-child { - border-left: 0; - } - > th:last-child, - > td:last-child { - border-right: 0; - } - } - } - - // Only nuke the last row's bottom-border in `tbody` and `tfoot` since - // chances are there will be only one `tr` in a `thead` and that would - // remove the border altogether. - > tbody, - > tfoot { - > tr:last-child { - > th, - > td { - border-bottom: 0; - } - } - } - - } - } -}
diff --git a/docs/static/less/bootstrap/theme.less b/docs/static/less/bootstrap/theme.less deleted file mode 100644 index 6f957fb..0000000 --- a/docs/static/less/bootstrap/theme.less +++ /dev/null
@@ -1,247 +0,0 @@ - -// -// Load core variables and mixins -// -------------------------------------------------- - -@import "variables.less"; -@import "mixins.less"; - - - -// -// Buttons -// -------------------------------------------------- - -// Common styles -.btn-default, -.btn-primary, -.btn-success, -.btn-info, -.btn-warning, -.btn-danger { - text-shadow: 0 -1px 0 rgba(0,0,0,.2); - @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075); - .box-shadow(@shadow); - - // Reset the shadow - &:active, - &.active { - .box-shadow(inset 0 3px 5px rgba(0,0,0,.125)); - } -} - -// Mixin for generating new styles -.btn-styles(@btn-color: #555) { - #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%)); - .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners - background-repeat: repeat-x; - border-color: darken(@btn-color, 14%); - - &:hover, - &:focus { - background-color: darken(@btn-color, 12%); - background-position: 0 -15px; - } - - &:active, - &.active { - background-color: darken(@btn-color, 12%); - border-color: darken(@btn-color, 14%); - } -} - -// Common styles -.btn { - // Remove the gradient for the pressed/active state - &:active, - &.active { - background-image: none; - } -} - -// Apply the mixin to the buttons -.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; } -.btn-primary { .btn-styles(@btn-primary-bg); } -.btn-success { .btn-styles(@btn-success-bg); } -.btn-info { .btn-styles(@btn-info-bg); } -.btn-warning { .btn-styles(@btn-warning-bg); } -.btn-danger { .btn-styles(@btn-danger-bg); } - - - -// -// Images -// -------------------------------------------------- - -.thumbnail, -.img-thumbnail { - .box-shadow(0 1px 2px rgba(0,0,0,.075)); -} - - - -// -// Dropdowns -// -------------------------------------------------- - -.dropdown-menu > li > a:hover, -.dropdown-menu > li > a:focus { - #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%)); - background-color: darken(@dropdown-link-hover-bg, 5%); -} -.dropdown-menu > .active > a, -.dropdown-menu > .active > a:hover, -.dropdown-menu > .active > a:focus { - #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%)); - background-color: darken(@dropdown-link-active-bg, 5%); -} - - - -// -// Navbar -// -------------------------------------------------- - -// Default navbar -.navbar-default { - #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg); - .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered - border-radius: @navbar-border-radius; - @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075); - .box-shadow(@shadow); - - .navbar-nav > .active > a { - #gradient > .vertical(@start-color: darken(@navbar-default-bg, 5%); @end-color: darken(@navbar-default-bg, 2%)); - .box-shadow(inset 0 3px 9px rgba(0,0,0,.075)); - } -} -.navbar-brand, -.navbar-nav > li > a { - text-shadow: 0 1px 0 rgba(255,255,255,.25); -} - -// Inverted navbar -.navbar-inverse { - #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg); - .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered - - .navbar-nav > .active > a { - #gradient > .vertical(@start-color: @navbar-inverse-bg; @end-color: lighten(@navbar-inverse-bg, 2.5%)); - .box-shadow(inset 0 3px 9px rgba(0,0,0,.25)); - } - - .navbar-brand, - .navbar-nav > li > a { - text-shadow: 0 -1px 0 rgba(0,0,0,.25); - } -} - -// Undo rounded corners in static and fixed navbars -.navbar-static-top, -.navbar-fixed-top, -.navbar-fixed-bottom { - border-radius: 0; -} - - - -// -// Alerts -// -------------------------------------------------- - -// Common styles -.alert { - text-shadow: 0 1px 0 rgba(255,255,255,.2); - @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05); - .box-shadow(@shadow); -} - -// Mixin for generating new styles -.alert-styles(@color) { - #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%)); - border-color: darken(@color, 15%); -} - -// Apply the mixin to the alerts -.alert-success { .alert-styles(@alert-success-bg); } -.alert-info { .alert-styles(@alert-info-bg); } -.alert-warning { .alert-styles(@alert-warning-bg); } -.alert-danger { .alert-styles(@alert-danger-bg); } - - - -// -// Progress bars -// -------------------------------------------------- - -// Give the progress background some depth -.progress { - #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg) -} - -// Mixin for generating new styles -.progress-bar-styles(@color) { - #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%)); -} - -// Apply the mixin to the progress bars -.progress-bar { .progress-bar-styles(@progress-bar-bg); } -.progress-bar-success { .progress-bar-styles(@progress-bar-success-bg); } -.progress-bar-info { .progress-bar-styles(@progress-bar-info-bg); } -.progress-bar-warning { .progress-bar-styles(@progress-bar-warning-bg); } -.progress-bar-danger { .progress-bar-styles(@progress-bar-danger-bg); } - - - -// -// List groups -// -------------------------------------------------- - -.list-group { - border-radius: @border-radius-base; - .box-shadow(0 1px 2px rgba(0,0,0,.075)); -} -.list-group-item.active, -.list-group-item.active:hover, -.list-group-item.active:focus { - text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%); - #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%)); - border-color: darken(@list-group-active-border, 7.5%); -} - - - -// -// Panels -// -------------------------------------------------- - -// Common styles -.panel { - .box-shadow(0 1px 2px rgba(0,0,0,.05)); -} - -// Mixin for generating new styles -.panel-heading-styles(@color) { - #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%)); -} - -// Apply the mixin to the panel headings only -.panel-default > .panel-heading { .panel-heading-styles(@panel-default-heading-bg); } -.panel-primary > .panel-heading { .panel-heading-styles(@panel-primary-heading-bg); } -.panel-success > .panel-heading { .panel-heading-styles(@panel-success-heading-bg); } -.panel-info > .panel-heading { .panel-heading-styles(@panel-info-heading-bg); } -.panel-warning > .panel-heading { .panel-heading-styles(@panel-warning-heading-bg); } -.panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); } - - - -// -// Wells -// -------------------------------------------------- - -.well { - #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg); - border-color: darken(@well-bg, 10%); - @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1); - .box-shadow(@shadow); -}
diff --git a/docs/static/less/bootstrap/thumbnails.less b/docs/static/less/bootstrap/thumbnails.less deleted file mode 100644 index c428920..0000000 --- a/docs/static/less/bootstrap/thumbnails.less +++ /dev/null
@@ -1,36 +0,0 @@ -// -// Thumbnails -// -------------------------------------------------- - - -// Mixin and adjust the regular image class -.thumbnail { - display: block; - padding: @thumbnail-padding; - margin-bottom: @line-height-computed; - line-height: @line-height-base; - background-color: @thumbnail-bg; - border: 1px solid @thumbnail-border; - border-radius: @thumbnail-border-radius; - .transition(all .2s ease-in-out); - - > img, - a > img { - &:extend(.img-responsive); - margin-left: auto; - margin-right: auto; - } - - // Add a hover state for linked versions only - a&:hover, - a&:focus, - a&.active { - border-color: @link-color; - } - - // Image captions - .caption { - padding: @thumbnail-caption-padding; - color: @thumbnail-caption-color; - } -}
diff --git a/docs/static/less/bootstrap/tooltip.less b/docs/static/less/bootstrap/tooltip.less deleted file mode 100644 index bd62699..0000000 --- a/docs/static/less/bootstrap/tooltip.less +++ /dev/null
@@ -1,95 +0,0 @@ -// -// Tooltips -// -------------------------------------------------- - - -// Base class -.tooltip { - position: absolute; - z-index: @zindex-tooltip; - display: block; - visibility: visible; - font-size: @font-size-small; - line-height: 1.4; - .opacity(0); - - &.in { .opacity(@tooltip-opacity); } - &.top { margin-top: -3px; padding: @tooltip-arrow-width 0; } - &.right { margin-left: 3px; padding: 0 @tooltip-arrow-width; } - &.bottom { margin-top: 3px; padding: @tooltip-arrow-width 0; } - &.left { margin-left: -3px; padding: 0 @tooltip-arrow-width; } -} - -// Wrapper for the tooltip content -.tooltip-inner { - max-width: @tooltip-max-width; - padding: 3px 8px; - color: @tooltip-color; - text-align: center; - text-decoration: none; - background-color: @tooltip-bg; - border-radius: @border-radius-base; -} - -// Arrows -.tooltip-arrow { - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} -.tooltip { - &.top .tooltip-arrow { - bottom: 0; - left: 50%; - margin-left: -@tooltip-arrow-width; - border-width: @tooltip-arrow-width @tooltip-arrow-width 0; - border-top-color: @tooltip-arrow-color; - } - &.top-left .tooltip-arrow { - bottom: 0; - left: @tooltip-arrow-width; - border-width: @tooltip-arrow-width @tooltip-arrow-width 0; - border-top-color: @tooltip-arrow-color; - } - &.top-right .tooltip-arrow { - bottom: 0; - right: @tooltip-arrow-width; - border-width: @tooltip-arrow-width @tooltip-arrow-width 0; - border-top-color: @tooltip-arrow-color; - } - &.right .tooltip-arrow { - top: 50%; - left: 0; - margin-top: -@tooltip-arrow-width; - border-width: @tooltip-arrow-width @tooltip-arrow-width @tooltip-arrow-width 0; - border-right-color: @tooltip-arrow-color; - } - &.left .tooltip-arrow { - top: 50%; - right: 0; - margin-top: -@tooltip-arrow-width; - border-width: @tooltip-arrow-width 0 @tooltip-arrow-width @tooltip-arrow-width; - border-left-color: @tooltip-arrow-color; - } - &.bottom .tooltip-arrow { - top: 0; - left: 50%; - margin-left: -@tooltip-arrow-width; - border-width: 0 @tooltip-arrow-width @tooltip-arrow-width; - border-bottom-color: @tooltip-arrow-color; - } - &.bottom-left .tooltip-arrow { - top: 0; - left: @tooltip-arrow-width; - border-width: 0 @tooltip-arrow-width @tooltip-arrow-width; - border-bottom-color: @tooltip-arrow-color; - } - &.bottom-right .tooltip-arrow { - top: 0; - right: @tooltip-arrow-width; - border-width: 0 @tooltip-arrow-width @tooltip-arrow-width; - border-bottom-color: @tooltip-arrow-color; - } -}
diff --git a/docs/static/less/bootstrap/type.less b/docs/static/less/bootstrap/type.less deleted file mode 100644 index 5e2a219..0000000 --- a/docs/static/less/bootstrap/type.less +++ /dev/null
@@ -1,293 +0,0 @@ -// -// Typography -// -------------------------------------------------- - - -// Headings -// ------------------------- - -h1, h2, h3, h4, h5, h6, -.h1, .h2, .h3, .h4, .h5, .h6 { - font-family: @headings-font-family; - font-weight: @headings-font-weight; - line-height: @headings-line-height; - color: @headings-color; - - small, - .small { - font-weight: normal; - line-height: 1; - color: @headings-small-color; - } -} - -h1, .h1, -h2, .h2, -h3, .h3 { - margin-top: @line-height-computed; - margin-bottom: (@line-height-computed / 2); - - small, - .small { - font-size: 65%; - } -} -h4, .h4, -h5, .h5, -h6, .h6 { - margin-top: (@line-height-computed / 2); - margin-bottom: (@line-height-computed / 2); - - small, - .small { - font-size: 75%; - } -} - -h1, .h1 { font-size: @font-size-h1; } -h2, .h2 { font-size: @font-size-h2; } -h3, .h3 { font-size: @font-size-h3; } -h4, .h4 { font-size: @font-size-h4; } -h5, .h5 { font-size: @font-size-h5; } -h6, .h6 { font-size: @font-size-h6; } - - -// Body text -// ------------------------- - -p { - margin: 0 0 (@line-height-computed / 2); -} - -.lead { - margin-bottom: @line-height-computed; - font-size: floor((@font-size-base * 1.15)); - font-weight: 200; - line-height: 1.4; - - @media (min-width: @screen-sm-min) { - font-size: (@font-size-base * 1.5); - } -} - - -// Emphasis & misc -// ------------------------- - -// Ex: 14px base font * 85% = about 12px -small, -.small { font-size: 85%; } - -// Undo browser default styling -cite { font-style: normal; } - -// Alignment -.text-left { text-align: left; } -.text-right { text-align: right; } -.text-center { text-align: center; } -.text-justify { text-align: justify; } - -// Contextual colors -.text-muted { - color: @text-muted; -} -.text-primary { - .text-emphasis-variant(@brand-primary); -} -.text-success { - .text-emphasis-variant(@state-success-text); -} -.text-info { - .text-emphasis-variant(@state-info-text); -} -.text-warning { - .text-emphasis-variant(@state-warning-text); -} -.text-danger { - .text-emphasis-variant(@state-danger-text); -} - -// Contextual backgrounds -// For now we'll leave these alongside the text classes until v4 when we can -// safely shift things around (per SemVer rules). -.bg-primary { - // Given the contrast here, this is the only class to have its color inverted - // automatically. - color: #fff; - .bg-variant(@brand-primary); -} -.bg-success { - .bg-variant(@state-success-bg); -} -.bg-info { - .bg-variant(@state-info-bg); -} -.bg-warning { - .bg-variant(@state-warning-bg); -} -.bg-danger { - .bg-variant(@state-danger-bg); -} - - -// Page header -// ------------------------- - -.page-header { - padding-bottom: ((@line-height-computed / 2) - 1); - margin: (@line-height-computed * 2) 0 @line-height-computed; - border-bottom: 1px solid @page-header-border-color; -} - - -// Lists -// -------------------------------------------------- - -// Unordered and Ordered lists -ul, -ol { - margin-top: 0; - margin-bottom: (@line-height-computed / 2); - ul, - ol { - margin-bottom: 0; - } -} - -// List options - -// Unstyled keeps list items block level, just removes default browser padding and list-style -.list-unstyled { - padding-left: 0; - list-style: none; -} - -// Inline turns list items into inline-block -.list-inline { - .list-unstyled(); - margin-left: -5px; - - > li { - display: inline-block; - padding-left: 5px; - padding-right: 5px; - } -} - -// Description Lists -dl { - margin-top: 0; // Remove browser default - margin-bottom: @line-height-computed; -} -dt, -dd { - line-height: @line-height-base; -} -dt { - font-weight: bold; -} -dd { - margin-left: 0; // Undo browser default -} - -// Horizontal description lists -// -// Defaults to being stacked without any of the below styles applied, until the -// grid breakpoint is reached (default of ~768px). - -@media (min-width: @grid-float-breakpoint) { - .dl-horizontal { - dt { - float: left; - width: (@component-offset-horizontal - 20); - clear: left; - text-align: right; - .text-overflow(); - } - dd { - margin-left: @component-offset-horizontal; - &:extend(.clearfix all); // Clear the floated `dt` if an empty `dd` is present - } - } -} - -// MISC -// ---- - -// Abbreviations and acronyms -abbr[title], -// Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257 -abbr[data-original-title] { - cursor: help; - border-bottom: 1px dotted @abbr-border-color; -} -.initialism { - font-size: 90%; - text-transform: uppercase; -} - -// Blockquotes -blockquote { - padding: (@line-height-computed / 2) @line-height-computed; - margin: 0 0 @line-height-computed; - font-size: @blockquote-font-size; - border-left: 5px solid @blockquote-border-color; - - p, - ul, - ol { - &:last-child { - margin-bottom: 0; - } - } - - // Note: Deprecated small and .small as of v3.1.0 - // Context: https://github.com/twbs/bootstrap/issues/11660 - footer, - small, - .small { - display: block; - font-size: 80%; // back to default font-size - line-height: @line-height-base; - color: @blockquote-small-color; - - &:before { - content: '\2014 \00A0'; // em dash, nbsp - } - } -} - -// Opposite alignment of blockquote -// -// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0. -.blockquote-reverse, -blockquote.pull-right { - padding-right: 15px; - padding-left: 0; - border-right: 5px solid @blockquote-border-color; - border-left: 0; - text-align: right; - - // Account for citation - footer, - small, - .small { - &:before { content: ''; } - &:after { - content: '\00A0 \2014'; // nbsp, em dash - } - } -} - -// Quotes -blockquote:before, -blockquote:after { - content: ""; -} - -// Addresses -address { - margin-bottom: @line-height-computed; - font-style: normal; - line-height: @line-height-base; -}
diff --git a/docs/static/less/bootstrap/utilities.less b/docs/static/less/bootstrap/utilities.less deleted file mode 100644 index a260312..0000000 --- a/docs/static/less/bootstrap/utilities.less +++ /dev/null
@@ -1,56 +0,0 @@ -// -// Utility classes -// -------------------------------------------------- - - -// Floats -// ------------------------- - -.clearfix { - .clearfix(); -} -.center-block { - .center-block(); -} -.pull-right { - float: right !important; -} -.pull-left { - float: left !important; -} - - -// Toggling content -// ------------------------- - -// Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1 -.hide { - display: none !important; -} -.show { - display: block !important; -} -.invisible { - visibility: hidden; -} -.text-hide { - .text-hide(); -} - - -// Hide from screenreaders and browsers -// -// Credit: HTML5 Boilerplate - -.hidden { - display: none !important; - visibility: hidden !important; -} - - -// For Affix plugin -// ------------------------- - -.affix { - position: fixed; -}
diff --git a/docs/static/less/bootstrap/variables.less b/docs/static/less/bootstrap/variables.less deleted file mode 100644 index 3846adc..0000000 --- a/docs/static/less/bootstrap/variables.less +++ /dev/null
@@ -1,829 +0,0 @@ -// -// Variables -// -------------------------------------------------- - - -//== Colors -// -//## Gray and brand colors for use across Bootstrap. - -@gray-darker: lighten(#000, 13.5%); // #222 -@gray-dark: lighten(#000, 20%); // #333 -@gray: lighten(#000, 33.5%); // #555 -@gray-light: lighten(#000, 60%); // #999 -@gray-lighter: lighten(#000, 93.5%); // #eee - -@brand-primary: #428bca; -@brand-success: #5cb85c; -@brand-info: #5bc0de; -@brand-warning: #f0ad4e; -@brand-danger: #d9534f; - - -//== Scaffolding -// -// ## Settings for some of the most global styles. - -//** Background color for `<body>`. -@body-bg: #fff; -//** Global text color on `<body>`. -@text-color: @gray-dark; - -//** Global textual link color. -@link-color: @brand-primary; -//** Link hover color set via `darken()` function. -@link-hover-color: darken(@link-color, 15%); - - -//== Typography -// -//## Font, line-height, and color for body text, headings, and more. - -@font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif; -@font-family-serif: Georgia, "Times New Roman", Times, serif; -//** Default monospace fonts for `<code>`, `<kbd>`, and `<pre>`. -@font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace; -@font-family-base: @font-family-sans-serif; - -@font-size-base: 14px; -@font-size-large: ceil((@font-size-base * 1.25)); // ~18px -@font-size-small: ceil((@font-size-base * 0.85)); // ~12px - -@font-size-h1: floor((@font-size-base * 2.6)); // ~36px -@font-size-h2: floor((@font-size-base * 2.15)); // ~30px -@font-size-h3: ceil((@font-size-base * 1.7)); // ~24px -@font-size-h4: ceil((@font-size-base * 1.25)); // ~18px -@font-size-h5: @font-size-base; -@font-size-h6: ceil((@font-size-base * 0.85)); // ~12px - -//** Unit-less `line-height` for use in components like buttons. -@line-height-base: 1.428571429; // 20/14 -//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc. -@line-height-computed: floor((@font-size-base * @line-height-base)); // ~20px - -//** By default, this inherits from the `<body>`. -@headings-font-family: inherit; -@headings-font-weight: 500; -@headings-line-height: 1.1; -@headings-color: inherit; - - -//-- Iconography -// -//## Specify custom locations of the include Glyphicons icon font. Useful for those including Bootstrap via Bower. - -@icon-font-path: "../fonts/"; -@icon-font-name: "glyphicons-halflings-regular"; -@icon-font-svg-id: "glyphicons_halflingsregular"; - -//== Components -// -//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start). - -@padding-base-vertical: 6px; -@padding-base-horizontal: 12px; - -@padding-large-vertical: 10px; -@padding-large-horizontal: 16px; - -@padding-small-vertical: 5px; -@padding-small-horizontal: 10px; - -@padding-xs-vertical: 1px; -@padding-xs-horizontal: 5px; - -@line-height-large: 1.33; -@line-height-small: 1.5; - -@border-radius-base: 4px; -@border-radius-large: 6px; -@border-radius-small: 3px; - -//** Global color for active items (e.g., navs or dropdowns). -@component-active-color: #fff; -//** Global background color for active items (e.g., navs or dropdowns). -@component-active-bg: @brand-primary; - -//** Width of the `border` for generating carets that indicator dropdowns. -@caret-width-base: 4px; -//** Carets increase slightly in size for larger components. -@caret-width-large: 5px; - - -//== Tables -// -//## Customizes the `.table` component with basic values, each used across all table variations. - -//** Padding for `<th>`s and `<td>`s. -@table-cell-padding: 8px; -//** Padding for cells in `.table-condensed`. -@table-condensed-cell-padding: 5px; - -//** Default background color used for all tables. -@table-bg: transparent; -//** Background color used for `.table-striped`. -@table-bg-accent: #f9f9f9; -//** Background color used for `.table-hover`. -@table-bg-hover: #f5f5f5; -@table-bg-active: @table-bg-hover; - -//** Border color for table and cell borders. -@table-border-color: #ddd; - - -//== Buttons -// -//## For each of Bootstrap's buttons, define text, background and border color. - -@btn-font-weight: normal; - -@btn-default-color: #333; -@btn-default-bg: #fff; -@btn-default-border: #ccc; - -@btn-primary-color: #fff; -@btn-primary-bg: @brand-primary; -@btn-primary-border: darken(@btn-primary-bg, 5%); - -@btn-success-color: #fff; -@btn-success-bg: @brand-success; -@btn-success-border: darken(@btn-success-bg, 5%); - -@btn-info-color: #fff; -@btn-info-bg: @brand-info; -@btn-info-border: darken(@btn-info-bg, 5%); - -@btn-warning-color: #fff; -@btn-warning-bg: @brand-warning; -@btn-warning-border: darken(@btn-warning-bg, 5%); - -@btn-danger-color: #fff; -@btn-danger-bg: @brand-danger; -@btn-danger-border: darken(@btn-danger-bg, 5%); - -@btn-link-disabled-color: @gray-light; - - -//== Forms -// -//## - -//** `<input>` background color -@input-bg: #fff; -//** `<input disabled>` background color -@input-bg-disabled: @gray-lighter; - -//** Text color for `<input>`s -@input-color: @gray; -//** `<input>` border color -@input-border: #ccc; -//** `<input>` border radius -@input-border-radius: @border-radius-base; -//** Border color for inputs on focus -@input-border-focus: #66afe9; - -//** Placeholder text color -@input-color-placeholder: @gray-light; - -//** Default `.form-control` height -@input-height-base: (@line-height-computed + (@padding-base-vertical * 2) + 2); -//** Large `.form-control` height -@input-height-large: (ceil(@font-size-large * @line-height-large) + (@padding-large-vertical * 2) + 2); -//** Small `.form-control` height -@input-height-small: (floor(@font-size-small * @line-height-small) + (@padding-small-vertical * 2) + 2); - -@legend-color: @gray-dark; -@legend-border-color: #e5e5e5; - -//** Background color for textual input addons -@input-group-addon-bg: @gray-lighter; -//** Border color for textual input addons -@input-group-addon-border-color: @input-border; - - -//== Dropdowns -// -//## Dropdown menu container and contents. - -//** Background for the dropdown menu. -@dropdown-bg: #fff; -//** Dropdown menu `border-color`. -@dropdown-border: rgba(0,0,0,.15); -//** Dropdown menu `border-color` **for IE8**. -@dropdown-fallback-border: #ccc; -//** Divider color for between dropdown items. -@dropdown-divider-bg: #e5e5e5; - -//** Dropdown link text color. -@dropdown-link-color: @gray-dark; -//** Hover color for dropdown links. -@dropdown-link-hover-color: darken(@gray-dark, 5%); -//** Hover background for dropdown links. -@dropdown-link-hover-bg: #f5f5f5; - -//** Active dropdown menu item text color. -@dropdown-link-active-color: @component-active-color; -//** Active dropdown menu item background color. -@dropdown-link-active-bg: @component-active-bg; - -//** Disabled dropdown menu item background color. -@dropdown-link-disabled-color: @gray-light; - -//** Text color for headers within dropdown menus. -@dropdown-header-color: @gray-light; - -// Note: Deprecated @dropdown-caret-color as of v3.1.0 -@dropdown-caret-color: #000; - - -//-- Z-index master list -// -// Warning: Avoid customizing these values. They're used for a bird's eye view -// of components dependent on the z-axis and are designed to all work together. -// -// Note: These variables are not generated into the Customizer. - -@zindex-navbar: 1000; -@zindex-dropdown: 1000; -@zindex-popover: 1010; -@zindex-tooltip: 1030; -@zindex-navbar-fixed: 1030; -@zindex-modal-background: 1040; -@zindex-modal: 1050; - - -//== Media queries breakpoints -// -//## Define the breakpoints at which your layout will change, adapting to different screen sizes. - -// Extra small screen / phone -// Note: Deprecated @screen-xs and @screen-phone as of v3.0.1 -@screen-xs: 480px; -@screen-xs-min: @screen-xs; -@screen-phone: @screen-xs-min; - -// Small screen / tablet -// Note: Deprecated @screen-sm and @screen-tablet as of v3.0.1 -@screen-sm: 768px; -@screen-sm-min: @screen-sm; -@screen-tablet: @screen-sm-min; - -// Medium screen / desktop -// Note: Deprecated @screen-md and @screen-desktop as of v3.0.1 -@screen-md: 992px; -@screen-md-min: @screen-md; -@screen-desktop: @screen-md-min; - -// Large screen / wide desktop -// Note: Deprecated @screen-lg and @screen-lg-desktop as of v3.0.1 -@screen-lg: 1200px; -@screen-lg-min: @screen-lg; -@screen-lg-desktop: @screen-lg-min; - -// So media queries don't overlap when required, provide a maximum -@screen-xs-max: (@screen-sm-min - 1); -@screen-sm-max: (@screen-md-min - 1); -@screen-md-max: (@screen-lg-min - 1); - - -//== Grid system -// -//## Define your custom responsive grid. - -//** Number of columns in the grid. -@grid-columns: 12; -//** Padding between columns. Gets divided in half for the left and right. -@grid-gutter-width: 30px; -// Navbar collapse -//** Point at which the navbar becomes uncollapsed. -@grid-float-breakpoint: @screen-sm-min; -//** Point at which the navbar begins collapsing. -@grid-float-breakpoint-max: (@grid-float-breakpoint - 1); - - -//== Container sizes -// -//## Define the maximum width of `.container` for different screen sizes. - -// Small screen / tablet -@container-tablet: ((720px + @grid-gutter-width)); -//** For `@screen-sm-min` and up. -@container-sm: @container-tablet; - -// Medium screen / desktop -@container-desktop: ((940px + @grid-gutter-width)); -//** For `@screen-md-min` and up. -@container-md: @container-desktop; - -// Large screen / wide desktop -@container-large-desktop: ((1140px + @grid-gutter-width)); -//** For `@screen-lg-min` and up. -@container-lg: @container-large-desktop; - - -//== Navbar -// -//## - -// Basics of a navbar -@navbar-height: 50px; -@navbar-margin-bottom: @line-height-computed; -@navbar-border-radius: @border-radius-base; -@navbar-padding-horizontal: floor((@grid-gutter-width / 2)); -@navbar-padding-vertical: ((@navbar-height - @line-height-computed) / 2); -@navbar-collapse-max-height: 340px; - -@navbar-default-color: #777; -@navbar-default-bg: #f8f8f8; -@navbar-default-border: darken(@navbar-default-bg, 6.5%); - -// Navbar links -@navbar-default-link-color: #777; -@navbar-default-link-hover-color: #333; -@navbar-default-link-hover-bg: transparent; -@navbar-default-link-active-color: #555; -@navbar-default-link-active-bg: darken(@navbar-default-bg, 6.5%); -@navbar-default-link-disabled-color: #ccc; -@navbar-default-link-disabled-bg: transparent; - -// Navbar brand label -@navbar-default-brand-color: @navbar-default-link-color; -@navbar-default-brand-hover-color: darken(@navbar-default-brand-color, 10%); -@navbar-default-brand-hover-bg: transparent; - -// Navbar toggle -@navbar-default-toggle-hover-bg: #ddd; -@navbar-default-toggle-icon-bar-bg: #888; -@navbar-default-toggle-border-color: #ddd; - - -// Inverted navbar -// Reset inverted navbar basics -@navbar-inverse-color: @gray-light; -@navbar-inverse-bg: #222; -@navbar-inverse-border: darken(@navbar-inverse-bg, 10%); - -// Inverted navbar links -@navbar-inverse-link-color: @gray-light; -@navbar-inverse-link-hover-color: #fff; -@navbar-inverse-link-hover-bg: transparent; -@navbar-inverse-link-active-color: @navbar-inverse-link-hover-color; -@navbar-inverse-link-active-bg: darken(@navbar-inverse-bg, 10%); -@navbar-inverse-link-disabled-color: #444; -@navbar-inverse-link-disabled-bg: transparent; - -// Inverted navbar brand label -@navbar-inverse-brand-color: @navbar-inverse-link-color; -@navbar-inverse-brand-hover-color: #fff; -@navbar-inverse-brand-hover-bg: transparent; - -// Inverted navbar toggle -@navbar-inverse-toggle-hover-bg: #333; -@navbar-inverse-toggle-icon-bar-bg: #fff; -@navbar-inverse-toggle-border-color: #333; - - -//== Navs -// -//## - -//=== Shared nav styles -@nav-link-padding: 10px 15px; -@nav-link-hover-bg: @gray-lighter; - -@nav-disabled-link-color: @gray-light; -@nav-disabled-link-hover-color: @gray-light; - -@nav-open-link-hover-color: #fff; - -//== Tabs -@nav-tabs-border-color: #ddd; - -@nav-tabs-link-hover-border-color: @gray-lighter; - -@nav-tabs-active-link-hover-bg: @body-bg; -@nav-tabs-active-link-hover-color: @gray; -@nav-tabs-active-link-hover-border-color: #ddd; - -@nav-tabs-justified-link-border-color: #ddd; -@nav-tabs-justified-active-link-border-color: @body-bg; - -//== Pills -@nav-pills-border-radius: @border-radius-base; -@nav-pills-active-link-hover-bg: @component-active-bg; -@nav-pills-active-link-hover-color: @component-active-color; - - -//== Pagination -// -//## - -@pagination-color: @link-color; -@pagination-bg: #fff; -@pagination-border: #ddd; - -@pagination-hover-color: @link-hover-color; -@pagination-hover-bg: @gray-lighter; -@pagination-hover-border: #ddd; - -@pagination-active-color: #fff; -@pagination-active-bg: @brand-primary; -@pagination-active-border: @brand-primary; - -@pagination-disabled-color: @gray-light; -@pagination-disabled-bg: #fff; -@pagination-disabled-border: #ddd; - - -//== Pager -// -//## - -@pager-bg: @pagination-bg; -@pager-border: @pagination-border; -@pager-border-radius: 15px; - -@pager-hover-bg: @pagination-hover-bg; - -@pager-active-bg: @pagination-active-bg; -@pager-active-color: @pagination-active-color; - -@pager-disabled-color: @pagination-disabled-color; - - -//== Jumbotron -// -//## - -@jumbotron-padding: 30px; -@jumbotron-color: inherit; -@jumbotron-bg: @gray-lighter; -@jumbotron-heading-color: inherit; -@jumbotron-font-size: ceil((@font-size-base * 1.5)); - - -//== Form states and alerts -// -//## Define colors for form feedback states and, by default, alerts. - -@state-success-text: #3c763d; -@state-success-bg: #dff0d8; -@state-success-border: darken(spin(@state-success-bg, -10), 5%); - -@state-info-text: #31708f; -@state-info-bg: #d9edf7; -@state-info-border: darken(spin(@state-info-bg, -10), 7%); - -@state-warning-text: #8a6d3b; -@state-warning-bg: #fcf8e3; -@state-warning-border: darken(spin(@state-warning-bg, -10), 5%); - -@state-danger-text: #a94442; -@state-danger-bg: #f2dede; -@state-danger-border: darken(spin(@state-danger-bg, -10), 5%); - - -//== Tooltips -// -//## - -//** Tooltip max width -@tooltip-max-width: 200px; -//** Tooltip text color -@tooltip-color: #fff; -//** Tooltip background color -@tooltip-bg: #000; -@tooltip-opacity: .9; - -//** Tooltip arrow width -@tooltip-arrow-width: 5px; -//** Tooltip arrow color -@tooltip-arrow-color: @tooltip-bg; - - -//== Popovers -// -//## - -//** Popover body background color -@popover-bg: #fff; -//** Popover maximum width -@popover-max-width: 276px; -//** Popover border color -@popover-border-color: rgba(0,0,0,.2); -//** Popover fallback border color -@popover-fallback-border-color: #ccc; - -//** Popover title background color -@popover-title-bg: darken(@popover-bg, 3%); - -//** Popover arrow width -@popover-arrow-width: 10px; -//** Popover arrow color -@popover-arrow-color: #fff; - -//** Popover outer arrow width -@popover-arrow-outer-width: (@popover-arrow-width + 1); -//** Popover outer arrow color -@popover-arrow-outer-color: fadein(@popover-border-color, 5%); -//** Popover outer arrow fallback color -@popover-arrow-outer-fallback-color: darken(@popover-fallback-border-color, 20%); - - -//== Labels -// -//## - -//** Default label background color -@label-default-bg: @gray-light; -//** Primary label background color -@label-primary-bg: @brand-primary; -//** Success label background color -@label-success-bg: @brand-success; -//** Info label background color -@label-info-bg: @brand-info; -//** Warning label background color -@label-warning-bg: @brand-warning; -//** Danger label background color -@label-danger-bg: @brand-danger; - -//** Default label text color -@label-color: #fff; -//** Default text color of a linked label -@label-link-hover-color: #fff; - - -//== Modals -// -//## - -//** Padding applied to the modal body -@modal-inner-padding: 20px; - -//** Padding applied to the modal title -@modal-title-padding: 15px; -//** Modal title line-height -@modal-title-line-height: @line-height-base; - -//** Background color of modal content area -@modal-content-bg: #fff; -//** Modal content border color -@modal-content-border-color: rgba(0,0,0,.2); -//** Modal content border color **for IE8** -@modal-content-fallback-border-color: #999; - -//** Modal backdrop background color -@modal-backdrop-bg: #000; -//** Modal backdrop opacity -@modal-backdrop-opacity: .5; -//** Modal header border color -@modal-header-border-color: #e5e5e5; -//** Modal footer border color -@modal-footer-border-color: @modal-header-border-color; - -@modal-lg: 900px; -@modal-md: 600px; -@modal-sm: 300px; - - -//== Alerts -// -//## Define alert colors, border radius, and padding. - -@alert-padding: 15px; -@alert-border-radius: @border-radius-base; -@alert-link-font-weight: bold; - -@alert-success-bg: @state-success-bg; -@alert-success-text: @state-success-text; -@alert-success-border: @state-success-border; - -@alert-info-bg: @state-info-bg; -@alert-info-text: @state-info-text; -@alert-info-border: @state-info-border; - -@alert-warning-bg: @state-warning-bg; -@alert-warning-text: @state-warning-text; -@alert-warning-border: @state-warning-border; - -@alert-danger-bg: @state-danger-bg; -@alert-danger-text: @state-danger-text; -@alert-danger-border: @state-danger-border; - - -//== Progress bars -// -//## - -//** Background color of the whole progress component -@progress-bg: #f5f5f5; -//** Progress bar text color -@progress-bar-color: #fff; - -//** Default progress bar color -@progress-bar-bg: @brand-primary; -//** Success progress bar color -@progress-bar-success-bg: @brand-success; -//** Warning progress bar color -@progress-bar-warning-bg: @brand-warning; -//** Danger progress bar color -@progress-bar-danger-bg: @brand-danger; -//** Info progress bar color -@progress-bar-info-bg: @brand-info; - - -//== List group -// -//## - -//** Background color on `.list-group-item` -@list-group-bg: #fff; -//** `.list-group-item` border color -@list-group-border: #ddd; -//** List group border radius -@list-group-border-radius: @border-radius-base; - -//** Background color of single list elements on hover -@list-group-hover-bg: #f5f5f5; -//** Text color of active list elements -@list-group-active-color: @component-active-color; -//** Background color of active list elements -@list-group-active-bg: @component-active-bg; -//** Border color of active list elements -@list-group-active-border: @list-group-active-bg; -@list-group-active-text-color: lighten(@list-group-active-bg, 40%); - -@list-group-link-color: #555; -@list-group-link-heading-color: #333; - - -//== Panels -// -//## - -@panel-bg: #fff; -@panel-body-padding: 15px; -@panel-border-radius: @border-radius-base; - -//** Border color for elements within panels -@panel-inner-border: #ddd; -@panel-footer-bg: #f5f5f5; - -@panel-default-text: @gray-dark; -@panel-default-border: #ddd; -@panel-default-heading-bg: #f5f5f5; - -@panel-primary-text: #fff; -@panel-primary-border: @brand-primary; -@panel-primary-heading-bg: @brand-primary; - -@panel-success-text: @state-success-text; -@panel-success-border: @state-success-border; -@panel-success-heading-bg: @state-success-bg; - -@panel-info-text: @state-info-text; -@panel-info-border: @state-info-border; -@panel-info-heading-bg: @state-info-bg; - -@panel-warning-text: @state-warning-text; -@panel-warning-border: @state-warning-border; -@panel-warning-heading-bg: @state-warning-bg; - -@panel-danger-text: @state-danger-text; -@panel-danger-border: @state-danger-border; -@panel-danger-heading-bg: @state-danger-bg; - - -//== Thumbnails -// -//## - -//** Padding around the thumbnail image -@thumbnail-padding: 4px; -//** Thumbnail background color -@thumbnail-bg: @body-bg; -//** Thumbnail border color -@thumbnail-border: #ddd; -//** Thumbnail border radius -@thumbnail-border-radius: @border-radius-base; - -//** Custom text color for thumbnail captions -@thumbnail-caption-color: @text-color; -//** Padding around the thumbnail caption -@thumbnail-caption-padding: 9px; - - -//== Wells -// -//## - -@well-bg: #f5f5f5; -@well-border: darken(@well-bg, 7%); - - -//== Badges -// -//## - -@badge-color: #fff; -//** Linked badge text color on hover -@badge-link-hover-color: #fff; -@badge-bg: @gray-light; - -//** Badge text color in active nav link -@badge-active-color: @link-color; -//** Badge background color in active nav link -@badge-active-bg: #fff; - -@badge-font-weight: bold; -@badge-line-height: 1; -@badge-border-radius: 10px; - - -//== Breadcrumbs -// -//## - -@breadcrumb-padding-vertical: 8px; -@breadcrumb-padding-horizontal: 15px; -//** Breadcrumb background color -@breadcrumb-bg: #f5f5f5; -//** Breadcrumb text color -@breadcrumb-color: #ccc; -//** Text color of current page in the breadcrumb -@breadcrumb-active-color: @gray-light; -//** Textual separator for between breadcrumb elements -@breadcrumb-separator: "/"; - - -//== Carousel -// -//## - -@carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6); - -@carousel-control-color: #fff; -@carousel-control-width: 15%; -@carousel-control-opacity: .5; -@carousel-control-font-size: 20px; - -@carousel-indicator-active-bg: #fff; -@carousel-indicator-border-color: #fff; - -@carousel-caption-color: #fff; - - -//== Close -// -//## - -@close-font-weight: bold; -@close-color: #000; -@close-text-shadow: 0 1px 0 #fff; - - -//== Code -// -//## - -@code-color: #c7254e; -@code-bg: #f9f2f4; - -@kbd-color: #fff; -@kbd-bg: #333; - -@pre-bg: #f5f5f5; -@pre-color: @gray-dark; -@pre-border-color: #ccc; -@pre-scrollable-max-height: 340px; - - -//== Type -// -//## - -//** Text muted color -@text-muted: @gray-light; -//** Abbreviations and acronyms border color -@abbr-border-color: @gray-light; -//** Headings small color -@headings-small-color: @gray-light; -//** Blockquote small color -@blockquote-small-color: @gray-light; -//** Blockquote font size -@blockquote-font-size: (@font-size-base * 1.25); -//** Blockquote border color -@blockquote-border-color: @gray-lighter; -//** Page header border color -@page-header-border-color: @gray-lighter; - - -//== Miscellaneous -// -//## - -//** Horizontal line color. -@hr-border: @gray-lighter; - -//** Horizontal offset for forms and lists. -@component-offset-horizontal: 180px;
diff --git a/docs/static/less/bootstrap/wells.less b/docs/static/less/bootstrap/wells.less deleted file mode 100644 index 15d072b..0000000 --- a/docs/static/less/bootstrap/wells.less +++ /dev/null
@@ -1,29 +0,0 @@ -// -// Wells -// -------------------------------------------------- - - -// Base class -.well { - min-height: 20px; - padding: 19px; - margin-bottom: 20px; - background-color: @well-bg; - border: 1px solid @well-border; - border-radius: @border-radius-base; - .box-shadow(inset 0 1px 1px rgba(0,0,0,.05)); - blockquote { - border-color: #ddd; - border-color: rgba(0,0,0,.15); - } -} - -// Sizes -.well-lg { - padding: 24px; - border-radius: @border-radius-large; -} -.well-sm { - padding: 9px; - border-radius: @border-radius-small; -}
diff --git a/docs/static/less/pouchdb/alerts.less b/docs/static/less/pouchdb/alerts.less deleted file mode 100644 index 2e80354..0000000 --- a/docs/static/less/pouchdb/alerts.less +++ /dev/null
@@ -1,44 +0,0 @@ -@import "@{bootstrap}/alerts.less"; - -.alert { .clearfix(); } - -.alert-text { .make-xs-column(10); } - -.alert:before { - float: left; - display: block; - content: ''; - height: @alert-before-size; - width: @alert-before-size; - border-radius: 50%; - border: 1px solid; - font-size: @alert-before-size * .75; - font-family: @font-family-monospace; - text-align: center; - line-height: @alert-before-size; -} - -.alert-info:before { - content: @alert-before-info-text; - border-color: @alert-info-border; - background-color: lighten(@alert-info-bg, 3%); - color: @alert-info-text; -} -.alert-success:before { - content: @alert-before-success-text; - border-color: @alert-success-border; - background-color: lighten(@alert-success-bg, 3%); - color: @alert-success-text; -} -.alert-warning:before { - content: @alert-before-warning-text; - border-color: @alert-warning-border; - background-color: lighten(@alert-warning-bg, 3%); - color: @alert-warning-text; -} -.alert-danger:before { - content: @alert-before-danger-text; - border-color: @alert-danger-border; - background-color: lighten(@alert-danger-bg, 3%); - color: @alert-danger-text; -}
diff --git a/docs/static/less/pouchdb/anchors.less b/docs/static/less/pouchdb/anchors.less deleted file mode 100644 index 57803b0..0000000 --- a/docs/static/less/pouchdb/anchors.less +++ /dev/null
@@ -1,17 +0,0 @@ -.anchor { - &.h1, - &.h2, - &.h3, - &.h4, - &.h5, - &.h6 { - display: inline-block; - text-decoration: none; - } - - &::before { - content: '# '; - opacity: .25; - } - &:focus { outline: none; } -} \ No newline at end of file
diff --git a/docs/static/less/pouchdb/block.less b/docs/static/less/pouchdb/block.less deleted file mode 100644 index 2b734b4..0000000 --- a/docs/static/less/pouchdb/block.less +++ /dev/null
@@ -1,13 +0,0 @@ -.block { - @media (max-width: @screen-md-min) { - > h1, > h2, > h3, > h4, > h5, > h6, - > .h1, > .h2, > .h3, > .h4, > .h5, > .h6, - > p { - text-align: center; - } - > p { - margin: 0 auto; - max-width: 60%; - } - } -} \ No newline at end of file
diff --git a/docs/static/less/pouchdb/buttons.less b/docs/static/less/pouchdb/buttons.less deleted file mode 100644 index d626667..0000000 --- a/docs/static/less/pouchdb/buttons.less +++ /dev/null
@@ -1,29 +0,0 @@ -@import "@{bootstrap}/buttons.less"; - -.btn { - .button-size(@padding-base-vertical; @padding-large-horizontal*2; @font-size-base; @line-height-base; @border-radius-base); -} - -.btn-lg { - .button-size(@padding-large-vertical; @padding-large-horizontal*2; @font-size-large; @line-height-large; @border-radius-large); -} -.btn-sm { - .button-size(@padding-small-vertical; @padding-small-horizontal*2; @font-size-small; @line-height-small; @border-radius-small); -} -.btn-xs { - .button-size(@padding-xs-vertical; @padding-xs-horizontal*2; @font-size-small; @line-height-small; @border-radius-small); -} - -// Social button variants -.btn-github { - .button-variant(@btn-github-color; @btn-github-bg; @btn-github-border); -} -.btn-twitter { - .button-variant(@btn-twitter-color; @btn-twitter-bg; @btn-twitter-border); -} - -@media (max-width: @screen-xs-max) { - .btn { - width: 100%; - } -} \ No newline at end of file
diff --git a/docs/static/less/pouchdb/code.less b/docs/static/less/pouchdb/code.less deleted file mode 100644 index 9452039..0000000 --- a/docs/static/less/pouchdb/code.less +++ /dev/null
@@ -1,6 +0,0 @@ -@import "@{bootstrap}/code.less"; - -pre { - padding-left: @pre-padding; - padding-right: @pre-padding; -}
diff --git a/docs/static/less/pouchdb/header.less b/docs/static/less/pouchdb/header.less deleted file mode 100644 index 529e721..0000000 --- a/docs/static/less/pouchdb/header.less +++ /dev/null
@@ -1,8 +0,0 @@ -header { - overflow-x: hidden; - position: relative; - padding: 25px 0; - border-bottom: 2px solid; - border-color: @header-border-color; - background-color: @header-color; -} \ No newline at end of file
diff --git a/docs/static/less/pouchdb/highlight.less b/docs/static/less/pouchdb/highlight.less deleted file mode 100644 index 5e43004..0000000 --- a/docs/static/less/pouchdb/highlight.less +++ /dev/null
@@ -1,71 +0,0 @@ -.highlight { - pre { - background-color: #3f3f3f; - - border: none; - border-radius: 10px; - } - - code, - pre{ color: #ffffff; } - - .hll { background-color: #3e403d } - .c { color: #75715e } - .err { color: #960050; background-color: #1e0010 } - .k { color: #66d9ef } - .l { color: #ae81ff } - .n { color: #f8f8f2 } - .o { color: #f92672 } - .p { color: #f8f8f2 } - .cm { color: #75715e } - .cp { color: #75715e } - .c1 { color: #75715e } - .cs { color: #75715e } - .ge { font-style: italic } - .gs { font-weight: bold } - .kc { color: #66d9ef } - .kd { color: #66d9ef } - .kn { color: #f92672 } - .kp { color: #66d9ef } - .kr { color: #66d9ef } - .kt { color: #66d9ef } - .ld { color: #e6db74 } - .m { color: #ae81ff } - .s { color: #e6db74 } - .na { color: #a6e22e } - .nb { color: #f8f8f2 } - .nc { color: #a6e22e } - .no { color: #66d9ef } - .nd { color: #a6e22e } - .ni { color: #f8f8f2 } - .ne { color: #a6e22e } - .nf { color: #a6e22e } - .nl { color: #f8f8f2 } - .nn { color: #f8f8f2 } - .nx { color: #6eca97 } - .py { color: #f8f8f2 } - .nt { color: #f92672 } - .nv { color: #f8f8f2 } - .ow { color: #f92672 } - .w { color: #f8f8f2 } - .mf { color: #ae81ff } - .mh { color: #ae81ff } - .mi { color: #ae81ff } - .mo { color: #ae81ff } - .sb { color: #e6db74 } - .sc { color: #e6db74 } - .sd { color: #e6db74 } - .s2 { color: #e6db74 } - .se { color: #ae81ff } - .sh { color: #e6db74 } - .si { color: #e6db74 } - .sx { color: #e6db74 } - .sr { color: #e6db74 } - .s1 { color: #e6db74 } - .ss { color: #e6db74 } - .bp { color: #f8f8f2 } - .vc { color: #f8f8f2 } - .vg { color: #f8f8f2 } - .vi { color: #f8f8f2 } - .il { color: #ae81ff } -}
diff --git a/docs/static/less/pouchdb/icons.less b/docs/static/less/pouchdb/icons.less deleted file mode 100644 index b56aa31..0000000 --- a/docs/static/less/pouchdb/icons.less +++ /dev/null
@@ -1,94 +0,0 @@ -.icon { - margin: 0 auto; - margin-top: @grid-gutter-width; - background-image: url("@{img_dir}/icons.svg"); - background-repeat: no-repeat; - - & ~ * { text-align: center; } - - &-twitter, - &-couchdb, - &-github, - &-travis, - &-leveldb, - &-saucelabs { - opacity: .75; - &:hover { opacity: 1; } - } - - &-node { - background-position: 0; - width: 68px; - height: 73px; - } - - &-light { - background-position: -73px -1px; - width: 92px; - height: 85px; - } - - &-learn { - background-position: -170px 0; - width: 92px; - height: 87px; - } - &-open { - background-position: -267px -5px; - width: 111px; - height: 77px; - } - &-twitter { - background-position: -388px -24px; - width: 46px; - height: 39px; - } - &-couchdb { - background-position: -439px -15px; - width: 90px; - height: 57px; - } - &-github { - background-position: -537px -22px; - width: 45px; - height: 43px; - } - &-travis { - background-position: -589px -20px; - width: 45px; - height: 43px; - } - &-leveldb { - background-position: -640px -20px; - width: 40px; - height: 43px; - } - &-saucelabs { - background-position: -686px -22px; - width: 45px; - height: 43px; - } - - @media (max-width: @screen-sm-min) { - &-node, - &-light, - &-learn, - &-open { - height: 70px; - width: 67px; - background-size: 500px; - + * { margin-top: 0; } - } - &-node { - height: 60px; - width: 50px; - background-position: 0 0; - } - &-light { background-position: -50px 0; } - &-learn { background-position: -117px 0; } - &-open { - background-position: -181px 0; - width: 85px; - } - } -}
diff --git a/docs/static/less/pouchdb/logo.less b/docs/static/less/pouchdb/logo.less deleted file mode 100644 index 892e99f..0000000 --- a/docs/static/less/pouchdb/logo.less +++ /dev/null
@@ -1,49 +0,0 @@ -.logo { - float: left; - width: @logo-width; - .logo-img, - .logo-type { - float: left; - } - .logo-img { - opacity: .9; - height: @logo-img-height; - margin-top: -@logo-img-height*.2; - width: @logo-img-height*@logo-img-ratio; - background-image: url(@logo-img); - background-size: 100%; - } - .logo-type { - margin-left: 8px; - font-size: 3em; - line-height: 1.1; - text-transform: lowercase; - letter-spacing: -1px; - color: @text-color; - } - &:hover .logo-img { opacity: 1; } - .clearfix(); -} -/** - * When we hit the breakpoint - * Center the logo in the middle - **/ -@media (max-width: @navs-breakpoint-justified) { - .logo { - float: none; - display: block; - margin: auto; - } -} -@media (max-width: @logo-breakpoint) { - .logo { - width: auto; - .logo-img { - display: block; - float: none; - margin: auto; - } - .logo-type { display: none; } - } - -}
diff --git a/docs/static/less/pouchdb/mixins.less b/docs/static/less/pouchdb/mixins.less deleted file mode 100644 index 861a24c..0000000 --- a/docs/static/less/pouchdb/mixins.less +++ /dev/null
@@ -1,22 +0,0 @@ -@import "@{bootstrap}/mixins.less"; - -// Intrinsic Ratio Helper -// https://github.com/nickcolley/intrinsic-ratio-less - - -// Intrinsic ratio -.ir(@ratio: 16/9, @width: 100%, @margin: auto) { - position: relative; - margin: @margin; - width: unit(@width, ~'%'); - height: 0; - padding-bottom: unit(@width / @ratio, ~'%'); - > iframe { - position: absolute; - width: 100%; - height: 100%; - border: 0; - } -} - -.iframe-responsive { .ir(); }
diff --git a/docs/static/less/pouchdb/navs.less b/docs/static/less/pouchdb/navs.less deleted file mode 100644 index 336f692..0000000 --- a/docs/static/less/pouchdb/navs.less +++ /dev/null
@@ -1,57 +0,0 @@ -@import "@{bootstrap}/navs.less"; - -.nav-header { - float: right; - > li { min-width: 100px; } -} -.nav-silent { - > li > a { - padding: .1em 0; - color: @text-color; - } -} - -/** - * Sidebar navigation used in learn.html - **/ -.nav-sidebar { - > li.active > a, - > li > a:hover { - color: darken(@brand-primary, 10%); - border-right: 2px solid lighten(@brand-primary, 10%); - padding-right: 10px; - } -} - -@media (max-width: @navs-breakpoint-justified) { - .nav-header { - width: 100%; - > li { - float: none; - display: table-cell; - width: 1%; - min-width: initial; - > a { text-align: center; } - } - } -} - -@media (max-width: @navs-breakpoint-horizontal) { - .nav-header > li:last-child { - float: left; - width: 100%; - } -} - -@media (max-width: @logo-breakpoint) { - .nav-header > li { - float: left; - width: 100%; - } -} - -@media (max-width: @screen-sm-min) { - .nav.nav-sidebar { margin-bottom: 25px; } - .nav-head, - .nav.nav-sidebar { text-align: center; } -}
diff --git a/docs/static/less/pouchdb/post.less b/docs/static/less/pouchdb/post.less deleted file mode 100644 index 9beea5e..0000000 --- a/docs/static/less/pouchdb/post.less +++ /dev/null
@@ -1,5 +0,0 @@ -.post { - margin-top: 10px; - margin-bottom: 40px; - &:last-of-type { margin-bottom: 10px; } -} \ No newline at end of file
diff --git a/docs/static/less/pouchdb/pouchdb.less b/docs/static/less/pouchdb/pouchdb.less deleted file mode 100644 index f05badc..0000000 --- a/docs/static/less/pouchdb/pouchdb.less +++ /dev/null
@@ -1,45 +0,0 @@ -@bootstrap: "../bootstrap"; - -@import "variables.less"; - -// Mixins -@import "mixins.less"; - -// Reset -@import "@{bootstrap}/normalize.less"; -@import "@{bootstrap}/print.less"; -@import "@{bootstrap}/type.less"; - -@import "@{bootstrap}/normalize.less"; -@import "@{bootstrap}/print.less"; -@import "alerts.less"; - -// Core CSS -@import "scaffolding.less"; -@import "code.less"; -@import "@{bootstrap}/grid.less"; -@import "@{bootstrap}/tables.less"; - - -// Components -@import "@{bootstrap}/media.less"; -@import "@{bootstrap}/pagination.less"; -@import "@{bootstrap}/pager.less"; - -// Utility classes -@import "@{bootstrap}/responsive-utilities.less"; - -// PouchDB Overrides -@import "navs.less"; -@import "buttons.less"; -@import "utilities.less"; - -// PouchDB Specific -@import "highlight.less"; -@import "header.less"; -@import "logo.less"; -@import "anchors.less"; -@import "post.less"; -@import "ribbon.less"; -@import "icons.less"; -@import "block.less";
diff --git a/docs/static/less/pouchdb/ribbon.less b/docs/static/less/pouchdb/ribbon.less deleted file mode 100644 index 149734f..0000000 --- a/docs/static/less/pouchdb/ribbon.less +++ /dev/null
@@ -1,14 +0,0 @@ -.ribbon { - z-index: 1; - position: absolute; - top: 0; right: 0; - padding: .1em 3em; - border: 1px solid rgba(0,0,0,.1); - background-color: @gray-lighter; - color: @text-color; - font-weight: bold; - -webkit-transform: translateX(75%) rotate(45deg) translateX(-30%); - transform: translateX(75%) rotate(45deg) translateX(-30%); - -webkit-transform-origin: top left; - transform-origin: top left; -} \ No newline at end of file
diff --git a/docs/static/less/pouchdb/scaffolding.less b/docs/static/less/pouchdb/scaffolding.less deleted file mode 100644 index 366d1c6..0000000 --- a/docs/static/less/pouchdb/scaffolding.less +++ /dev/null
@@ -1,30 +0,0 @@ -@import "@{bootstrap}/scaffolding.less"; - -blockquote { - font-size: 1.1em; - border-left-color: #ddf3e7; - cite { font-size: 1.2em; } -} - -// Temporary fix for Jekyll's P tags all over the place. :/ -p:empty { display: none; } - -.intro, -.infoblocks, -.icons, -.footer { - padding: 20px 0 30px; -} -.page-head { padding: 10px 0 20px; } - -article { padding: 20px 0 75px; } - -.page-head, -.intro, -.blog, -.footer { - background-color: @gray-lighter; -} - -.intro .highlight { margin-top: 2em; } -.icons { border-top: 20px solid @gray-lighter; }
diff --git a/docs/static/less/pouchdb/utilities.less b/docs/static/less/pouchdb/utilities.less deleted file mode 100644 index 77450a8..0000000 --- a/docs/static/less/pouchdb/utilities.less +++ /dev/null
@@ -1,21 +0,0 @@ -@import "@{bootstrap}/utilities.less"; - -.affix { - padding: 1em 0; - position: static; -} - -@media (min-width: @affix-min-width) and (min-height: @affix-min-height) { - - .affix { position: fixed; } - - .affix, - .affix-top { - top: 0; - } - - .affix-top, - .affix-bottom { - position: absolute; - } -}
diff --git a/docs/static/less/pouchdb/variables.less b/docs/static/less/pouchdb/variables.less deleted file mode 100644 index 389ca8a..0000000 --- a/docs/static/less/pouchdb/variables.less +++ /dev/null
@@ -1,69 +0,0 @@ -@import "@{bootstrap}/variables.less"; - -// Base img dir -@img_dir: "../img"; - -// Color -@brand-accent: #fa3649; -@brand-primary: #6ccb99; -@twitter: cornflowerblue; -@github: darkslategray; - -// Social colors -@btn-twitter-color: lighten(@twitter, 25%); -@btn-twitter-bg: @twitter; -@btn-twitter-border: darken(@twitter, 10%); -@btn-github-color: lighten(@github, 50%); -@btn-github-bg: @github; -@btn-github-border: darken(@github, 10%); - -// Scaffolding -@body-bg: #f6f6f6; -@text-color: @gray; - -// Container sizes -@container-large-desktop: ((950px + @grid-gutter-width)); - -// Code -@code-color: darken(@brand-primary, 30%); -@code-bg: lighten(@brand-primary, 30%); - -// Type -@font-family-sans-serif: "Open Sans", Helvetica, Arial, sans-serif; - -@link-color: @brand-accent; -@nav-link-hover-bg: none; - -@headings-font-family: "Lato", Helvetica, Arial, sans-serif; -@header-color: #ffffff; -@header-border-color: #c8c8c8; - -// Logo -@logo-img: '@{img_dir}/mark.svg'; -@logo-fallback-img: '@{img_dir}/mark.png'; -@logo-img-ratio: .78; -@logo-img-height: 70px; -@logo-width: 250px; -// When it gets silly small display only the mark. -@logo-breakpoint: 330px; - -// Navs - -// Switch nav into justified view -@navs-breakpoint-justified: @screen-sm-max; -// Switch nav into horizontal view -@navs-breakpoint-horizontal: 510px; - -// Minimum width and height for fixed sidebars -@affix-min-width: @screen-sm-min; -@affix-min-height: 475px; - -// Alerts -@alert-before-size: 35px; -@alert-before-info-text: 'i'; -@alert-before-success-text: '\2713'; -@alert-before-warning-text: '!'; -@alert-before-danger-text: 'x'; - -// Pre -@pre-padding: 15px;
diff --git a/lib/version-browser.js b/lib/version-browser.js index b8d015e..523fb8e 100644 --- a/lib/version-browser.js +++ b/lib/version-browser.js
@@ -1 +1 @@ -module.exports = "3.1.1-prerelease"; +module.exports = "3.2.0";
diff --git a/package.json b/package.json index ebe16c3..99036c6 100644 --- a/package.json +++ b/package.json
@@ -1,6 +1,6 @@ { "name": "pouchdb", - "version": "3.1.1-prerelease", + "version": "3.2.0", "description": "PouchDB is a pocket-sized database.", "main": "./lib/index.js", "homepage": "http://pouchdb.com/", @@ -108,4 +108,4 @@ "es3ify" ] } -} +} \ No newline at end of file
diff --git a/scripts/baldrick-test.sh b/scripts/baldrick-test.sh deleted file mode 100755 index 87982d0..0000000 --- a/scripts/baldrick-test.sh +++ /dev/null
@@ -1,36 +0,0 @@ -#!/bin/bash -x - -# Run PouchDB test suite, expect a global couchdb command to be installed -# -# Run as: -# -# ./scripts/baldrick-test.sh - -# tmp directory to store CouchDB data files -TMP=./tmp -COUCH_URI_FILE=$TMP/couch.uri - -# Install PouchDB dependancies -npm install - -# Provision a CouchDB instance just for this test -./scripts/start_standalone_couch.sh $TMP > /dev/null 2>&1 & -COUCH_PID=$! - -# Wait for CouchDB to start by polling for the uri file -# Not nasty at all :) -while [ ! -f $COUCH_URI_FILE ] -do - sleep 2 -done -COUCH_HOST=$(cat $COUCH_URI_FILE) - -# Run tests -grunt test --couch-host=$COUCH_HOST -EXIT_STATUS=$? - -# Cleanup -kill $COUCH_PID - -# Make sure we exit with the right status -exit $EXIT_STATUS \ No newline at end of file
diff --git a/scripts/bundle-browserify-test.sh b/scripts/bundle-browserify-test.sh deleted file mode 100755 index 0496e03..0000000 --- a/scripts/bundle-browserify-test.sh +++ /dev/null
@@ -1,7 +0,0 @@ -#!/bin/bash - -echo '<!DOCTYPE html><html>' > test.html -echo "<head><meta charset='utf-8'></head>" >> test.html -echo "<script type=\"text/javascript\">" >> test.html -browserify $1 >> test.html -echo "</script></html>" >> test.html \ No newline at end of file
diff --git a/scripts/jenkins-deploy.sh b/scripts/jenkins-deploy.sh deleted file mode 100644 index 1c93914..0000000 --- a/scripts/jenkins-deploy.sh +++ /dev/null
@@ -1,18 +0,0 @@ -ROOT=$(pwd) - -# Build the docs -cd $ROOT/docs -jekyll - -# Publish docs -cp -R $ROOT/docs/_site/* /home/daleharvey/www/pouchdb.com - -# Build -cd $ROOT -npm install - -grunt -grunt spatial -grunt gql - -cp $ROOT/dist/* /home/daleharvey/www/download.pouchdb.com \ No newline at end of file
diff --git a/scripts/start_standalone_couch.sh b/scripts/start_standalone_couch.sh deleted file mode 100755 index c263954..0000000 --- a/scripts/start_standalone_couch.sh +++ /dev/null
@@ -1,34 +0,0 @@ -#!/bin/bash -e - -# Start a standalone CouchDB, this is a wrapper around the $ couchdb -# command that will create a standalone instance of CouchDB allowing -# you to easily run serveral servers in parallel, each instance starts -# on an ephemeral port and has a dedicated directory for its data and logs -# use the couch.uri file to locate the host -# -# Run as: -# -# $ ./start_standalone_couch.sh ~/data/instanceId - -COUCH_DIR=$1 - -# Make all the directories -mkdir -p $COUCH_DIR/data/views - -# Create a standalone configuration based on the directory -# we are passed in, CouchDB will start on a random port and couch.uri -# will tell us where that is, data is stored within the directory -echo "[httpd] -bind_address = 127.0.0.1 -port = 0 - -[log] -level = debug -file = $COUCH_DIR/couch.log - -[couchdb] -database_dir = $COUCH_DIR/data -view_index_dir = $COUCH_DIR/data/views -uri_file = $COUCH_DIR/couch.uri" > $COUCH_DIR/couch.ini - -couchdb -a $COUCH_DIR/couch.ini \ No newline at end of file
diff --git a/tests/integration/browser.migration.js b/tests/integration/browser.migration.js deleted file mode 100644 index 71871d4..0000000 --- a/tests/integration/browser.migration.js +++ /dev/null
@@ -1,881 +0,0 @@ -/* global PouchDB, PouchDBVersion110, PouchDBVersion200, - PouchDBVersion220, PouchDBVersion306 */ -'use strict'; - -var scenarios = [ - 'PouchDB v1.1.0', - 'PouchDB v2.0.0', - 'PouchDB v2.2.0', - 'PouchDB v3.0.6', - 'websql' -]; - -describe('migration', function () { - - function usingDefaultPreferredAdapters() { - var defaults = ['idb', 'websql']; - return !(PouchDB.preferredAdapters < defaults || - PouchDB.preferredAdapters > defaults); - } - - scenarios.forEach(function (scenario) { - - describe('migrate from ' + scenario, function () { - - var dbs = {}; - var constructors = {}; - var skip = false; - - beforeEach(function (done) { - - if (!usingDefaultPreferredAdapters() || window.msIndexedDB) { - skip = true; - done(); - return; - } - - constructors = { - 'PouchDB v1.1.0': PouchDBVersion110, - 'PouchDB v2.0.0': PouchDBVersion200, - 'PouchDB v2.2.0': PouchDBVersion220, - 'PouchDB v3.0.6': PouchDBVersion306, - PouchDB: PouchDB - }; - - // need actual unique db names for these tests - var localName = testUtils.adapterUrl('local', 'test_migration_local'); - var remoteName = testUtils.adapterUrl('http', 'test_migration_remote'); - - dbs.first = { - pouch : constructors[scenario] || PouchDB, - local : localName, - remote : remoteName, - localOpts : {} - }; - - dbs.second = { - pouch : PouchDB, - local : localName, - remote : remoteName - }; - - if (scenario in PouchDB.adapters) { - dbs.first.localOpts.adapter = scenario; - } - // else scenario might not make sense for this browser, so just use - // same adapter for both - - testUtils.cleanup([dbs.first.local, dbs.second.local], done); - - }); - - afterEach(function (done) { - if (skip) { - done(); - return; - } - testUtils.cleanup([dbs.first.local, dbs.second.local], done); - }); - - var origDocs = [ - {_id: '0', a: 1, b: 1}, - {_id: '3', a: 4, b: 16}, - {_id: '1', a: 2, b: 4}, - {_id: '2', a: 3, b: 9} - ]; - - it('Testing basic migration integrity', function (done) { - if (skip) { return done(); } - var oldPouch = - new dbs.first.pouch(dbs.first.local, dbs.first.localOpts, - function (err) { - should.not.exist(err, 'got error: ' + JSON.stringify(err)); - if (err) { - done(); - } - }); - oldPouch.bulkDocs({docs: origDocs}, function (err, res) { - var removedDoc = {_deleted: true, _rev: res[0].rev, _id: res[0].id}; - oldPouch.remove(removedDoc, function (err, res) { - oldPouch.close(function (err) { - should.not.exist(err, 'got error: ' + JSON.stringify(err)); - var newPouch = new dbs.second.pouch(dbs.second.local); - newPouch.then(function (newPouch) { - return newPouch.allDocs({key: '2'}); - }).then(function (res) { - res.total_rows.should.equal(3); - res.rows.should.have.length(1); - return newPouch.allDocs({key: '0'}); - }).then(function (res) { - res.total_rows.should.equal(3); - res.rows.should.have.length(0); - done(); - }).catch(function (err) { - should.not.exist(err, 'got error: ' + JSON.stringify(err)); - done(); - }); - }); - }); - }); - }); - - it("Test basic replication with migration", function (done) { - if (skip) { return done(); } - var docs = [ - {_id: "0", integer: 0, string: '0'}, - {_id: "1", integer: 1, string: '1'}, - {_id: "2", integer: 2, string: '2'}, - {_id: "3", integer: 3, string: '3', _deleted : true}, - {_id: "4", integer: 4, string: '4', _deleted : true} - ]; - - new dbs.first.pouch(dbs.first.remote, function (err, oldPouch) { - should.not.exist(err, 'got error in constructor: ' + - JSON.stringify(err)); - if (err) { - done(); - } - oldPouch.bulkDocs({docs: docs}, {}, function (err, res) { - should.not.exist(err, 'got error in bulkDocs: ' + - JSON.stringify(err)); - new dbs.first.pouch(dbs.first.local, dbs.first.localOpts, - function (err, oldLocalPouch) { - oldPouch.replicate.to(oldLocalPouch, function (err, result) { - should.not.exist(err, 'got error in replicate: ' + - JSON.stringify(err)); - if (err) { - done(); - } - should.exist(result.ok, 'replication was ok'); - oldPouch.close(function (err) { - should.not.exist(err, 'got error in close: ' + - JSON.stringify(err)); - if (err) { - done(); - } - should.not.exist(err, 'got error: ' + JSON.stringify(err)); - if (err) { - done(); - } - oldLocalPouch.close(function (err) { - should.not.exist(err, 'got error in close: ' + - JSON.stringify(err)); - if (err) { - done(); - } - new dbs.second.pouch(dbs.second.local, - function (err, newPouch) { - should.not.exist(err, 'got error in 2nd constructor: ' + - JSON.stringify(err)); - if (err) { - done(); - } - newPouch.allDocs({}, function (err, res) { - should.not.exist(err, 'got error in allDocs: ' + - JSON.stringify(err)); - res.rows.should.have.length(3, 'unexpected rows: ' + - JSON.stringify(res.rows)); - res.total_rows.should.equal(3); - done(); - }); - }); - }); - }); - }); - }); - }); - }); - }); - - it("Test basic replication with migration + changes()", function (done) { - if (skip) { return done(); } - var docs = [ - {_id: "0", integer: 0, string: '0'}, - {_id: "1", integer: 1, string: '1'}, - {_id: "2", integer: 2, string: '2'}, - {_id: "3", integer: 3, string: '3', _deleted : true}, - {_id: "4", integer: 4, string: '4', _deleted : true} - ]; - - new dbs.first.pouch(dbs.first.remote, function (err, oldPouch) { - should.not.exist(err, 'got error in constructor: ' + - JSON.stringify(err)); - if (err) { - done(); - } - oldPouch.bulkDocs({docs: docs}, {}, function (err, res) { - should.not.exist(err, 'got error in bulkDocs: ' + - JSON.stringify(err)); - new dbs.first.pouch(dbs.first.local, dbs.first.localOpts, - function (err, oldLocalPouch) { - oldPouch.replicate.to(oldLocalPouch, function (err, result) { - should.not.exist(err, 'got error in replicate: ' + - JSON.stringify(err)); - if (err) { - done(); - } - should.exist(result.ok, 'replication was ok'); - oldPouch.close(function (err) { - should.not.exist(err, 'got error in close: ' + - JSON.stringify(err)); - if (err) { - done(); - } - should.not.exist(err, 'got error: ' + JSON.stringify(err)); - if (err) { - done(); - } - oldLocalPouch.close(function (err) { - should.not.exist(err, 'got error in close: ' + - JSON.stringify(err)); - if (err) { - done(); - } - new dbs.second.pouch(dbs.second.local, - function (err, newPouch) { - should.not.exist(err, 'got error in 2nd constructor: ' + - JSON.stringify(err)); - if (err) { - done(); - } - newPouch.changes({include_docs: true}) - .on('complete', function (complete) { - complete.results.should.have.length(5, - 'no _local docs in changes()'); - done(); - }).on('error', done); - }); - }); - }); - }); - }); - }); - }); - }); - - if ((scenario === 'PouchDB v2.2.0' || scenario === 'PouchDB v3.0.6')) { - it("Test persistent views don't require update", function (done) { - if (skip) { return done(); } - var oldPouch = - new dbs.first.pouch(dbs.first.local, dbs.first.localOpts, - function (err) { - should.not.exist(err, 'got error: ' + JSON.stringify(err)); - if (err) { - done(); - } - }); - var docs = origDocs.slice().concat([{ - _id: '_design/myview', - views: { - myview: { - map: function (doc) { - emit(doc.a); - }.toString() - } - } - }]); - var expectedRows = [ - { key: 1, id: '0', value: null }, - { key: 2, id: '1', value: null }, - { key: 3, id: '2', value: null }, - { key: 4, id: '3', value: null } - ]; - oldPouch.bulkDocs({docs: docs}, function (err, res) { - should.not.exist(err, 'bulkDocs'); - oldPouch.query('myview', function (err, res) { - should.not.exist(err, 'query'); - res.rows.should.deep.equal(expectedRows); - oldPouch.close(function (err) { - should.not.exist(err, 'close'); - var newPouch = new dbs.second.pouch(dbs.second.local); - newPouch.then(function (newPouch) { - return newPouch.query('myview', {stale: 'ok'}); - }).then(function (res) { - res.rows.should.deep.equal(expectedRows); - done(); - }).catch(function (err) { - should.not.exist(err, 'catch'); - done(); - }); - }); - }); - }); - }); - - it("Test persistent views don't require update, with a value", - function (done) { - if (skip) { return done(); } - var oldPouch = - new dbs.first.pouch(dbs.first.local, dbs.first.localOpts, - function (err) { - should.not.exist(err, 'got error: ' + JSON.stringify(err)); - if (err) { - done(); - } - }); - var docs = origDocs.slice().concat([{ - _id: '_design/myview', - views: { - myview: { - map: function (doc) { - emit(doc.a, doc.b); - }.toString() - } - } - }]); - var expectedRows = [ - { key: 1, id: '0', value: 1 }, - { key: 2, id: '1', value: 4 }, - { key: 3, id: '2', value: 9 }, - { key: 4, id: '3', value: 16 } - ]; - oldPouch.bulkDocs({docs: docs}, function (err, res) { - should.not.exist(err, 'bulkDocs'); - oldPouch.query('myview', function (err, res) { - should.not.exist(err, 'query'); - res.rows.should.deep.equal(expectedRows); - oldPouch.close(function (err) { - should.not.exist(err, 'close'); - var newPouch = new dbs.second.pouch(dbs.second.local); - newPouch.then(function (newPouch) { - return newPouch.query('myview', {stale: 'ok'}); - }).then(function (res) { - res.rows.should.deep.equal(expectedRows); - done(); - }).catch(function (err) { - should.not.exist(err, 'catch'); - done(); - }); - }); - }); - }); - }); - - it('Returns ok for viewCleanup after modifying view', function (done) { - if (skip) { return done(); } - var oldPouch = - new dbs.first.pouch(dbs.first.local, dbs.first.localOpts, - function (err) { - should.not.exist(err, 'got error: ' + JSON.stringify(err)); - if (err) { - done(); - } - }); - var ddoc = { - _id: '_design/myview', - views: { - myview: { - map: function (doc) { - emit(doc.firstName); - }.toString() - } - } - }; - var doc = { - _id: 'foo', - firstName: 'Foobar', - lastName: 'Bazman' - }; - oldPouch.bulkDocs({docs: [ddoc, doc]}).then(function (info) { - ddoc._rev = info[0].rev; - return oldPouch.query('myview'); - }).then(function (res) { - res.rows.should.deep.equal([ - {id: 'foo', key: 'Foobar', value: null} - ]); - ddoc.views.myview.map = function (doc) { - emit(doc.lastName); - }.toString(); - return oldPouch.put(ddoc); - }).then(function () { - return oldPouch.query('myview'); - }).then(function (res) { - res.rows.should.deep.equal([ - {id: 'foo', key: 'Bazman', value: null} - ]); - return oldPouch.close(); - }).then(function () { - var newPouch = new dbs.second.pouch(dbs.second.local); - newPouch.viewCleanup().then(function () { - done(); - }, done); - }, done); - }); - it('Remembers local docs', function (done) { - if (skip) { return done(); } - var oldPouch = - new dbs.first.pouch(dbs.first.local, dbs.first.localOpts, - function (err) { - should.not.exist(err, 'got error: ' + JSON.stringify(err)); - if (err) { - done(); - } - }); - var docs = [ - { _id: '_local/foo' }, - { _id: '_local/bar' } - ]; - oldPouch.bulkDocs({docs: docs}).then(function () { - return oldPouch.close(); - }).then(function () { - var newPouch = new dbs.second.pouch(dbs.second.local); - newPouch.get('_local/foo').then(function () { - return newPouch.get('_local/bar'); - }).then(function () { - done(); - }, done); - }, done); - }); - - it('Testing migration with weird doc ids', function (done) { - if (skip) { return done(); } - - var origDocs = [ - {_id: 'foo::bar::baz'}, - {_id: '\u0000foo\u0000'} - ]; - - var oldPouch = - new dbs.first.pouch(dbs.first.local, dbs.first.localOpts, - function (err) { - should.not.exist(err, 'got error: ' + JSON.stringify(err)); - if (err) { - done(); - } - }); - oldPouch.bulkDocs({docs: origDocs}, function (err, res) { - should.not.exist(err, 'got error: ' + JSON.stringify(err)); - oldPouch.close(function (err) { - should.not.exist(err, 'got error: ' + JSON.stringify(err)); - var newPouch = new dbs.second.pouch(dbs.second.local); - newPouch.then(function (newPouch) { - return newPouch.allDocs(); - }).then(function (res) { - res.total_rows.should.equal(2); - res.rows.should.have.length(2); - res.rows[1].id.should.equal(origDocs[0]._id); - res.rows[0].id.should.equal(origDocs[1]._id); - done(); - }); - }); - }); - }); - } - - if (scenario === 'PouchDB v3.0.6') { - // attachments didn't really work until this release - it('#2818 Testing attachments with compaction of dups', function () { - if (skip) { return; } - - var docs = [ - { - _id: 'doc1', - _attachments: { - 'att.txt': { - data: 'Zm9vYmFy', // 'foobar' - content_type: 'text/plain' - } - } - }, - { - _id: 'doc2', - _attachments: { - 'att.txt': { - data: 'Zm9vYmFy', // 'foobar' - content_type: 'text/plain' - } - } - } - ]; - - var oldPouch = new dbs.first.pouch( - dbs.first.local, dbs.first.localOpts); - return oldPouch.bulkDocs(docs).then(function () { - return oldPouch.close(); - }).then(function () { - var newPouch = new dbs.second.pouch(dbs.second.local, - {auto_compaction: false}); - return newPouch.get('doc1').then(function (doc1) { - return newPouch.remove(doc1); - }).then(function () { - return newPouch.compact(); - }).then(function () { - return newPouch.get('doc2', {attachments: true}); - }).then(function (doc2) { - doc2._attachments['att.txt'].data.should.equal('Zm9vYmFy'); - }); - }); - }); - - it('#2818 Testing attachments with compaction of dups 2', function () { - if (skip) { return; } - - var docs = [ - { - _id: 'doc1', - _attachments: { - 'att.txt': { - data: 'Zm9vYmFy', // 'foobar' - content_type: 'text/plain' - } - } - } - ]; - - var oldPouch = new dbs.first.pouch( - dbs.first.local, dbs.first.localOpts); - return oldPouch.bulkDocs(docs).then(function () { - return oldPouch.close(); - }).then(function () { - var newPouch = new dbs.second.pouch(dbs.second.local, - {auto_compaction: false}); - return newPouch.put({ - _id: 'doc2', - _attachments: { - 'att.txt': { - data: 'Zm9vYmFy', // 'foobar' - content_type: 'text/plain' - } - } - }).then(function () { - return newPouch.get('doc2'); - }).then(function (doc2) { - return newPouch.remove(doc2); - }).then(function () { - return newPouch.compact(); - }).then(function () { - return newPouch.get('doc1', {attachments: true}); - }).then(function (doc1) { - doc1._attachments['att.txt'].data.should.equal('Zm9vYmFy'); - }); - }); - }); - - it('#2818 Testing attachments with compaction of dups 3', function () { - if (skip) { return; } - - var docs = [ - { - _id: 'doc1', - _attachments: { - 'att.txt': { - data: 'Zm9vYmFy', // 'foobar' - content_type: 'text/plain' - } - } - }, - { - _id: 'doc_deleted', - _deleted: true - }, - { - _id: 'doc_no_attachments' - } - ]; - - for (var i = 0; i < 25; i++) { - // test paging in the migration - docs.push({ - _id: 'some_other_doc_' + i - }); - } - - var oldPouch = new dbs.first.pouch( - dbs.first.local, dbs.first.localOpts); - return oldPouch.bulkDocs(docs).then(function () { - return oldPouch.close(); - }).then(function () { - var newPouch = new dbs.second.pouch(dbs.second.local, - {auto_compaction: false}); - return newPouch.put({ - _id: 'doc2', - _attachments: { - 'att.txt': { - data: 'Zm9vYmFy', // 'foobar' - content_type: 'text/plain' - } - } - }).then(function () { - return newPouch.get('doc2'); - }).then(function (doc2) { - return newPouch.remove(doc2); - }).then(function () { - return newPouch.compact(); - }).then(function () { - return newPouch.get('doc1', {attachments: true}); - }).then(function (doc1) { - doc1._attachments['att.txt'].data.should.equal('Zm9vYmFy'); - }); - }); - }); - - it('#2818 Testing attachments with compaction of dups 4', function () { - if (skip) { return; } - - var docs = [ - { - _id: 'doc1', - _attachments: { - 'att.txt': { - data: 'Zm9vYmFy', // 'foobar' - content_type: 'text/plain' - }, - 'att2.txt': { - data: 'Zm9vYmFy', // 'foobar' - content_type: 'text/plain' - }, - 'att3.txt': { - data: 'Zm9v', // 'foo' - content_type: 'text/plain' - } - } - } - ]; - - var oldPouch = new dbs.first.pouch( - dbs.first.local, dbs.first.localOpts); - return oldPouch.bulkDocs(docs).then(function () { - return oldPouch.close(); - }).then(function () { - var newPouch = new dbs.second.pouch(dbs.second.local, - {auto_compaction: false}); - return newPouch.put({ - _id: 'doc2', - _attachments: { - 'att.txt': { - data: 'Zm9vYmFy', // 'foobar' - content_type: 'text/plain' - } - } - }).then(function () { - return newPouch.get('doc2'); - }).then(function (doc2) { - return newPouch.remove(doc2); - }).then(function () { - return newPouch.compact(); - }).then(function () { - return newPouch.get('doc1', {attachments: true}); - }).then(function (doc1) { - doc1._attachments['att.txt'].data.should.equal('Zm9vYmFy'); - doc1._attachments['att2.txt'].data.should.equal('Zm9vYmFy'); - doc1._attachments['att3.txt'].data.should.equal('Zm9v'); - }); - }); - }); - - it('#2818 Testing attachments with compaction of dups 5', function () { - if (skip) { return; } - - var docs = [ - { - _id: 'doc1', - _attachments: { - 'att.txt': { - data: 'Zm9vYmFy', // 'foobar' - content_type: 'text/plain' - }, - 'att2.txt': { - data: 'Zm9vYmFy', // 'foobar' - content_type: 'text/plain' - }, - 'att3.txt': { - data: 'Zm9v', // 'foo' - content_type: 'text/plain' - } - } - }, { - _id: 'doc3', - _attachments: { - 'att-a.txt': { - data: 'Zm9vYmFy', // 'foobar' - content_type: 'text/plain' - }, - 'att-b.txt': { - data: 'Zm9v', // 'foo' - content_type: 'text/plain' - }, - 'att-c.txt': { - data: 'YmFy', // 'bar' - content_type: 'text/plain' - } - } - } - ]; - - var oldPouch = new dbs.first.pouch( - dbs.first.local, dbs.first.localOpts); - return oldPouch.bulkDocs(docs).then(function () { - return oldPouch.close(); - }).then(function () { - var newPouch = new dbs.second.pouch(dbs.second.local, - {auto_compaction: false}); - return newPouch.put({ - _id: 'doc2', - _attachments: { - 'att.txt': { - data: 'YmFy', // 'bar' - content_type: 'text/plain' - } - } - }).then(function () { - return newPouch.get('doc2'); - }).then(function (doc2) { - return newPouch.remove(doc2); - }).then(function () { - return newPouch.compact(); - }).then(function () { - return newPouch.get('doc1', {attachments: true}); - }).then(function (doc1) { - doc1._attachments['att.txt'].data.should.equal('Zm9vYmFy'); - doc1._attachments['att2.txt'].data.should.equal('Zm9vYmFy'); - doc1._attachments['att3.txt'].data.should.equal('Zm9v'); - return newPouch.get('doc3', {attachments: true}); - }).then(function (doc3) { - doc3._attachments['att-a.txt'].data.should.equal('Zm9vYmFy'); - doc3._attachments['att-b.txt'].data.should.equal('Zm9v'); - doc3._attachments['att-c.txt'].data.should.equal('YmFy'); - }); - }); - }); - - it('#2818 Testing attachments with compaction of dups 6', function () { - if (skip) { return; } - - var docs = []; - - for (var i = 0; i < 40; i++) { - docs.push({ - _id: 'doc' + i, - _attachments: { - 'att.txt' : { - data: PouchDB.utils.btoa(Math.random().toString()), - content_type: 'text/plain' - } - } - }); - } - docs.push({ - _id: 'doc_a', - _attachments: { - 'att.txt': { - data: 'Zm9vYmFy', // 'foobar' - content_type: 'text/plain' - }, - 'att2.txt': { - data: 'Zm9vYmFy', // 'foobar' - content_type: 'text/plain' - }, - 'att3.txt': { - data: 'Zm9v', // 'foo' - content_type: 'text/plain' - } - } - }); - var oldPouch = new dbs.first.pouch( - dbs.first.local, dbs.first.localOpts); - return oldPouch.bulkDocs(docs).then(function () { - return oldPouch.close(); - }).then(function () { - var newPouch = new dbs.second.pouch(dbs.second.local, - {auto_compaction: false}); - return newPouch.put({ - _id: 'doc_b', - _attachments: { - 'att.txt': { - data: 'Zm9v', // 'foo' - content_type: 'text/plain' - } - } - }).then(function () { - return newPouch.get('doc_b'); - }).then(function (doc) { - return newPouch.remove(doc); - }).then(function () { - return newPouch.compact(); - }).then(function () { - return newPouch.get('doc_a', {attachments: true}); - }).then(function (doc) { - doc._attachments['att.txt'].data.should.equal('Zm9vYmFy'); - doc._attachments['att2.txt'].data.should.equal('Zm9vYmFy'); - doc._attachments['att3.txt'].data.should.equal('Zm9v'); - }); - }); - }); - - it('#2818 compaction of atts after many revs', function () { - if (skip) { return; } - - var oldPouch = new dbs.first.pouch( - dbs.first.local, dbs.first.localOpts); - - return oldPouch.put({_id: 'foo'}).then(function (res) { - return oldPouch.putAttachment('foo', 'att', res.rev, 'Zm9v', - 'text/plain'); - }).then(function () { - return oldPouch.get('foo', {attachments: true}); - }).then(function (doc) { - doc._attachments['att'].content_type.should.equal('text/plain'); - should.exist(doc._attachments['att'].data); - return oldPouch.get('foo'); - }).then(function (doc) { - return oldPouch.put(doc); - }).then(function () { - var newPouch = new dbs.second.pouch(dbs.second.local, - {auto_compaction: false}); - return newPouch.compact().then(function () { - return newPouch.get('foo', {attachments: true}); - }).then(function (doc) { - doc._attachments['att'].content_type.should.equal('text/plain'); - doc._attachments['att'].data.length.should.be.above(0, - 'attachment exists'); - }); - }); - }); - - it('#2890 PNG content after migration', function () { - if (skip) { return; } - - var oldPouch = new dbs.first.pouch( - dbs.first.local, dbs.first.localOpts); - - var transparent1x1Png = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HA' + - 'wCAAAAC0lEQVR4nGP6zwAAAgcBApocMXEA' + - 'AAAASUVORK5CYII='; - var black1x1Png = - 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAACkl' + - 'EQVR4nGNiAAAABgADNjd8qAAA' + - 'AABJRU5ErkJggg=='; - - return oldPouch.put({_id: 'foo'}).then(function (res) { - return oldPouch.putAttachment('foo', 'att', res.rev, - transparent1x1Png, 'image/png'); - }).then(function () { - return oldPouch.get('foo', {attachments: true}); - }).then(function (doc) { - doc._attachments['att'].content_type.should.equal('image/png'); - should.exist(doc._attachments['att'].data); - return oldPouch.get('foo'); - }).then(function (doc) { - return oldPouch.put(doc); - }).then(function () { - var newPouch = new dbs.second.pouch(dbs.second.local, - {auto_compaction: false}); - return newPouch.compact().then(function () { - return newPouch.get('foo', {attachments: true}); - }).then(function (doc) { - doc._attachments['att'].content_type.should.equal('image/png'); - doc._attachments['att'].data.should.equal(transparent1x1Png); - return newPouch.putAttachment('bar', 'att', null, - black1x1Png, 'image/png'); - }).then(function () { - return newPouch.get('bar', {attachments: true}); - }).then(function (doc) { - doc._attachments['att'].content_type.should.equal('image/png'); - doc._attachments['att'].data.should.equal(black1x1Png); - }); - }); - }); - } - }); - }); -});
diff --git a/tests/integration/browser.worker.js b/tests/integration/browser.worker.js deleted file mode 100644 index 7d38006..0000000 --- a/tests/integration/browser.worker.js +++ /dev/null
@@ -1,87 +0,0 @@ -'use strict'; - -var sourceFile = window.location.search.match(/[?&]sourceFile=([^&]+)/); - -if (!sourceFile) { - sourceFile = '../../dist/pouchdb.js'; -} else { - sourceFile = '../../dist/' + sourceFile[1]; -} - -if (typeof window.Worker === 'function') { - runTests(); -} - -function runTests() { - - describe('browser.worker.js', function () { - - var dbs = {}; - - beforeEach(function (done) { - dbs.name = testUtils.adapterUrl('local', 'testdb'); - dbs.remote = testUtils.adapterUrl('http', 'test_repl_remote'); - testUtils.cleanup([dbs.name, dbs.remote], done); - }); - - after(function (done) { - testUtils.cleanup([dbs.name, dbs.remote], done); - }); - - it('create it', function (done) { - var worker = new Worker('worker.js'); - worker.addEventListener('message', function (e) { - e.data.should.equal('pong'); - worker.terminate(); - done(); - }); - worker.postMessage(sourceFile); - worker.postMessage('ping'); - }); - - it('check pouch version', function (done) { - var worker = new Worker('worker.js'); - worker.addEventListener('message', function (e) { - PouchDB.version.should.equal(e.data); - worker.terminate(); - done(); - }); - worker.postMessage(sourceFile); - worker.postMessage('version'); - }); - - it('create remote db', function (done) { - var worker = new Worker('worker.js'); - worker.addEventListener('error', function (e) { - throw e; - }); - worker.addEventListener('message', function (e) { - e.data.should.equal('lala'); - worker.terminate(); - done(); - }); - worker.postMessage(sourceFile); - worker.postMessage(['create', dbs.remote]); - }); - - - // Mozilla bug: https://bugzilla.mozilla.org/show_bug.cgi?id=701634 - // IE bug: https://connect.microsoft.com/IE/feedback/details/866495 - if (!('mozIndexedDB' in window || 'msIndexedDB' in window)) { - it('create local db', function (done) { - var worker = new Worker('worker.js'); - worker.addEventListener('error', function (e) { - throw e; - }); - worker.addEventListener('message', function (e) { - e.data.should.equal('lala'); - worker.terminate(); - done(); - }); - worker.postMessage(sourceFile); - worker.postMessage(['create', dbs.name]); - }); - } - - }); -}
diff --git a/tests/integration/cordova/.cordova/config.json b/tests/integration/cordova/.cordova/config.json deleted file mode 100644 index 33fd5c2..0000000 --- a/tests/integration/cordova/.cordova/config.json +++ /dev/null
@@ -1,4 +0,0 @@ -{ - "id": "com.pouchdb.tests", - "name": "PouchDB Test Runner" -} \ No newline at end of file
diff --git a/tests/integration/cordova/config.xml b/tests/integration/cordova/config.xml deleted file mode 100644 index a7027d9..0000000 --- a/tests/integration/cordova/config.xml +++ /dev/null
@@ -1,12 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<widget id="com.pouchdb.tests" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0"> - <name>PouchDB Test Runner</name> - <description> - Runs the unit tests suite for the PouchDB project on Cordova. - </description> - <author email="daleharvey@arandomurl.com" href="http://pouchdb.com"> - The PouchDB Team - </author> - <content src="tests/integration/index.html" /> - <access origin="*" /> -</widget>
diff --git a/tests/integration/cordova/merges/firefoxos/icons/icon-128x128.png b/tests/integration/cordova/merges/firefoxos/icons/icon-128x128.png deleted file mode 100644 index 8973954..0000000 --- a/tests/integration/cordova/merges/firefoxos/icons/icon-128x128.png +++ /dev/null Binary files differ
diff --git a/tests/integration/cordova/merges/firefoxos/icons/icon-60x60.png b/tests/integration/cordova/merges/firefoxos/icons/icon-60x60.png deleted file mode 100644 index 5adb4a6..0000000 --- a/tests/integration/cordova/merges/firefoxos/icons/icon-60x60.png +++ /dev/null Binary files differ
diff --git a/tests/integration/cordova/merges/firefoxos/manifest.webapp b/tests/integration/cordova/merges/firefoxos/manifest.webapp deleted file mode 100644 index a230a9a..0000000 --- a/tests/integration/cordova/merges/firefoxos/manifest.webapp +++ /dev/null
@@ -1,18 +0,0 @@ -{ - "launch_path": "/tests/integration/index.html", - "installs_allowed_from": [ - "*" - ], - "version": "0.0.1", - "name": "PouchDB Test Runner", - "pkgName": "com.pouchdb.tests", - "description": "Runs the unit tests suite for the PouchDB project on Cordova.", - "developer": { - "name": "The PouchDB Team", - "url": "http://pouchdb.com" - }, - "icons": { - "128": "./icons/icon-128x128.png", - "60": "./icons/icon-60x60.png" - } -}
diff --git a/tests/integration/cordova/platforms/.gitignore b/tests/integration/cordova/platforms/.gitignore deleted file mode 100644 index 5e7d273..0000000 --- a/tests/integration/cordova/platforms/.gitignore +++ /dev/null
@@ -1,4 +0,0 @@ -# Ignore everything in this directory -* -# Except this file -!.gitignore
diff --git a/tests/integration/cordova/plugins/.gitignore b/tests/integration/cordova/plugins/.gitignore deleted file mode 100644 index 5e7d273..0000000 --- a/tests/integration/cordova/plugins/.gitignore +++ /dev/null
@@ -1,4 +0,0 @@ -# Ignore everything in this directory -* -# Except this file -!.gitignore
diff --git a/tests/integration/deps/bigimage.js b/tests/integration/deps/bigimage.js deleted file mode 100644 index 16cc623..0000000 --- a/tests/integration/deps/bigimage.js +++ /dev/null
@@ -1,12 +0,0 @@ -(function () { - 'use strict'; - - var bigimage = "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yza2iXhidiYKdrPxJO9Y9+6JeBqzm8xE955Yimv8IbsoWUeRbqxd/w+/397yd3e0D/3u2WHPLMKP9xTHnOJqt213fb695Sd2tz//q0+3n1v99fajF76+/drZn2n/7XuPaPfd+YX2ln97Xbv4b/6+XfS0o9ttH/+19r0//+X2kStvac/efH/73R9+SXvZ2za2L//3723Lo9rH+5PHZ1a0733zb7XT/uS17bXv/mz7V+cd3w6Z/ad22Ze/0v5lFApj2u3euyLuT+1pf/6BT7f/uOqG9r+/6HXtV8/+XPvv37Oq/dG//3/aay/5cnvzRZuj8AhGMeeE0frTX9ne8wvnt/93z8+1d73xOfFakjvaW579g+22/+OP2q3v+8529+cvbs985TPb5igYX7hxd/vG59/dfuS+n2ifufKadtzmw3sYtbZu75faT7/zgvaxK69tk199T3vea1/cvuPZ32wvWf6p9oxXvKm978pb20Xrb2o/evbL2weec3175Zt/s532/72uve7dn27/+vwT2rrlz28/c+4H2hde8o72p2++oG1YvrX97Atf147+7b9r215xWPujH7mgveX9z2m//YNntL0P3dp+/z/9VnvLH3+s3fD2KCTHhZvilwvkU1yTN/30G9vH/uZv2lWXXdGWx1PFeyKfd2/fG/I3t//26/+1HXfiye2TH//b9tb/9Nb2X3/9v7Xbb9vaPvl3H28/9aafiXcOz7b/+eH/GQs2vjjGdX8g3kN8y423tnPPf1aLRdO+efft7Zgjjom1GeuFLOOJ7JxHkWvxBon23POfGzk+0b7whc93tegLX/CC9qxnP6ftjsI1frwvO9x6eRT9yOk9e2bb2c84u1119VXdP31x7fDLla1bt7ZN8S8TKJXzWhSeOp7klyzxBDsl2Ol40phfrozxPmbWXIwxHpjEiHFKe2MtTMaTyPwSIgq04dutGV6xwg0tjul47/POXXtifW/pXmnBP72huYbdY6DsPewTrF0O9w/slWVfZAutf26o7A3ZH5lydeLBHDiIS8POfQUZfSg2Nnjj6cs5wKtTbgzlxvI8ieP+i03e1+y7j2Zf/NB7Hs5HylzxE1vk+NucLzLHd/8nLs3x4fHnQMaBX54XOovD2Of933HxE1vOk35d/7r+5ih54rogh+j3c4d+rf/Y/efWYq3/+X2Z3AAX93jzB5lydeKW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1+tFawJyD08m9hs6NWlbTCQBEiABEiABEiABEiABEiABuwRUdPzlhKPsZmc+EiABEiCBdiZAdxbtDJTVkUC6Ejh8p+nIzsxK2D2XDVcWZuHWFtg7cPi+ZlZuSYAESIAESIAESIAESIAESIAESIAESIAEOjkBisidfALZfRJIhcDeO+yZMLvDaf/nQF1aJAo9swsxuvcOiZIZTwIkQAIkQAIkQAIkQAIkQAIkQAIkQAIk0MkI2FeNOtnA2F0SIIGWBHYvmYje+b1aJkiMA/YWzIsUju8T+ZgxMyNZOnIv6LPU7vFYDnlAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiTQTgToE7mdQLIaEugsBA4ffTCe+PhZY0Vcs88ul1Mk5PiisJkndhuQlXWdMdbLgwsHoyAzNzZrhxzvfNIteOrYpnDdGRkZ4X3ukAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJtB8BWiK3H0vWRAKdgsDgggEYVjzU0leH02U5tnMQ69LC6XDiuLEz7BRttzwqHJufdquUFZEACZAACZAACZAACZAACZAACZAACZAACVgIUES24OABCXQPAoePPgiuKOHY4UjVlQXEktnKatKACdYIHpEACZAACZAACZAACZAACZAACZAACZAACXQJAhSRu8Q0chAkkBqBwsw8TCgZZxRyuMQbcjA1VxaR1kJKcg9PJvYbOjUSzT0SIAESIAESIAESIAESIAESIAESIAESIIEuQ4AicpeZSg6EBFIjcPhO0+Fxe+ASNxRtDT6f3yh64PB921oFy5EACZAACZAACZAACZAACZAACZAACZAACaQ5gbarR2k+MHaPBEigdQIHjNwHjpjF8VovFckRCATRK7cXRvfeIRLJPRIgARIgARIgARIgARIgARIgARIgARIggS5FwN2lRsPBkEA3JfC3r+fhhJ2PSHn0u5dMhH62R1i26UfU+7ZgYt/R26N5tkkCJEACJEACJEACJEACJEACJEACJEACJGCTAEVkm6CYjQTSmUBbBOTtPZ6RvYZt7y6wfRIgARIgARIgARIgARIgARIgARIgARIgARsE6M7CBiRmIQESIAESIAESIAESIAESIAESIAESIAESIAESIIHuSoAicnedeY6bBEiABEiABEiABEiABEiABEiABEiABEiABEiABGwQoIhsAxKzkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkEB3JUARubvOPMdNAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAjYIUES2AYlZSIAESIAESIAESIAESIAESIAESIAESIAESIAESKC7EqCI3F1nnuMmARIgARIgARIgARIgARIgARIgARIgARIgARIgARsEKCLbgMQsJEACJEACJEACJEACJEACJEACJEACJEACJEACJNBdCVBE7q4zz3GTAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQgA0CFJFtQGIWEiABEiABEiABEiABEiABEiABEiABEiABEiABEuiuBCgid9eZ57hJgARIgARIgARIgARIgARIgARIgARIgARIgARIwAYBisg2IDELCZAACZAACZAACZAACZAACZAACZAACZAACZAACXRXAhSRu+vMc9wkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkYIMARWQbkJiFBEiABEiABEiABEiABEiABEiABEiABEiABEiABLorAYrI3XXmOW4SIAESIAESIAESIAESIAESIAESIAESIAESIAESsEGAIrINSMxCAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAt2VAEXk7jrzHDcJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJ2CBAEdkGJGYhARIgARIgARIgARIgARIgARIgARIgARIgARIgge5KgCJyd515jpsESIAESIAESIAESIAESIAESIAESIAESIAESIAEbBCgiGwDErOQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQQHclQBG5u848x00CJEACJEACJEACJEACJEACJEACJEACJEACJEACNghQRLYBiVlIgARIgARIgARIgARIgARIgARIgARIgARIgARIoLsSoIjcXWee4yYBEiABEiABEiABEiABEiABEiABEiABEiABEiABGwQoItuAxCwkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIk0F0JUETurjPPcZMACZAACZAACZAACZAACZAACZAACZAACZAACZCADQJuG3k6fZZFixZ1+jFwACRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiSwPQjQEnl7UGebJEACJEACJEACJEACJEACJEACJEACJEACJEACJNBJCHQLS+SRI0d2kulgN0mABEiABEiABEiABEiABEiABEiABEiABEiABEggvQjQEjm95oO9IQESIAESIAESIAESIAESIAESIAESIAESIAESIIG0IkAROa2mg50hARIgARIgARIgARIgARIgARIgARIgARIgARIggfQiQBE5veaDvSEBEiABEiABbRCEcwAAIABJREFUEiABEiABEiABEiABEiABEiABEiCBtCJAETmtpoOdIQESIAESIAESIAESIAESIAESIAESIAESIAESIIH0IkAROb3mg70hARIgARIgARIgARIgARIgARIgARIgARIgARIggbQiQBE5raaDnSEBEiABEiABEiABEiABEiABEiABEiABEiABEiCB9CJAETm95oO9IQESIAESIAESIAESIAESIAESIAESIAESIAESIIG0IkAROa2mg50hARIgARIgARIgARIgARIgARIgARIgARIgARIggfQiQBE5veaDvSEBEiABEiABEiABEiABEiABEiABEiABEiABEiCBtCJAETmtpoOdIQESIAESIAESIAESIAESIAESIAESIAESIAESIIH0IkAROb3mg70hARIgARIgARIgARIgARIgARIgARIgARIgARIggbQiQBE5raaDnSEBEiABEiABEiABEiABEiABEiABEiABEiABEiCB9CJAETm95oO9IQESIAESIAESIAESIAESIAESIAESIAESIAESIIG0IkAROa2mg50hARIgARIgARIgARIgARIgARIgARIgARIgARIggfQiQBE5veaDvSEBEiABEiABEiABEiABEiABEiABEiABEiABEiCBtCJAETmtpoOdIQESIAESIAESIAESIAESIAESIAESIAESIAESIIH0IkAROb3mg70hARIgARIgARIgARIgARIgARIgARIgARIgARIggbQiQBE5raaDnSEBEiABEiABEiABEiABEiABEiABEiABEiABEiCB9CJAETm95oO9IQESIAESIAESIAESIAESIAESIAESIAESIAESIIG0IkAROa2mg50hARIgARIgARIgARIgARIgARIgARIgARIgARIggfQiQBE5veaDvSEBEiABEiABEiABEiABEiABEiABEiABEiABEiCBtCJAETmtpoOdIQESIAESIAESIAESIAESIAESIAESIAESIAESIIH0IkAROb3mg70hARIgARIgARIgARIgARIgARIgARIgARIgARIggbQiQBE5raaDnSEBEiABEiABEiABEiABEiABEiABEiABEiABEiCB9CJAETm95oO9IQESIAESIAESIAESIAESIAESIAESIAESIAESIIG0IkAROa2mg50hARIgARIgARIgARIgARIgARIgARIgARIgARIggfQiQBE5veaDvSEBEiABEiABEiABEiABEiABEiABEiABEiABEiCBtCJAETmtpoOdIQESIAESIAESIAESIAESIAESIAESIAESIAESIIH0IkAROb3mg70hARIgARIgARIgARIgARIgARIgARIgARIgARIggbQiQBE5raaDnSEBEiABEiABEiABEiABEiABEiABEiABEiABEiCB9CJAETm95oO9IQESIAESIAESIAESIAESIAESIAESIAESIAESIIG0IkAROa2mg50hARIgARIgARIgARIgARIgARIgARIgARIgARIggfQiQBE5veaDvSEBEiABEiABEiABEiABEiABEiABEiABEiABEiCBtCJAETmtpoOdIQESIAESIAESIAESIAESIAESIAESIAESIAESIIH0IuBOr+6wNyRAAiRAAiTQ+Ql4vd7mQXjg8XT+8XAE6UkgKOeZzzzTeKK1yyTxu9suGDu8Es5ThyNmAyRAAiRAAv/P3nkAOFFtb/xL3V7oSxVQpAoqAiJFRAUsWBGx9+7zj71XbKiABZ/6bE99IopdVBCl96L0pQnILrBLWbaXJJv8z51s6ia7STZbgG/eG2fmzi3n/u7NLPnm5FwSIAESqESAInIlJEwggSOIgOUg0jdmoFw+6eWIQ+cenREbQfeK8rKwa8sObNy+HeWmJjBYD8KQ0hqdOhyLjh3bIo4iWQRUIyjiyMe8L6bhj03/IKVZN1x07eU4NkUXQUUNs0jhgUxsWLNC5lkGCkrERl0cmnfqhfOH90XiYdTNzb++jInf73BDvujhCTinY6L7mickEBUCZVvw+P9NxEGHQ6uuxVlj8dxlXaNSdYOvpJaehenfjsPrMzO17jv0zfHIa8+hY0LtPXwKs3Zgd56lStw6eTmQkpyM5JSm/FtbQSrq4+Qoxu6tmSis+CxVOSBy0xyfgmQZkyYp8dVlrXw/5LZMSEiRcU+OR3J8BO1UbpkpJEACJEACJEACJFBjAhSRa4yQFZBAwyTgKNqBtx99BevK7E4D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gARIgARIgARIgASCEqCIHBQNb5AACZAACZAACZAACZAACZAACZAACZAACZAACZAACVBE5hwgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIISoAiclA0vEECJEACJEACJEACJEACJEACJEACJEACJEACJEACJEARmXOABEiABEiABEiABEiABEiABEiABEiABEiABEiABEggKAGKyEHR8AYJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkABFZM4BEiABEiABEiABEiABEiABEiABEiABEiABEiABEiCBoAQoIgdFwxskQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIUkTkHSIAESIAESIAESIAESIAESIAESIAESIAESIAESIAEghKgiBwUDW+QAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAlQROYcIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESCEqAInJQNLxBAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAEZlzgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIICgBishB0fAGCZAACZAACZAACZAACZAACZAACZAACZAACZAACZAARWTOARIgARIgARIgARIgARIgARIgARIgARIgARIgARIggaAEKCIHRcMbJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACFJE5B0iABEiABEiABEiABEiABEiABEiABEiABEiABEiABIISoIgcFA1vkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJUETmHCABEiABEiABEiABEiABEiABEiABEiABEiABEiABEghKgCJyUDS8QQIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQBGZc4AESIAESIAESIAESIAESIAESIAESIAESIAESIAESCAoAYrIQdHwBgmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAEVkzgESIAESIAESIAESIAESIAESIAESIAESIAESIAESIIGgBCgiB0XDGyRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAsajAUFsbOzR0E32kQRIgARIgARIgARIgARIgARIgARIgARIgARIgASiToCeyFFHygpJgARIgARIgARIgARIgARIgARIgARIgARIgARI4MghQBH5yBlL9oQESIAESIAESIAESIAESIAESIAESIAESIAESIAEok6AInLUkbJCEiABEiABEiABEiABEiABEiABEiABEiABEiABEjhyCFBEPnLGkj0hARIgARIgARIgARIgARIgARIgARIgARIgARIggagToIgcdaSskARIgARIgARIgARIgARIgARIgARIgARIgARIgASOHAIUkY+csWRPSIAESIAESIAESIAESIAESIAESIAESIAESIAESCDqBCgiRx0pKyQBEiABEiABEiABEiABEiABEiABEiABEiABEiCBI4cAReQjZyzZExIgARIgARIgARIgARIgARIgARIgARIgARIgARKIOgGKyFFHygpJgARIgARIgARIgARIgARIgARIgARIgARIgARI4MghQBH5yBlL9oQESIAESIAESIAESIAESIAESIAESIAESIAESIAEok6AInLUkbJCEiABEiABEiABEiABEiABEiABEiABEiABEiABEjhyCFBEPnLGkj0hARIgARIgARIgARIgARIgARIgARIgARIgARIggagToIgcdaSskARIgARIgARIgARIgARIgARIgARIgARIgARIgASOHAIUkY+csWRPSIAESIAESIAESIAESIAESIAESIAESIAESIAESCDqBCgiRx0pKyQBEiABEiABEiABEiABEiABEiABEiABEiABEiCBI4cAReQjZyzZExIgARIgARIgARIgARIgARIgARIgARIgARIgARKIOgGKyFFHygpJgARIgARIgARIgARIgARIgARIgARIgARIgARI4MghQBH5yBlL9oQESIAESIAESIAESIAESIAESIAESIAESIAESIAEok6AInLUkbJCEiABEiABEiABEiABEiABEiABEiABEiABEiABEjhyCBiPnK6wJyRAAiRweBDYtSsDu/fsQXr6ZuQeygUcdixavFQ7Hso9JOmb4HDo0KNHdyQnJcFkMqJv3z7Q6XRISU1G9+7d0KpVK7Rr1+7w6DCtJAESIAESIAESIAESIAESIAESIAESOKwJUEQ+rIePxpMACRwuBNavX49pX3+HJUuXY/OmzbA7IKKwHjqHQwRju5w7UGaxip5sg9Eoj2a5t1HyodwOk1mPZctFZIYO5eXlmpis+t21axec1v80XHLpRTjhhBMOFxS0kwRIgARIgARIgARIgARIgARIgARI4DAjQBH5MBswmksCJHB4EMjNzcXSpcswc9Ys2X9HQV4hHNDDLuqxEokddruIx5Ki1yk1WTqlF7FYB6tV5xSVJbdO/qfuqTImKaNTeSVNlVPHjRs3yb4F773/ARqlpmDEsGEYPmIY+vbri9TU1MMDFK0kARIgARIgARIgARIgARIgARIgARJo8AQoIjf4IaKBJEAChxuBSRMm4v33P0ZufoHShjUh2KA3ifgrlyIEG2TX6QyaGGww6LV0cUaWcBZyX4nG5arH4pFsMIlwrNfy25XgbFeiskG8l+2w2sRrGeLBLPXrpI5D+YX45tvvMW3aN0hKSsQtt9yEsfeNVRVxIwESIAESIAESIAESIAESIAESIAESIIEaEeDCejXCx8IkQAIk4CHw5dQv0KdPH7w26Q0UFhVrHsdGvVHEXwP0EuNYL0JwudUKW7lNK2TQi5CshGDlYCyb0zNZicYGEZDNIjgbYDAaJPSFyqDyyiNbhb4QYVmFwLDLXu4od4rQUrcSmqUQcvPyMUFsGHjaIEz78iut7vr8T9amTViXni6xnl37NhzILYqqSbaMjbBu3ql8t303RxEs6zYCVt/koFeS/9BtN6Dkt21Bs0TjhrK3fF90GUTDLtZBAiRAAiRAAiRAAiRAAiRAAiRAAoEI0BM5EBWmkQAJkEAYBBbNn4eH7r0Hu/cfRLmIvUr8dWjKsDP0hHIyNijhV050Bo8HsvI8dqjgyKINK7FYiciqmM7ojH2sTCi3iVuyiMhKIDYY1K7XvJUdZpPIz3YRpMvFc1l2EZMNuhjotDbU+0GHtnjfA/c/hAkTXsekSa+i/4ABqsq63USUnf76q1hQ4hTOvRs3tDkLE56/Go1cKrr3zXDOpY2C51+FTjRZx6OvwNy9mad02T8oHi/3nn4bpk7xnvQqznSxUo/VUkWOGt5S9j76KsyjHkTCRd1qWBmLkwAJkAAJkAAJkAAJkAAJkAAJkEDtE6Ancu0zZgskQAJHKIF1q1dj9PkjMPri85G5ew+MOqMIubJYnhKC5VgucY81jbhioTzlQWw2m50eygajFutYskg+p3isQl2oaxWyQpUrl115IBuljBZDWa7KJdaFSlaitFqUzy6ezSoEhkEn4TJUPSIyq3aUR7LKpxfROltsu/KyMbj84kuxft1aSa3bLbWJxz+4ZVqKu/HyzN8xZe5u93VNTgytnKWLXnm/ktex4iB4GtSma9LwbGpQgGgMCZAACZAACZAACZAACZAACZBAgyJAT+QGNRw0hgRI4HAh8OtPP+LeO29DUWGhU+QVAdlqs6FcxGPliWwRT1YlJKtzk0mJwCL8Ki1VFE2rRYRfh/MdnhJ8y+0S4kLKKo9jpUCr83JRkGNizE4vY/FGVnXpNOFZQliIc7JWr+axLNGTRTw2G81aqAzRnOW+UqLVon16GE1GuVblDVi+bIWIyaPw3gcfoP/AwXWOusPIx/HMqOPhKNyMR//1EvaK3bu2b8RL3z8n53b0uuRx3HRGB82ufxZ8hBemrYbd0BnPPDIIkx+ZiD1og0cnjUPXVI8o7eqEPUeYdO4E++atKHh/PpLu9PSvUm7xBC75/g2UfbPVWbx5VyQ/cv1nz7cAACAASURBVBf0zRNc1fkcy3ctRtF/f4R9S7aWbjh1BJJuuxxQwrTyKp4wDqa+58Iy5zPYtzo9rs3X3ImE4X00Id+nshAugrZnLEL+c2NhGvww4s44TqvJtnUqCp5bjOSXX4ahtdPTumT6E7BuG4iUsUNRMvdjlH6wtKJVeckxdCSSb7zAaVdVHGqhXyF0nVlIgARIgARIgARIgARIgARIgAQaKAF6IjfQgaFZJEACDZfA+29Pxs1XXYGCggItbIVOFs2zi0hr1cJO6GC1OhAbE4u4mDgtTIUSdHUSZ0IJv0rfNcfGQYIeSz6beBGL0CsL6EFEZYPRJOdGEZ3lqIW3kDIiKqvYxzA6BWmDeDWbxDNZ1GYRm+0wi0BtlHqVF7NOjiKlSsgLicMs9ihPZovVLlXLudxxSB4Vq/n6K0fj6ymf1Tngfbt2Yf/+/RIbeR0KlHuwbN1O7IZeLe3Iy7di7ldzJF1uiIA579tFKMvLg65lZ8TnbdQEZ509A+v2FjoLBvivaeBoxN/TG+WLP4Z1a3GAHCrJgoJX79YE5NjbxiLx2Tuhi09HvixC6MgNXMS6/U/oEo9H4hMPIv7/hqJ86QwUTFnjzmzPzUbpfz6Gru1IJL30IMwXtIbls3+jZMV+d55wToK2p0uALtmGsl9WuWM/l0yfKR7pBShb7hTEdY79KJ26G4b27WD7Z4YmIMfceCsSn3sQcTf3l2njCulRPYdo9yscBsxLAiRAAiRAAiRAAiRAAiRAAiTQsAhQRG5Y40FrSIAEGjiBe++4Fc8+/rAItiLXKhdX8fbVyeJ5DvfidwbxGFaisMRDVmEmRNAtl4X01G6XUBQxsTFaiAmbhKFwCsUiMKugyOq/UpdewlGoRfMM4rZsEE9jnd6hib/KQ9kgQrJKVx7PKuSFXtpV3spKQDZK2ArldazOtVAXUpdUpnmc2sVOY0yMZqsSux3iQvvUQw/ikbtvr1PaRWs+wwMPPIDxk39CoYjF5aa+uODk1hh46TmaHfrieVh3QEJ0HNqAeTlOj95zRvZDk05n4brhgzFoxE04u0tiUJsdohub+9wASKiIwudf16j6Zy7fuxTlEtEj7oFXEDuoF4zH9kHqc88LExuK58oCfAG22CF3I+m+G2Hs0k3qvwbmS5JgW7nWLeSKhgu9tJskHr6Gtt0Qf9mjcIhTs31fZCJyVe3FDOkNR/ZfErNZpoB9J2yrxGBpq+zHBVp/7QVbNbtiTmwPhyVP6425s/SzYzfEDLkRSTecpc2JUDhEu18B0DKJBEiABEiABEiABEiABEiABEjgMCHAcBaHyUDRTBIggfolcOjQIVx63jlIX7dOE+GUNWqRO7M5VvNC1q41j18RdMWLWPx/UW6RkBYi5hpE2DWLiGuXkA168UguLbNoHsZK7RNtWERjETXj47SYxirmsVpET4W00In7sFE8j82yiJ7yQFYitEHEYpNZBGQp7JD27Q6bdt+hFtaTdlQoCxVPWdVnVycSysJms2pt6EXctpeXybmI1eL1/MO307B39y68+fHnSEltVOuAHfo0nNrnGOze9Bcy8ywwWJfjk1nn4t6zT8cpsT9jZWk5Fvy5Da3jFoukK6aLyHyGiMYOXRKGXnkThlZroSyGJ966yU/egPyxHyPvkzVIvibFPV6quKPwH62+GK/F9xz61ogZaYRl0TroLjymUiv2nK0omz8TZXO3ACUlQJGMTUvlDe7ZjMc19VzImVqcL9KtqvZMx/YT8XgVyvdJX60LRL1ujaTHh6HgsY9hE83alvmnvHRoAaMKbWEfJIL6bBQ8LKE6uvRG7EXnw9yjvWZWqByi2a9IebAcCZAACZAACZAACZAACZAACZBA/RNQ7m/cSIAESIAEqiCwWhbQG9i/P/5avRalEiPCtVtEsDWJGKvEZKPJIEKvAbHiaWyUcBQqhrEWlkJEZBWywlJaBuV9XFxUhHIRdSUosoi7FtF4ReAVcVjd02IhS4gLkxKKpS7lmewQQVkdRWuWXR7ZIgCreMkWiZMs0SykjHORPYPOITGXJTay2KEUY0tJKWxlZc62lKQtIrNddiUyW0XMdjjEI1m8pVctW4TrLjkPG9euroJAdG51PO923HnnnXjhzbcxso1zpbs189ehGE1xwehuWiObfv4U//naacuxZw5BI6Wyh7npmw5G7DWtUT7rdVjW7w2ttElCjATY7AcWI/+eF0VELkbcmGuQ9MRDMPQOkDFKSdW1p0/qpHk5l61PR9my+dB3Gijez+KdLO2Xrd8Iy/I1kjbEuZBgTHukvvEe4h+6QRT5VSh++VnkvfSjNpeCmhuEQ9D8vEECJEACJEACJEACJEACJEACJHBUEKCIfFQMMztJAiQQKYFc8UC+5bprkLcvC82SY9EiJRYtU2Pl3IRmjZKkWiXsqlATIooqz2ARaDW5V4nHsithWQnB5RKiQnkYK8FZeRM7xEtYnZeLEuwQb2FLcRnsIiCrvVwW3hPdV8RkEahVrGVLmdTpFJO1BfocEsbCECt1iOex1KN25dKs09yaJU6yVr9driUUhhRQcZXLNeFY6pD6xHUaZaod5agstm9O34DHxt6BPOlrbW5FeQckbrQFhfs2Y8t+FaVZNhWDQrZ2/Uaimdhpz8sQL2UliZpw3lldtXsqRvLGVQsxZ9lGlKhbIWxxwx7QwloUvfIfH9FU3+hYLYawdacnZrKKI1z2bQGM3Tv6eC2rZqzrftE8extPfAgxp/YRwVZE3PwQDAghi07iWftv1bXn0KUiZkRzlP3vQ1h+ssm5KNrifR07RtI+nATbAvFMH3qCVz/MMPccjOSnP5Z40V1h3/i7FgojXA7+dvKaBEiABEiABEiABEiABEiABEjg6CJAEfnoGm/2lgRIIEwCoy88F5mZGZpArJOYww6JU+yQkBQx4m1skPAV7tjIIhA7F7iTNJHwVFxi9YC1i0CsrrV4x0rkFQFXJ6KvJhyLWKxEZ4eouUrsLRe3YpVf3dMUXpvEB5Z7SgRWXsVWCY/h9Fi2orRUwipIWRXuQoWnkDOxyyjCsYS/MMVo9hmVN7QI0WrBPc2bWa5VfnVuE3tFXhbLRPyW9K0iJN97w5Vh0gkv+775siDh9bfgrgdfw+YyJbYDgy84A3GCRZfYGRf3cy36JtJ82wtwQlPnn6jibTMw/s338d9/j8evmyQAcQibEluTHrmqUk59k17QtZeYyc89Auvm3RLeYjcK3h+nCc1xZ3evnL95RxkvWThPwmzYD8midT+/CPtWZW+lrGEn2DasgmXdGljWrtB267qNMITQXsxJJ2lCuArz4QrLEXPyEGnfGUc65vjWmi32vfNR/NN8CX2xX7O9fHeO28ZwObgL8oQESIAESIAESIAESIAESIAESOCoJMCYyEflsLPTJEACoRB4+qHbxUt3PUzi/WqW8BPFJRIKQom8qrCIsDoJWhwfHw9TrAixookqAVgJsirEhQpnYZUQFSqkhVVCT0hxzctYFEnJI17CUotZvJSVJ7NU5dwk3ITou7JVpCvvZuV6LLGOHVqoCnlkiwCt1xbMk+AWIr6qhfTKrBJjWQqKPK3ZpcJnJCUkwCLtl5WVaPm0Bf7E+1iLz2w2o6S4WGIuq0X7lAXSotj017KFeOzu2/Di5Pec9tTif2NbdsYlV16H4T1buFs59YJL8J+ln2nXg2VBPSUuqy0mJc15Iv9t2USYBNhET620GVqehZgxc1E2dbczvIPKIV67KU8+j4I3n0HRuCe0MkqMTXj0FRhUHGHxetayxTu9hE3HDZfwEEtQPPEFLR0tJLbwFZ1QOtd56fqvriK/+zqAPa576qhvrCJMzECx7K5N2dHonYerbc+QpsJXzIS+21nQK5OlAkPLUyTMxVfSz1NhaOZMAyywfPm57K4WjIi//xnl5C1beBxcNQTi7LrHIwmQAAmQAAmQAAmQAAmQAAmQwJFLoOIrepUd9M7jOvc/Ot3F5Ou51OS9q3T/a1eaOgbbnQqKU0nxP1fCtyqn0tW5OgbaXXm6FxcXPy55uJEACZBAyAS++Hgy3prwJPbniIewRUJESKzh7AIRZVXoiIpNPdySEhMQHxcvHr5mEY7FC1k8fW0iGmtRLeRRpRawU3GI1aPQZFQew1KfxEF2eRFrkSgkrIUKeWGRBffELxlGg1nE5xiogA9KbNbiI8u5WrBPxU1W4rCq0yxicLK0X2qR+McSFqNMPJWVh7TyYlaCtjHGhILCAucDU8Rmze/YYERsjBKRi0RElpjMEpdZgkggBlbo5doqBj076d8YddW10mLdbv/Mfh1PffKXCNtt8fy749AuRhF2bnaxt0SEzwSPs7LrVsRHh0UEYxkKvQjunlENUp3Kq9RXYV4nWzTb0+oSq80JAU0Pi0PAGphIAiRAAiRAAiRAAiRAAiRAAkc3AXEwU55HG2RXX+WVCKCOgXZtHfmKPK5z/zKu8uoYbFdfY1331LlrV2muc9dRkrS86qjS1OZ/9E7TMvj/h57I/kR4TQIkcNQTmDNrOt6Z9KyIwmbRY8V7V0JY6EUA1uutEotYhYZQ0q48b1XoCHO85DOJwBsjR50seGdFYWG+iMLiF6w3ifhs1sJRKJdfm6SVqwXulDeziMZ2EYJF79Ue5TGxZi1OskqzO6zivSyirl0tumfX4gDrlbuyW1OVWMpyWVaiR3ZujvxVKhdPYrFJEsvEc9muVtuTth2Spv56xCjhU3k/i+0qr8Wi+iThL+R/OlnUT8VnFulaC9Ohk3yP33Mn2rVvj74DBtfJXPhnwWd4/+eVyNibq7WXdsYVPgKyStTHi4AcZWt0SlQVNGoIqt2CCLDVlos0QzTbq6ausDhE2h+WIwESIAESIAESIAESIAESIAESOKwJUEQ+rIePxpMACUSbwNZN6/H2q48jVjyPC4vtyC8oQZOURPEMNoqHsAGt2x6DlKapyD10EMXFNsTHNkZZqXgGi3BbWlaMUmuxFrfYaBDB2KY8hI0Sl9j5AwqLRXkoOwVkFXpCC2ohAq5Rib1WHWIlnwqFYRaROtakR4wIvWphPhWCQnk2K29jtUBeuYjF6twmZVVsYyUu2+02Tay2iUBt0VkkxIUsxidhLcSJGsWlhXKqF0FbhGXlHS3ncXFx8k5UXnaKuK1Cb0j4ZfGzFU9bnYjXEqbj/luuwX++/AFdTzgx2ogr1Xfo76UiIBdq6YY2Z+HRa7pVysMEEiABEiABEiABEiABEiABEiABEiCB+iNAEbn+2LNlEiCBBkjgo3cnSBzhYsTEmSVMhE0EVvGCFUFY/o+E2DhccOEFGH7+OThw4AD27t0v4SSa4vlnx6OwrBQlEk5CLZAXI+EiDOJxXCrxiJNS4kSETtE8j7V6RcBVi9spUVctmKd8mpVorERqk6SbzXEiIItns0GFsdBrIrKKdmyXBfnUInwWCZVhE7vKSss0j2LlQ+wKkWEXUVn51apwFwVy3yr5iy0OlEgs5GLZbaIoW5TXsWRTYTFUnGWThNIwS+ekeyIga/+VdKCoIB+Tnnsc/5n2c62PUpeLnsUT/fYjtmlLtG2WWuvtsQESIAESIAESIAESIAESIAESIAESIIHwCFBEDo8Xc5MACRzBBDanr8PWzRs0j11RgUXQVYvXiYCsPITNRsTZDejUrSs6dO2O1uLpG7duE7oedzxapSWjvCQHcRJCQrRa8fAVAddWho4djkHP7t2QmpwkYTBENBZxV4WlKC0qkvjFpeJVbBNv5TJNwFWicqyI1ElJjaQ9k+wiHUtk99jYWM0DWgnPyuXYruJYlNtQmJePQ4cOwVYmdYhgbZU0JQxLLAsRs0tRVCy7xFguKrUgr7gEMRKmoljcja3iCW0Tobu4VARyaVO1Lk7X4vWsR7yI16Iryy5Cs3gp/7l0EVYsmo8+tRzWIja1KTrJzo0ESIAESIAESIAESIAESIAESIAESKBhEqCI3DDHhVaRAAnUA4Epn30AvXgR6yQ+sIoVbI6xwyhCq1qZToWViDMbJPSEAbHx8cg/UCCL2InIXFaIW8ZciM3rN2LuH3OxZ18+EpLjEZeYis7dj0fTJilolJyMeFnkLq1xIxWCFyUFBZq3cKmlRLyLy8XTWeqVhfQS4hOlzXgRl8UVWNq0a17NsZqQnCAxgZWQLJbBIYvhWcXreX9WFg6JR3SpeB0rL2KriNR2zQO6TEJxFKNAxOp82fftz8HBnHzklpSiTIW7kLjLKmazFs6iQpiWopp4HGtWHtJyLu0rr2bljTxl5oJ6GA02SQIkQAIkQAIkQAIkQAIkQAIkQAIk0FAIUERuKCNBO0iABOqVwI/ffoVcWaTOHBsj+m2seAzLInkSCkJ56aoYwuIYLJ7JJhFYlVdyLJJFGLbLdcHWzeJFG49TzjsbFw87C1O++AIxSfHIKylAcpNGSEhKQnxcLFITEtCiRRM0ionRFtYrExHYJsqt0nINRgl/YYyVc4PmaZwrXsYWq0VCV1g0r+Wi/AJYk8vQuHFTicfcBCmJ8RJD2YpWzZtj/969YvchLVyGClMhhouXs1VCclhQUFyI/YdyER+/R1Th3Sg/5EBxuRUlEgpZZOQK3s6jFINZhGiTXhbYE1HboZeOS4VbN67Hj1P/hwvGXF2v48PGSYAESIAESIAESIAESIAESIAESIAE6o8AReT6Y8+WSYAEGhCB9//9Bjp17yICcYwIqRIWwgLx/JXwE0o9Vr7JSlhV7sEi9BpEYE0SITknPx9JItgmi2dyUXEu2rVtj3/deTPmzp+D/XmxsJvMWjiM8rIyGEREThYxWeXVi4exikrhkHpVeza5sFodiBNPZJOUKRHPYuWFXCQicEFuHrb/vQ3bd2dgu4i8zVukoUePHhJnORlJCVJXs2ZIlKNR7CwXD+NYacMiYS2USJ2Tdwhx2ftEENbDKm1BvKxLpd4DEuJCrrRdDUGiKOWpcbKsnhKxJRyGREuGXdpSoTdUvg9eH08RWYHiRgIkQAIkQAIkQAIkQAIkQAIkQAJHKQGKyEfpwLPbJEACHgJvThyP3Xsy0aVXdxF1TTAb47TF6kwmEX8ltoNexFW9xAw2iRcyRIQ1SKwHS6kVtrxiEYVjRRDWIbVZExTIYnSNmzbFeecMx9adO7B5x07s3ncAySmpaCx7YkysFhvZoEJkSB0Oqc8hR5OEyoiV0BiqLaOIt0YRgnUiCsdLPOTkxGSkpKZi/57dyDmUg3xpY+f2rShp3BhxEkM5RhbkUwJyUkKipgor0dssi+epY0yxWYTpeAmREYNE8Y6OzTMjJVnCYuzPFaFYRHJRiFPj5F6sCMgqRUJrlMtifNJFbXOIV7Ja+C9b2Lw38UXcdt9jHmg8IwESIAESIAESIAESIAESIAESIAESOGoIUEQ+aoaaHSUBEghEIFcWp/v0w/+IeCquwSLgGkQ41etEUDXIuYi7RiUeKyFZpauF8ySMhPLO1VyJ5cwkAq1NvJFjGzWGUWIeH9qXjWYtW6J71y44kHMImXv2wiaev0kS0zhO8saIfmyQdhxSr84o9SmXZKmn3CKxikvKJNxEIfIkZnJOYQEKZNG8/PxSFBbkwSAL8KWKENyiWVNNbM7NPYhS8VqOk/AbcbHxKFZxlcVeu8Q2VgvnHcg5gH9270bG3ixs+XsLtmzZhkKJiazaTDbpRSTXiQBu1ryPdeJ9LKW0finRWO0GFRtDOuoQW+USX378Dq648Q4kpzZSvQ9ry9q0CfulPvcfHF08Wndsh2RZuDDkrXQzHrnjJeyVcbrwkcm4pGtS5aJ+eS7tfAjP3/w0toiH9g3PTcaQYwKUcdXiVzZg/a68YRzzt36Dfz3/I9D0HLz72hjEhdFle+4urM+woFOP49zlSvfvwpa9ReKx7muEQ4awcccuSEuo3EDWpnXIS+6Azq3kRUO9bhbsTF+Pv3fth03mQKeTTkLHZr42FezZhEV/rkMhktGz3wAc73dfmR+Ii3+3HGUHsHLFNqT16Ie2qZWZ+OfnNQmQAAmQAAmQAAmQAAmQAAmQQNUE3N/pq87GuyRAAiRwZBJYtmSR5kEcExenicRKKNYrQdUsorGIsioeslqsTsUa1omgarGoUBMOTQQ2JSbALvdN4o2sFuSLS02WdANKJMyFUco3Tk1BaX4hmjVuoYWeMEkYDJOEjjCJl7BDjgYRgQ0icKqF8QpEKN6buReZIvxaxBNYn5SKZh064+9tf2HlggVIMljRLNGM7j26omVac1lszyQew+INbdVJbGZZDFBnR4mEzVAL6uVIHOTtuzKwbccO7NqVKUIw0KZtG+gl314RlS0WJRgrqVhJyTYRzTWdWEIgS8Nuvc0u6cpjWhLkUFxYiD+XLsKQEeeHNxEcRZj++qtYUKKEat9txB0v4IpT2/gmRvHKXlyCPerlgGz7iqNYcQRV6WPDK5S18Rc8PP5LGbsUPDX5DRyX6ByYv+e8iQk/7w9Y2QgR16/wF9eF/0+vvY7Vg+/F29f2CFiuLhLth9bjsfte014C6EwpcFjzgM+Bs+58Bdf0a6GZsHflZ3jkrd+1PichHz9NmyIvDCbJC4PGbhODcXFn0E4s+HXSI/gy3YrzHukuInIVLw98C/KKBEiABEiABEiABEiABEiABEggCAGKyEHAMJkESODoIPDbjOnSUREaldaoDkrAVV7CKkyECMI6FU9YPHUdKIdBxN/9Bw6gqKBQxGBxBY01i+Brk1ARSSgvLoJVxOaigiJYJI9JRF69CJhmo1FCVZi0sBNKtjUaZGE+8UjWxch9yWOWa4d4LFvKSmGUttq3bY9iseHYPv1hbtEWa7ftxb7cfMSmmnDMcV1Fzy0Xz+ZixMSnIjU5EUnJKYhPSNIWwsuRkBfbt+8Qz+OdyMw+gIISK8zJshhfYhyaN2ssgrdIxjY78g7man1SsqReLaAndomvtThXy1F2ccIW2yVdjjpdBRgRkxf89nP4IrLUntpEKsqUE9lSkk3Iyxd3adl+fe9d9DtpHDrGKEtC3zT2IWTXJXbG8y8+gsy8OHTxF1erKO+qX8JKy2KKVWQM4Va8KV7LZS8NIXNFljVfPYuJP293XunifAp2H/0aPhntk4Q989/Aox+uQ+emCb43Kq5iRENNknAp9bnp45Nx3AlDcNONV8hClDEy5Yrw4/j/w7RPfsOovtcg3rEXH/17Nszdx+DNB89BHCruv/YhzvjgATSS+VcVF+++7VnyX01AVmn8R443GZ6TAAmQAAmQAAmQAAmQAAmQQOQE+P0qcnYsSQIkcAQQmPXbTPHAFc9gJZ4qr2IJCyESsqinehGNVWgLkX5FWTZIuklCQajzRrKQXYzETi5u0xqFO7YhVQRhR2kJsrftRLGIwUrobZTWTERoEZolnnKceDmbRJhWIrGS8nRSl068kHUSI1knYTLE6Rht2jmQGCdicomI1XFSv+RLEW/lpgkmHH9MK3TtkIZ2rVoiSYTnpKQENGqUglTxfE5t1ARxTZujULyP8zdvwpJlS1FUVg5jcgs0T2uKZcuWwVCWJ/GYHWgsi/DlykJ9VpuIuJpntdgi1qpNScXK01p8rLVrUZMlboDzSjFQ/5s/e4bzXoT/bX/O43h2zPE4uHEq7hv/K3T2DGzIKETHtofw+sMTsa04FmMefxwDVdiJ0r/x+iNvaWlXPPMMBnicUbF69qdYPH4x9lhkzFoPwFOP34L2AcI4oGwXvnj3E+yyGHH+HQ9JvTFYN/N/ePeL+SiU8YZEgm7d5SSMHH0d+rf2dMq7fsS0xU333Y/BXZxhPHSOA5j+wWR8tXCHs4Dcv+ref2FYV6c3bfn+9Xj1+QlIz5XY0rGdMfxUJ19X7S6P3D1og0cnjUPXAKEWdCK4nn7LCxjdPh13PvGTq2jgoyMPP05Zg5gTr8PJzXzbClhAmEy653n0eHACzj6uwkNXE3Tvx66TH8bdwzo4Bd5XXkThKcNRNO9zLPzHqYCfdP7duG1UH3doDUjbsz+ZhE/mOFk07XkOHr77cjQP9FIgph1uvu96j0m6BHTt0QqOXc64HMW7NmhhR269enhF/Qk4/8Zr8M2DH2HNrjIJRSKflRC42A/9hSffXYSeZ5+L/X/86mmPZyRAAiRAAiRAAiRAAiRAAiRAAjUiEMI3zhrVz8IkQAIk0GAJrF69WjyLc1GuM0lMZBF25X/GitjCKgayEo4Nsvqc0ht1sgieEpVtNgkFoYmq4qWakoSichvsSmyVvUmr1jj2xJNkcb0WSGncVOIHp6K83LlYnVaJWq5PFq4T91+pQ3ZpQ040r+cEqatZ6zS0bNcSLVS4CvFwzlizEie0boYrLzwPvbt3Q7x4NTeSmMQn9z8NTSXucoJ4QKuwGTqJcay8pwsKxQtaPI3bHXs8rrrhFsTIonz5JUXQi2BtsdpQVlKCUnUtHtU68UAWk52isdig5GRNV60YLSUca+KxJKpwF0r+LpGQFpvXr4l4PNW6hGpLbdrR10PUUYLM3FyJAS1e1+6wEzZ3Wnae03PZWRrYtmiRJiCr6/Ldi/Dkg/9DifTFf3NYSySsx14J4bFLqzdv41d4bco8TUBOSUmR7Fbs3rQcB7w7Lqne9aMsAx+Mn4BdZQpWHj647yGPgKwalPufv/wQfkwvEFF8L15+2Ckgq1s6ibP829x0dereCvdvcIZ0EAF93d5Cd7r3Sc/z78WNA9vAXpLvnRzwPC99BpbIi4erRvcLeN8/UTHZVmZBgS9S5GZbse1gkTt7Xl4WZn76IXa1PA+PPvEIrjqjA/6aPhkfL8quyGPBrIkPiICcifNuvg8P/2s0dOtm4OFxPwUcC3fF7hML0tfvkRcmzgSr5aB408v8V17rFZs+uQ2ayTzMKXYaWy0XEcM/fu4tlLcbg7uu7C+xwV018UgCJEACJEACJEACJEACJEACJFBTAvRErilBlicBEjhsCXzx+f9ksTmLhJdIEC9hJZYq6ZtdugAAIABJREFUT2TlMaw8ciXchIjIehXbQdQobWE9EVKLioo00VhJXTHKIzkpWYRiEQxFEI5v2Rp6FR9ZwlkYxMtYhZmIjY2TRfMssIv4bLOJFGtW7+6ktNIkRcXVqdAZIk4bpS5jfCIc0pbDLov6ycJ6jYwSRMNahBJLMayWUgmJIR7P0lje/v0STkMvoRbMklc8Xq3lUqMeyeLS3KJFKzRr0hwx0o8hgwYgO/NvCQ1gQ9Gh/SI6JyA756AzbIWyQXb1P80YMUhpySp+srJNJauuK89rsUaOioEev377JTr36CUZwt92LpqFn2OWYO6Pc8QiqVtEw65pzoXVRKt3tutVbaA0dbv5qdfgudvPwj+z38NLny6Gvuh3LPrnIpyV5lVYTpVo7V1H5vrNWgYVZ/iiO57A0C4JyNyehxbHKs9nT1lj+3Pw2jOXw57+rXhM/6h5TK/cLrGt4xZjfo4MtsyNW1+ajAGtYrH4g/vx3oID+OmnZRhizNO8aVVNI+95BaNOjsW34x/GD+kl7spTOp2J64YXYruuE87u4ruonDtTqCcims76fBb0bS9FX7EllM0l5AfKK76+7mTR9WHqcSPG3XG6ltbluAexa+k9stCfisfcAuX7VuB/ay0Sc3gyRmuhQnrh2YcKcafw2lU0Ep0rYji7K/Q72bvyc3wjMYvPvf8MzfPYKobp7FmQCCzywXJltsFDzpUW/Jg+fQLmHUr8f/bOA0Cusu76Z+ruzPaW3ispFCMthBIpgiKvBZWiWBBfAbGAICL6qjQpChbsDfhEAUFRQEQBpRm6EkIKJIH03exme5u2853/nZ3N7GTabjaU7LnJndue+rtlZs/85zy49PITUBx+eUh5s5eqIyIgAiIgAiIgAiIgAiIgAiIgAkZAIrKuAxEQgVFL4MX/Ps++xxnB24Hi6krGCVPg9fgopnLmlod2FD5G+vZS2fJRQLUI3nDEVC6zeTB/Yx4vKWdEbx/XqTX3dtGDOAhfRSkilo77fYwetjjezp6QU0YJbSUchdYUWwYlW4Rz3KKJY9xPQZjuF46Q7C8NopK2E9EuRriGKxANB+hpHEdlXSUH6fM75ZrAS0MHlsG2cUDA2to6WmcEGXHcjeceewSl9Es+6sC3oal+M7a4wyin9UXspZdYKUVhtoLGx1znWuK/IxTbbmuay8KPjQHFcQvUtXaawvzCs09akmFN8eanccedO7Me+6nPJQaMSxFwdx7NvnbkcYc4wuO8dxyL8b9d5kT2thegNs5beixw36/Z5TbcfPVFuJlWFB8///M0lhg8nXjqiY4HL2YcgPHue5zyLcX29QkR2iKYf37JZ/DzlGzh+m3YuK7e2RPzHYxjFo1xQJ5w8nH48xV/GUgZd9Xi6NM/haMH9gx/pWfDMtyz2QaPSwixwy8pc87aSbWDDvgZNZwUmjubEn3963fPx+PBhO9zWxsHy+P0Ai1K5ubwoG5bdT8H0PsXxh5zPk7Zb+xAHSbuD+jH/XsHO0IPJN1lpXfzg7j6znV4H0VtE7BdfV5+eUIh3LzLNYmACIiACIiACIiACIiACIiACOw2AYnIu41QBYiACLwVCWx87TWse3klB7ajMEyxtp1WEOY0QTcIFHHgOxsUz6KPvSYCx8K0EGakLgcni4QZQxtjIiqvcYqq3ooqRFqb4S+rQDejfXvamhktHEdXOETp2ERYRi/39tKHOOZYSpgIHaAFRjxmqnMEcRtkj5HI1IKdiGKL+I3HQk4dZpvhp99ykAPjuSiJlVWXo7yuguuMhqWA3BdhG4uLHUHYGbCPgpkN/ud2sd4+tjnciQDLLWY47rgxYxBxIqwT7bb2J/yeHTmZZfIfxeg4Bwek+skl153AVFOUTQ+14y6sW70KWzdtwITJU4d82s2/+Ix3zaMFRw39cOfR79mpYFA5yTelODl1JJo26PjubLjHHIUbv12N//fTX+GpDS2OFYWJyfVfuhanz8lUssVL75zC/bYKFok8feE+KOH5czkiZQTuMTN5/tY7iV2+QMo3tAmBdWcpI7f2+O23I+ZfMqyIZl7ag6Zi++ZgCBO/Z3GmpR/6FBZWcMBGbhmLOL87mTYle4S1Ccifv/o2lC8+E1d+7ICBGuO0W0mf4txl3w3seiQtJSOy7/3Jbc7OFfTL3vpXF3pDa9DIe+nhm67EK3PehXPOOGynl3Nadm2KgAiIgAiIgAiIgAiIgAiIgAjkJ5D2Z2T+DEohAiIgAnsDgU0bNziRwZXlpWhp70JnVzdWrV6D2bMmsXuJKGMbaM9DuwlKhYwCps7LcOM+ehU7vsamsDKit6i6mp7KFLq6OywbijiInkUmR8I9jpjsp0gcYKRmV28IJRSEIxSgYxSUPZxdnoQYbKKzCbim1ros7NdaYEIzReji0hIEKCL7aY/hLaFVBgcti0cpMtMew3yQ4/Q2jvf7NHstHJq5bHDAItpmFNHyooh1uupq6I1chAYOvueU7UQfU0w2LZyeFVZz3KKZaaNhdTrtsLaYsm2v7J+Jy+aLHKfYWL9l07BE5CmLluIdR+yq1ppYmPSv3dFupshlWPf0g/2D33EzbXrkwedxwqyj0PjUowNRwoUEnIZatyFUsRDnXvY9nN2yAl+94DtO/pdfZgTtrs1KqxWYOHcG960ggyDe/YkLcHD/QHZ9XW0IBSsQWbuNx9fD3f1vPLfxQxwMrgwv0L950ETBc+Xz/0FDtBqHHjx/2MJmbPsT+O3KMA779HsTUdODKsm+YawtQndrAznP7h9YL7QZz7fklWoHFeoPmKc0EJyyEAfmiDpOzZQUkKedcD6+ddpOAdnSlE9eAF/8r3hqfQtm7ZcYRbFt3TPONTCrtiS1mF3XqWhPXLgYh04zaxeq2BYxHTbxnte7K4AAv/xxbE12zak9IiACIiACIiACIiACIiACIiACBRKQiFwgKCUTARHYuwisWrGcwi09faigmthKlRSPPPIYgsVLMW/WeHiosJrwVGRCLYVVFyN8TUiNMMI4ZlHAzBy3qF/OVVOnoXXdywjESygC02OZGb1+D9pbO3nch3A4hm7aWYQpAsdYj5lQuOlt3Eeh2OWIyQzrNPsIRj/HKTI7A/VRpPbQ87ikmD/wZ6Sy1e8KWPgnRTKKwHGGTFtai5J2MWrYLDM8JgSzbT622fL5aZNRVOSHm4Iyxw1EPUXkaF9ioD9rt/UhIVpTSKZVBmtmyyhiWzkU0NkiZ0rs4yrTW/TyulUvYdGhh/cfLXzhCHwZkrtLajCB7Wkki3/9+Mt44hfsJbuZPiWF5sZlv8ZZnJOTReMePpPRr6atp0Uvp26vuvsK3PBPRmePm4xZte4BAbquxgTHrl3yWvmp+UsoXB/ovQ/PRtvwows/id9PngJ/ez3q28I4gTYKp05e2G9/EcFv/u88/CbZwJRl99q/4ZofJOwtWspvxAcKFGBTinBWn/rzrTync/H+JbTNGMLkKpmE/ao8ePiuO7F0+ocwwdeBP914jcNiWlo5vXYtZJmKJy7GSZNuwz1Xnw/fOReQfx29utfgqZUefODkxbuI4yZ6WwRy3D0ZJ+zvxwvPPZfwxaZ2PXbuIkyunIOT5/lw2w3XYMalX8KM+Mu47oYH4Z70Lszjuco9+bH4tE9hcUoiV986fOnMy3HUxy/ASbOKU45oVQREQAREQAREQAREQAREQAREYDgE8v1lNpwylUcEREAE3vQE2tvbTSuliNqH0iIvqhmRHKVy+fjjy9DTbSa9FFIpmDrj4PXbV/hpbRGLhBHiQHkRisGMH0YbB9qLMgK4bMpUi3ukKk0rDAq3ZTXVtFdOfE/XGzI7i7Djp9zV242e3h5uRzjYHu0sOCie2WOYKEyFjWVSvGWEs8vDcvwlHKivlOJx/+ylI63Hn0jHfPHecEJMpvhsXhx+1hekeOyi2B0wEZnttQhnL8N0vfR3jjFPlHYcMaaNcrbo4z4Ti8nBGTiPqrHFH5tthU1uCtuJ9YSYaDxs8MHOjnbn+FBfisv7PRDSMppP8Flf/xjq+us1AXnWkuNw5NyE+FfmZKO1CJsVL56L97z70IESTEj98lUf74/GTaSxg4nI5MHbVTPf7uTrqd+EF1dscNYXHHMmzlw6ieuD0zoH0/ZZO8/7/jdx/H4TncPNmzY6AjLorTynwg9X6Vx89asfQWl/P2zgwPedcaLTL3e/jllUMS5RNF/H12TmMZDAVhhJS7vrwVPvOvzxiW7MP/mDGN9f1+AEg7fMqmJAEHaV4H1fOAO1Lc/gmq9ehC9cdBleDByKmUW8DtLCuWvKea2lTMFg4rpwdrGck//vahy/bxnu/sk1uPDCC3H5Nb/AExu7Mkb9drXVJ7L1bcJPr7kG1//gB/gB5x/++AdYtq2Tx/x49/mX4x2TG/HTyy/Cl6/4BZonHIbLv3rKLoJ0oqAMXJwDiRd+l+O0w/EmT9mvVREQAREQAREQAREQAREQAREQgeERSPmLMGsBqWmS6+nLpBht+1Nn25++ndxny2yz/Ybajtkyfd1UmeQxW0+mSV8m0yzo7u6+lOk0iYAIiMAAgeuvvhI3/+LHCIUoxPIp5aEFRMOODtNiMXvmJLz3Pe9AV1sjVry0Gi+trseit81FsKQMRSV1uOHHP0cFbSx6Qt3Y1rANUyYxIpW2Eu1NDVj/zJOYP2sGBWQXNq1fj789+E90UbydPHE8qmhLUUN7inG1NSgt4QB8RZzLKuHmYHhmS2GeGRYZ7AyYZ+Iyd5mQa0/ROKOPLUk83IVISzN9mNsoknkpWPO3+34qlGx/R2s7nnnmWWyi3cTEceOcQcVc3B+hUL6jvQ3PvPAi/vHwQ7TfMJHaxGpmY/lWhZvCcx9tNWImSBNIMW05nKpZr8tmytt+s8tg3o+ecz4+8bkLB1iO5EoXRXmXrwTBwfrlLlUYB7MoLinJY3WwS04GLJvwz/1+5k3XZzMkz7jL6u8xVFEf25De2DC6QxyMsShz+X3dzIsS8BLY8xMF52+dewV6jrsQV5+2YFB9hbIelCnDRvJc+HjeGDy/25O1y6bhnNvdrlwFiIAIiIAIiIAIiIAIiIAIiMAwCASDwSuZjSPZ2yBG/JlvYmnr6bP9OZpMk1xPbifTJvPbMtts0V7JY7aenG1fcj255C4nrS1tn03py9R9ToL0F9lZpBPRtgiIwKgg8PS/n3CEUYvKNdsHH6N4aytKGFkcwqq1m1D99HLsN38a4r5ihCmsWqCwReVSeoWXwqwJrBalXBKgTzGjeR1FlmLuFd/7AU5797tQESzGli0bnOjg+uYd6O6tQoAWF129bg76FUaA0cq0S6YlBaOR6WlMI+OEkGxhwZxcnsRzP+7iewgtK2yO0RbDBOTO7Q0oopgbZwQ19WEWYvHDbkf4nTFjJjZv3uj0zUMzYxpx0D45iq7uHjQ0NjntdPxh2W8Tka0/tuTC6Z+9ryQkYxZLQZvqMrf72F8PrThM1Ab++8zjzLBnRORChUMXo7R30W7ZqkKmIorHRL9bk9XvaMAZC/IjyPObbXIH2fZsB0dof89r9+O8b95FOw4q7Zw+e8zMXUoulPUuGdN27M65SCvK2RypdmUqW/tEQAREQAREQAREQAREQAREQASGR0Ai8vC4KZcIiMBbnIDpplRJnUHjTETto1ewCahVFJJ7mlrx+JMvIGS+wzQT7gpFsWnrDmxvop9uSQ/+ct/fUVVejoqKYkxl1LEJsTZ7GCq8sX47rr/xR0C4F8e981hUVpYnrCRYV4TlWeRzmJYSfWZhQV9kGyDP2mFyroeWE/SesJbR6oJexxYWTZW4LxxBrLsVLtpo9DQ0wsfd/jL6LxcXU3g2v2TWz7BWN9OXMNK5tLSMoncURX0+x/c4RH+IHta5dZtZCljPEwKyh8KwTbYnTiHaEY0dRdnZTW3axGmLRE7YbDgKMqOSNb35CRRVzMD/vPNodKAcBx+3FHPq+v003vxNVwtFQAREQAREQAREQAREQAREQATehAQkIr8JT4qaJAIisOcJbKPlQx9F1z6KtGYfYZMJptWVZYza7UVzZy+eZjRyclq5blNCbKXY+++PnUk91YNpk2vx14f+ZpJsIhnDdG2wOnNUjlPYDVGYbuvqpNtEABEKxi4OkBdhOG+UArLZLLtYhlMrI51dFJPpVOykMVHY8Sk2EZnCcZy2GejuZsQyo5Hpyeyj73KEwja8FMFNc2bZXvofRyJRWl4wQpn/zAs2xlDnMIXrXorQjU1NjERuZjqTu2OMLLbo6USzbcXRjrltu/ooatt2YqZAzaQmMrsS/hbo7hyeJ3KyNi33PAF31Vy89/S5e74i1SACIiACIiACIiACIiACIiACIjAqCEhEHhWnWZ0UARFIJ7B58yYUF/kY7Ruj9TAH0aNISgnYXCVQV8WB7JihsyfkiMVhCrwBWiC0d3ZTpPVi//32xbpX1tEneX9GGlc6RTuxxBSF/YwODod6mJ8WEj098NPWIExBt6Ojm57I5QgE/BSRY9wXo/ZLkZgCstu8MijsutwUhs26giOpuWxQvjiFZUYURzkYH0fE424fo4PdaGlpxQv/fQEvrVmD/Zcsxsx95qG0vROd7R1oaW7Gtq0bMXXqVJbPvJE4unu6sXlbA316wyj1+p2+srsUkvujj1m7EwxtPbGOM9o4To9kE8qTA+uZNO0c4sv6V1ZbSk0iIAIiIAIiIAIiIAIiIAIiIAIiIAKjhIBE5FFyotVNERCBwQRMtrXZom0dGwduOYG2jLotolhbVVKE8qAPZVVV2LBxM6ZOn4wXVrxMoRk4YvES9LS3Y+7cWQgwytjUVac8FuajiBzppBJNKwnzWS4u9qO+oYkuFRx0rKiYSy86ujspYPtRVlEBnyPUUoI2Ow0KxnD5nShkK9NxIzZbC67RiBluPwdxq6tFc1ML5h1wAI74n/fStiKO1RSTV61+BfX19di26VXU1FY7eU2s7qEA3tkbwobNWx3nfifo2qKQbWIdCZHYVmlZYUoyyzNFObk/4bfsJGWGxP6EnOyUoBcREAEREAEREAEREAEREAEREAEREIFRQKBfSRgFPVUXRUAERCCFwMQJk0w2dfaYgOqIqCa9moDKpZsDynlMYe6LwBwjQh20cKACG6Mw++yzz9GOgoPcMZrYTeXZ7DBilJGtNBORza7CPJZL6FNcQxG6u6uLkcgdtJWgIEwRORSNoLWrAyFaU0Q4x6MxBhqHWHwU8UgPt7nOGZFeBgXTooJParefA7UxithfVoYpCxagbvp0WlVE4S0uQh9Hylu/eQOeevYpeDhoW4C+yBZNbFYdYZbfuKOVfs47GBvNLrhM7raWps7cZK9dVpGxYL/NBzmxJJmUdcs3Y45sEoyYJhEQAREQAREQAREQAREQAREQAREYLQQkIo+WM61+ioAIDCIwccoUxMzTYWCiqMr/iQjchMuxz8fB7igq+xlYXBosArVaSq19mDt7Bm0nQhSHO2kV0YMIheYYBdsQBWaOjucIuH4ua2tqMWHCeHgZbdzZ2Ul7i1709IbhLylFmEJzL20uopypODtCsUUAm1CNcE9ijkWc6Gg3I5jdvgBitL3o6upGfcsOvLLhNaylJcfyNatRTwuL2Qv35Wh7ReiiaOwJBhGjuN3DKOZ2einX0w+5h37Jzk9PWFe8f3A8xwva1g0DZ0dCpoDsppic8Gtmc9gmZyYcR2CnoBwsqxigphUREAEREAEREAEREAEREAEREAEREIG9n4DsLPb+c6weioAIZCKQ1I/NC9kijk08tQHtKJKauGq7vBykziYPl17u4GFHeHZEVUYa91IUjjCquIjCbMIz2MU8XgQDQdQFAxhXNwbjxoylkDwO6zfWo5e2EhaFHI0XUZQucSKJI+a3TIHWooBNoDY7CdO24/QzRh/9kbneyUjmro5ObGtoQG8ohJbWdnRQlPb5i9G4fTuCjDz2+PwoCgQYcdyEyuoqVJeXOX3opB/y1oZtTv9shw385zbLCqevLJyT9dUUdOuXeTNzjS2hV7RFIPcft0H1nIH1uE1pna+aREAEREAEREAEREAEREAEREAEREAERgsBRSKPljOtfoqACAwiMH/Bvo547AiofHGibJ0UZvdAwZjCsQ2iZ4HBHkYSO6HCTGeRyh4Kvo7cShuKcg6W5+dAeD6mDRQVobKiEtXVdYwajmFsbR2qOSDfgn324XYIrW0ttLVgRHJ3L8XgCKOKexi47KEQTbGYA9n1mbUFReI4lxbpbFYavT1d+M/zz+KFF5dj85atjGjuhY+2FlMmTUUFI5oDHh/GVtegktYZY+iXbKrva4xSfmnVKrS0daCppQ3NLS0mTzt2x9S7nf45QrijVtvbgOO6nBCvnc3+aGSDY/8dJdnycaKwfMDBSxLrehUBERABERABERABERABERABERABERgVBBSJPCpOszopAiKQTqCiqpKiasw00YHJIm0tGNf8jJ2gXDviCKlMRMHVxOMIRViLHrY0UYq9FqtrdhUuHjfBeeL4SVjX2IhiCrzljEYuKfJR8B1Pf+RibNm6GSUBP8op+LbTXsJNobk50Iya6mr4/d5EvTEPLTRYnydR/o7mJkYgb6fg7cHUydNRW1ULT58bMdbd0htF9ay5cFHw3rJtK8ZXj2X0sAet7S3YsWM7BwWsRsP2Jvoim92GRRebJswW99tZ2NJF7+e4icnMZ32N2+x0m4K5/XNA2NKUZEtijCyFJhEQAREQAREQAREQAREQAREQAREQgdFCQCLyaDnT6qcIiMAgAuXl/b6+TpQtxWSzbqB4a9YWJpKa4GrewDaQnofWD3EKzhadTAUZvfQZ7qMlRG9vL5dMyTxWzIZXX8X2+gZEGGm8cM40BGim7Gek8YQxY7D4kENw3/0PoI3RyS0l7RhH4ThA72Kr18qIRRiBzDI8XkY/m7UFB8CLhhmt3N5F64sy9NDComtrA7pfrUe8J0x7DbaNQ+W1d3Zw7kIL5y30Si4dU41a2lmwM/RBjqG+sZl9sfKcjvYvrXdWGyOq+7if4rlNNqQgMzprzsJJQ5GZQnMiv6UCSsrKEyt6FQEREAEREAEREAEREAEREAEREAERGBUEUmLwRkV/1UkREAERcAjMW7CQy4Ro6qYdRWIgOYqt9Ps10TVO8TfKJ2SfbXksEpmD3JkpMsXZEK0pfCYwW0QyB8izcjo54N1Nv7kl4Tcc6sF+C+ehmNHFHgq0AZ8XByyYh4njxmHD+tfQ2tqGYvom29Tb24MQ05sgbWXH+6JcUMSmANxD64qWxiZaXIRRZJHQPVHU+EswsbwW5aCFRmcIFVxOrKihr7IHpRxYb/o02lyUlWHc+InwFwfRsKOF7aY1R79o7HZ52VqK5SaMs/441y0K2YlAZv1RhlObZbIJypbC8UK2blsyW1K6njV3ntN2vYiACIiACIiACIiACIiACIiACIiACIwOAopEHh3nWb0UARFIIzBx8hRaPHBAPFNSbeKyz8RbmykQ0zGC2qoJxUzDdYvWtW0edjyM4zFGInNgPYtUDlPkve22O9BYX48xFVWomTUL4xkRbBYVNtCej8LtWNpnHHbIQbj99j/SYqIRzZPbUFYagMtLQZf1uanStnBQvIrKKvRx8D0P6/JStA0x0njf+fMxdtwE9NS3wNPNiGhvMaORe9DB+sIx+iazHy09nYgUg8K1G2U1HMhvayOmzZ2F+INPsGuJwfKsjyYDmxqcsK1gn0wd7heMHcsOZ9tJ1R99zPTMb1MyGnnshMnOtl5EQAREQAREQAREQAREQAREQAREQARGBwGJyKPjPKuXIiACaQQmT5kGG1xv9UvLHb9gt/khc44wEriPsyPsUl8172MbYM9cK5wB9lhOT3cI1TV1KC+vwi9++gtsqW9E/bZtqKZFRhsHsStjOUXFjA32MbLZxGfqsKX0RN5nziwsOnB/PPXUcxgzlvlpC2F+ysEw66RvsZshwOHuLvjoo+xhpLKJ1/P3W4Dq2rFUcN0Uj+sQbWxFrD2EmIvCcGkxutsj6GEEMcqCFJ174S7yI+b2oqiyGtMX7IcwBeIgB9/zsBFsCsVyRjs7LCzSmBXYPpv6PY/NezkxyGDigKVizzmTD/POmD0f4ydNsRyaREAEREAEREAEREAEREAEREAEREAERgkBicij5ESrmyIgArsSOOiQxVi9crljWeFYGzMiOCGw0sKC2mliK07x1uVYPBT7/Jg5bTz8bj9mzJoNn9+Hpx9fRpHZ74jGkRB9janLRuifHDWxluW5aBthPsdeWkrU1lbhsMMOxYaNm/DksmUoKipGeOJERBl5PKayAi7aY/gYmRymiN0boiDM/GUVldYQCtFxeIsZsTymAuHibjQ3NGFDxw40t9Mao6wUsRI/heAgujhY36ZXN+Hdp56BkjET2DZadTBa2QTjOIXnPs4mKFvotQncpnCbiYdZV1i8sR1xBs9z1rhOcdnqdoRlHly89PhdQWqPCIiACIiACIiACIiACIiACIiACIjAXk2A0oQmERABERidBN73odMYakyRl3YTSZHUBFQTb30WvcsIZLN7cHuKOAheBQ7Y/wBMnzyNxykq08aio62D9hEBlARLUV5aTtnVZGcXejgg3raGRlpV+OHm4Houis0sDFUVZZjACOQTTjge4XAYy558Cps5EF8bB8prbOPAeeEQehmN7KJY3d7RhbaOboR6Qxyor4uWzCHaXNA+I9KF1q5mNHHe0LgFm5rr0RHpZr4w3Ix+3tHWjc5wHL6SCgrZFIBNGI+HqRmbd3P/ZAK3qeUJxTyx4ujJJiFTOHZClhNicuq6RWUfuvQ4J41eREAEREAEREAEREAEREAEREAEREAERg8Bicij51yrpyIgAmkEFuy7P8o4CJ0F3drgc4nJQxuJYnh9JdR9g6iumoQ5+yzC2LFTKK4GKP5G6XVchCJ/Mfw+Ln2M9KW4GmLksIm2fbQcRufwAAAgAElEQVSn6PMVY826V2mTwQHtKCS7OEif+SmbNltdUY7pU6bg/R94PzYxIvnRJ/6NZ/7zArY2t6CPgnSEonVbZxeKS0rRwcH6mhp3IEL/ZQtHNkHYU1yE2rFjMXPmDMydOxuzZk5HZRWH12M7rP6N9dsxlnYTtWPq0EprjUgkzDbFEWG8teOM7KKYzIZYMLJJxk4UMiONnW3bQWXZBHXzaHb2MW9SSC6hUD573r6WSJMIiIAIiIAIiIAIiIAIiIAIiIAIiMAoIiA7i1F0stVVERCBXQkc864Tcf99f6KgSqGX/7y0pujzeSge18FE02CwDBFG9kZoOdHHKOFyisAB+hXHGb3sZZRxDwe481Ak9nEQPUqvtL2gkExf4S1N7WhobMeYmlqqtRYFTIsMCtUl9CweV1eFBfPm4qilR+Lee+5DT2+YgnMMra0tmDNjKsqDxejr7UVLRzsmTZgIHyOMqWpTzDXhl+JuEX2OXX5GNY9FSUkJ6pkvxqjp3jhtMJjipJM/iAkTJlCM7qaI7WObGMXMFphG7AjHLMdEYttia519bHYiMtn8lS1MmdsWhW0mF5bKIrQPW/ouJtIkAiIgAiIgAiIgAiIgAiIgAiIgAiIw2ghIRB5tZ1z9FQERGETgmONPxMP/eJB2FbSkKK+keFxDX2I/Zx/CEYqyPVFGJnsRpHDcwsheLwVdP6N+yyqq0dbejhgtKCwKmNouLS5MqjUPZR9C9DVevmINZs+chgB9jh2lluWwaBQzXQUH2jvu6KMQY5Tx44xGfuTRJzBnzkzWGcGMqVNQZNHL3mL6K7vQ2NyKcePHOxHBHkZBx2h/YcJzNz2YW+mJ3NyyA92MkK5vbMZcDqY3ffZc1uem1UYxfFx6LPiYDWBQsTO5KBKbVuyERlvkMQXiuKMim1zMgfVMWHZEZqZjMls3EfnwY+SHnCCoVxEQAREQAREQAREQAREQAREQAREYXQQkIo+u863eioAIpBFYvORIHHLoERRvY/AVlaC6shodFIdtoD1fcRzh5mZnUD2LUy6iOOyht7D5GW/Y8CqtMMopChdR7KVoTFHXV0zrCuYzKdlFwXg1LS02b6vHrBkTaI1BcdZG3eMge8W0pKiuKoeH3sdHLlmM6dNn4MmnnsWK5SvR3trKgfbimDFjOsVrN7a3dqCSlhvu5g5GOzOSmUHJHbS+2NHQgBDb0dzRiU7WvWFzA1auXY9Djn0XPObBzPaauE0JmXbIJgsn2mWdcbbNq4J9schpF/eZ+O0MoGcpecjtdnrBvTYgH1BaWob9DjqU6TSJgAiIgAiIgAiIgAiIgAiIgAiIgAiMNgISkUfbGVd/RUAEBhEopUD7rpPeh7vu+CPc1F43b2ugzuujAFtMIRWorK5FS/MORiT30OrCg+IiL8VfLyOIY4kB9qi1hqK0fKCFhTtGoZZRvmYBYSYQ25vbsHzlaowfW4Wy8lJTlik4MxqZLQgW0xKDg/pNmzieA/vRnmLpElRUlOKZZ55HKPIk1m/cirqaKkyaMgkd3WFsotdxWTBIIdvLQf+8jE5uQVd3JxrbO9Hc2o31r21G4/ZW1NSNcfpnvsYxzhG2z0+fZgssNqnYIorNG7mP9hn0wKCAbAMHmnBsXshMw9nSmLjsZLLSuPP9H/kUrTyqnLL1IgIiIAIiIAIiIAIiIAIiIAIiIAIiMLoISEQeXedbvRUBEchA4N3vPQkP/P1h7KBthBk6+Px+9NIqwmwfeinU9lEwjkSjqKmuovhbjCYKuFF6JJu4atG7dryI0cU2xTnIHhVmHqJFBCOKV614BfNmzcDs2bTBKOLgfaZMUwj2FxU51hUBRhePra1irX045MBFHBBvLJ588hk8++x/MHbcGNpZMBI4vsmx0CgvCTIquRQtO3Y4dYUiIdQ3NHKAvs1Y++pmNNMD+fbf3eaI3Y2Njdha34ieznZE+7oQp02Gz5MQkE0o7qOA7eLAfyYUm82Fy14YmcwGct1NAZr+zgzHtnaNHTcBnzjnC06dehEBERABERABERABERABERABERABERh9BCQij75zrh6LgAhkIPDBUz6M3/z6/yFOv+JQKELxlBPFYCqr6Ozqol9yOUrpmdzW0UEf4g5GJPt4JAoXo5N99C/2UBsG8/oowNoAejYIXyQawjZGNq9YsQrVjCo2Udg8h53CGU1cVBRAcSBMQTrmRBnTHhkTx9XgsMMOwQv/XY6Nr21AK32YAyX0a2bE9PjxNpBeMTrbOli3y/FkrmeE8qYNG9HSTqHYW4T7/3IPnlv2BKK0umhjO4tYZoxicJSFuxlhTNcOREIUxakXu90hRin74aag7PVa5LGHbYkyCtuN3nAfI6QZbc245Y9LQLarQZMIiIAIiIAIiIAIiIAIiIAIiIAIjFoCEpFH7alXx0VABFIJHHHkYtx1118Y5duSGCCPUbkRRiOHQ70Uib2oqKqmZ3IAUXoUt9NCom76JEYh91GINdGY+isFV6+P9hCmPlNM7jPRlsqy6dAbN9fj1fWbUVlZxQH8GLFs7hGexAB8gUCAwnUUkQjtLpg+zno9FJhdffNRV1uJV199DZs4W4zwqjWrEGQ0soe+GxYl3EsvZPNQDoXC8BTRfoMD8XnYph62ryQYwJRxdRSdA6isq0WMDXvl5bW0vGhENB5FW2+3NZRSdCRhpxHgIH7RsOMNXeSPoSMURYBi8v4L5+M9J5+aikrrIiACIiACIiACIiACIiACIiACIiACo4yARORRdsLVXREQgewEzjrrDFx52bXwUzSORMJOwigF3qqKClQwErizs4MD6PUg1NPrCL1mZ+Hj4Hg2Lp35DLuciGSL6qWw7OtDV1vYObZlaz3WrX8NdXU1HERvMu0mLBjZIoPjtKmgvzIF3FJzk6AAHQmHGPnsRmU5BetoJfqi42FBwt2MHu4J9ziRyWHaZJjtRB/F6mg4SrHa50Qah8NdLJuWFRSMffR1NqG5h0Jza3s3xk6aiEMPPQzd3d147oUX0LJ2rdM/P8XnEIXyLvY3zvTmoxylKB1h2WXBcnzpa5dnB6YjIiACIiACIiACIiACIiACIiACIiACo4KARORRcZrVSREQgUIILNx3PhbMn4M1L61mFHKPBRRTUPYhEAgyErkc2xob0NbaAq+fg+NRPLagYze9g8eOHcsB+CoRCkcYuRxyPIZ9FIfjY8aguXE7B8PzYO26DRhDEbmsLIjq6nJHGHb8k02BpiDsYRov85gfcymjjU3Y7aB1hg2kN475bPC+enoh+31F6OoJo5OzhTTzMD2M2RJGPrsYxWyD4nnpzzxu0iQKzvR45jGzy9jKaOi2lg6MoSXGxAkTsYoiss8foMhtPhxw0pgonpxM5D78sCVYfMQRyV1aioAIiIAIiIAIiIAIiIAIiIAIiIAIjFICEpFH6YlXt0VABDIT+OjHT8cVjL7t7uqjIBxGHQe6CwRL0NXd41hXNDfvYJRwOSOVo7SbqEEpI5TbKfZu377d7JMd32HzHrYI5jB9iUM9PYxiLqU9RYSD322iGF3BiGOXs49SNKOG+7htNhY2WxSz1/FUdmKVKWKXUMAu5iB8O+iNbNHQ/uJyNO5ohT/Qix5GREdD9hjvQ3dnF6OjKQjbwH2c65t2YOqUydixvZliN602GB1tYnL9lnraYbhRR3/nVno9xylis2ZHPzYJ2aw7ovTgKC8twwVf/VpmSNorAiIgAiIgAiIgAiIgAiIgAiIgAiIwqghIRB5Vp1udFQERyEdg2oxpuOCSC/D1iy51/CW8HKxuwoRJ9DReyyjkNnRQrJ23zz4YN24so4VD9BhuoABLb2QW3Ed7ikjUBqSz6N8I/BxgL0SBtpfroKj86sbNqKgs42B6AXgp5AYoDpuHRZwD2/XROzlMa4qurl7H6zjGyOJAcQDuCjfaaaPhotA8dep0eikXIcRR8SxKmu4Tjh1GqKeLfs2MfDaLC4tEpjezWWO0NLc4g/Ft27KVwjH3MdKYhx2ReJ9Zcxm8TKGbfeju6XRsOhooPFvEs4vpfnfbbZi3cN98uHRcBERABERABERABERABERABERABERgFBCQiDwKTrK6KAIiMDQC8/ddgM+efx5++cNfoI+CrTvuZdRvCM3NzfRA9jHa2M3I40b4/T5G7no4eB4dkSm8erjdS8/k+qYmRgs3UmDe7gxU56JnsZe2GMcesRjbtu9AeflWCshe1FRWUvZ1O+JxiN7FFu3cS0sMt9uLIg7iV1YOLiP0NG6jGDwedRSz2zt6UFzfyAHzSmhV4XdE4g3rXmY7KVRTKI6xLhvszwRs81c2gbu6usoRwG0gQJeLbSnyO6KyK0b7DK8fVYys9rqimD1lIjq6e/GZL16AJUceOTRoSi0CIiACIiACIiACIiACIiACIiACIrDXEpCIvNeeWnVMBERgdwgcffyxWPvyWrz6ymY01NdT4O2iiNyCstJSRgDH4KcQa3bG3SbUuuOM5u3CimdWYMvmLXSicMFN+4gwo3qLfUGMqapy0oaiwEZ6E1fS3qKqLAAfxV4Ti6O0xujpDTGymUKwRRJTcC4rKaV/cik2b9rEiORizN5nDopKKtC3dTtFYA7E5/IyKrkXTfRJDkejbE8xs1I4psDd51hUsByPF02NjZg8eTLaW9spdtOuoj9iOWZeyExvvswxRkl7KYbHaYtx3HtOwgdOO3130CmvCIiACIiACIiACIiACIiACIiACIjAXkZAIvJedkLVHREQgZEj8L+fOxu333In/vyn+7BtW73jdxwsCTAC2PyL446dBfxurFq5GqtXr2Z0cTFqq+tQysje4tIgLS360EKLiPLSAErpbbxh/XrMmzsLDY07mK4SxcUcRC8YoZALtFOkDtFD2fyKA0E/B73zOVYTcQq88xbMxeQpU9ATdWFTww5EKRLTOcMZgO+pVSswjd7Hoc5OishuuOhzEWFUcpxLt48D9lFsNvG7ktHITazXhGYTruPcX8pQZ7PViMc5UF9zE/Y94G248OvfGDmAKkkEREAEREAEREAEREAEREAEREAERGCvICARea84jeqECIjAniLwPx96Dx74+8OMFO5FkFHINoco7CJOMZaC8rInl2FbwzZUV1ajrroaNeVVFGmLGBlcxOheL7ZRtI3RE3ls9Rj6KXfScsKHzVu2YyLtKcpLu52oYYsQ7uzgwHgMDq4oL0MlI5eLGOm8edNGTGEU8aSpU1BZUY2Wrgj9kOMsu4TF9LHerdjaWI/Zs2YjUFOMIIXqxqZGdHYyppgCtnkteylUe2hx0cNBAmvHjkNNTS16GfFswnLLjmaKzTGwhZizz2xceJkE5D11HalcERABERABERABERABERABERABEXgrE5CI/FY+e2q7CIjAHicQCBTjK187H1+58Ovo6umhD3Ix66Tay5Hrmk2EpUfFGAq8pfQorqGQXFlR4UQse+hJbNYUtbW12LG9iXYYvaiuGUNbiW4EfHE8/58XURI4iAPk9SFMH+U4rS/GjqnD5IkTnAjhULgX5bSzqBszlrYWlQjHXFjzysu0y6hHUaAEMR5ftfplZ4C9dg72ZxHIDI5GeWUVXSr8aG1pA2hnQV8NVHJfL9ve0d6JraFtFJU94FB+jKhmtDIjkWfMmIGzv/Q51lu2x3mqAhEQAREQAREQAREQAREQAREQAREQgbceAYnIb71zphaLgAi8zgQsSveW236JH97wM0f89VCkDYcZjcxp8uSJjOaNcoA6H2rrxqA4EEAfBd2+eMwRaE2EtsH4Nm3ahnEUiFspPLtLitDS1oLnXlyD+XNnoNjTh/JAEX2SS1FBEdpPKwxPyONEIPfBy7Td+P1td6GDgnUnxWiPj1HKW7bR/oJRxBSJX9v4Gt5+wCJGPrvR3dnhDO5nlsd9FIsrx4yhrUYYrRzsjxozShjpHI1x8D6m7YvGMX/fhfjqZZdIQHbOpl5EQAREQAREQAREQAREQAREQAREQAQyEaDMoEkEREAERCAfgVLaWFzy9S/h5JPf6wjGxcVBWk4E6W1ciwkUjyuCtLrgtkX52iB15jXMWGS4OHBdaTCAsXU1aGluRoSD4HV09dLfOI6V6zbikX8/g7bOMCqqailAlzKvnwJvEYrLK1DOKGYXReI/3n0PWrvD2NbUju2NzRSFY1i77lVaWvhQUVrJqOQInnr6Sbz62gZ6MZfB6/PSV7kEU6dPd3ybexjpbIPsmWeyh+Kxz7yS3S6c8J4TcNUNV0lAznfydVwEREAEREAEREAEREAEREAEREAERjkBRSKP8gtA3RcBERgagVM/8n5MmjwO99/3kCMKeygSx3q6GZkcp8OFiyKylw7DUUYju2hrwYHuKNbS+Jg+xxXo6uhGNBJCkS+IClpSRBmt3NLcgWeffZGeyrW0spjCCGaWw5Bhl5e2GRxA7/EnH0E9heOuKCOHWX4xBenOjjaKw10oCQYRi/nhdZUyyrgPXbS12PjaRkyYMAEtLR3YvHETgrTZKGKb3H4/rTfCCNA3mQXjo//7KSw97pihdV6pRUAEREAEREAEREAEREAEREAEREAERiUBicij8rSr0yIgArtD4PAjF2P8+HF46B+PYkdDA0JdXQhToJ08faojJHcx8jfSE6LncbEjCkdpb+GmALxjxw6sDa2h/UUEJWUlzsB7nqJaRidH8NDjT2IMI4/9HFCvlpHMZlnx/PPL8Sj39zK/l/u9tM1obmnEa+vW0ye5lP7M/sSAf8UBjB83llHGPjTRLsOipGPhFvgZ0eyziGhGLEfCPgrTcQQYUX3uBZ/DvH0X7A4C5RUBERABERABERABERABERABERABERhFBCQij6KTra6KgAiMHIGZs6dTrC3CHb+9Ha+s3EiRNoxuDl5H3wh0h3so4sYcSwsbXM/r9aLIX2SrmDhlItasWIlAsQ/lVdUc/M4DH48FS0vwxLP/RbAswKhhD15+bjn+8td/IGLmxowkXvPyaqx5aQ3rLObgfeUUoSkUM1LZ7DGKi4oZkdyHnlA3k3rRSCHZ4/FRRPbxWABe1sXYZrz9kINw+idPw7QZ00YOhEoSAREQAREQAREQAREQAREQAREQARHY6wlIRN7rT7E6KAIisKcITJw8Aedfcj5WvbgSv7rxZ2AYMrXaOIpoY9EZ7UWc3sQ28J2LdhaRnl709nTQqoIeyRVl6KPYW8No5rKycseruKGhHtvaW7Hi5fVooHfyQw/9i5HDRWhua8d//vM8I51DqKuqondypeNh7Pd7EYnFEOkNM8o5jioKy23t7RSni9hdFyK+KKoZ2ez1+zB56mR84EPvw4J95+0pFCpXBERABERABERABERABERABERABERgLyYgEXkvPrnqmgiIwOtDYN6+8/Gdn30fTz6+DH+/92+ob9iOuHklx2gl4YlTV445A9n5PImxTMtKGDnMYffWr3+Vg/MV8ZibEcNFCEXCeJ5RymZNEWMk8eZNm7Fx42YKxBXOYH5FtLQIlpRyAL4g3PRaDkUi9Ff2UzKOIkwLDTfFaq/Vx3pKqytQN64OJ73/PTj8yMNeHxCqRQREQAREQAREQAREQAREQAREQAREYK8kIBF5rzyt6pQIiMAbQeDQwxfD5rv+cDfu++O96GX0sNvtQR9F3b7uXmdQPT+tKbwuD8rLq9DS3gYOvQcf99lgeh0dHY4n8muvbcJT//63Y01RWzsGFfRPrqmrRU0NI4vpbxymeNzW2gp3by9tMvy00og6nss+Rj37KT4H6Zd83HtPxPs+/P43AoPqFAEREAEREAEREAEREAEREAEREAER2MsISETey06ouiMCIvDGEziZ1hHHn3AsXl71Ml584SU8+/wLaKVnsoticZRWFwxRpl+xn4KvH92d3XDRB9nn8qGCEcevvbYRGzdscHyPA/Q/9jG5RRm3NTchGg45InJJaRlq62o4sF6R45G8ZuUKJ/r4yHceg4OWHIK58/ehZ3LpGw9CLRABERABERABERABERABERABERABEdgrCNDAM++Umia5nr5M/EbbjDgHz7Y/dZ9tJ/cl1zMtPf3pbJm+bsK35bH9tp5Mk75MplnQ3d19KdNpEgEREIE3jMBr6zdg2eNPYtXyl7BtyzbU1Y1FU0szojGLIgb6YhG8RCuLLkYXT6RXclVFKQfni9DGgoPycYC80vJSFFFUjppNBgfUs+XEqVOw7/77Yd8D9sOMWTPesL6pYhEQAREQAREQAREQAREQAREQAREYzQSCweCV7P9LnGOc+/qXtp4+R1PSJNfT8yTz2zLbzN8zDxyz9eRs6ZPrySV3OWltaftsSl+m7nMSpL8oEjmdiLZFQAREYA8QmDZjKmy2qbGhEe3tnVj7yjqEQhyAj/v+8fcHMWXWTCfSOEIbDK/Xg7qx4zCmro52F27s+/YDOG6fC8FgABMnT0ZNbTVqx9Q55elFBERABERABERABERABERABERABERABPYkAYnIe5KuyhYBERCBDATqxtZRIK7DzNnTB46+lwPgaRIBERABERABERABERABERABERABERCBNyMBs3zQJAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIZCUhEzohFO0VABERABERABERABERABERABERABERABERABERABIyARGRdByIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAlkJSETOikYHREAEREAEREAEREAEREAEREAEREAEREAEREAEREAEJCLrGhABERABERABERABERABERABERABERABERABERABEchKQCJyVjQ6IAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIBFZ14AIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiEBWAhKRs6LRAREQAREQAREQAREQAREQAREQAREQAREQAREQAREQAYnIugZEQAREQAREQAREQAREQAREQAREQAREQAREQAREQASyEpCInBWNDoiACIiACIiACIiACIiACIiACIiACIiACIiACIiACEhE1jUgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiKQlYBE5KxodEAEREAEREAEREAEREAEREAEREAEREAEREAEREAEREAisq4BERABERABERABERABERABERABERABERABERABERCBrAQkImdFowMiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAISkXUNiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIZCUgETkrGh0QAREQAREQAREQAREQAREQAREQAREQAREQAREQARGQiKxrQAREQAREQAREQAREQAREQAREQAREQAREQAREQAREICsBichZ0eiACIiACIiACIiACIiACIiACIiACIiACIiACIiACIiARGRdAyIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAlkJSETOikYHREAEREAEREAEREAEREAEREAEREAEREAEREAEREAEJCLrGhABERABERABERABERABERABERABERABERABERABEchKQCJyVjQ6IAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIBFZ14AIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiEBWAhKRs6LRAREQAREQAREQAREQAREQAREQAREQAREQAREQAREQAYnIugZEQAREQAREQAREQAREQAREQAREQAREQAREQAREQASyEpCInBWNDoiACIiACIiACIiACIiACIiACIiACIiACIiACIiACEhE1jUgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiKQlYBE5KxodEAEREAEREAEREAEREAEREAEREAEREAEREAEREAEREAisq4BERABERABERABERABERABERABERABERABERABERCBrAQkImdFowMiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAISkXUNiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIZCUgETkrGh0QAREQAREQAREQAREQAREQAREQAREQAREQAREQARGQiKxrQAREQAREQAREQAREQAREQAREQAREQAREQAREQAREICsBichZ0eiACIiACIiACIiACIiACIiACIiACIiACIiACIiACIiARGRdAyIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAlkJSETOikYHREAEREAEREAEREAEREAEREAEREAEREAEREAEREAEJCLrGhABERABERABERABERABERABERABERABERABERABEchKQCJyVjQ6IAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIBFZ14AIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiEBWAhKRs6LRAREQAREQAREQAREQAREQAREQAREQAREQAREQAREQAYnIugZEQAREQAREQAREQAREQAREQAREQAREQAREQAREQASyEpCInBWNDoiACIiACIiACIiACIiACIiACIiACIiACIiACIiACEhE1jUgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiKQlYBE5KxodEAEREAEREAEREAEREAEREAEREAEREAEREAEREAEREAisq4BERABERABERABERABERABERABERABERABERABERCBrAQkImdFowMiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAISkXUNiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIZCUgETkrGh0QAREQAREQAREQAREQAREQAREQAREQAREQAREQARGQiKxrQAREQAREQAREQAREQAREQAREQAREQAREQAREQAREICsBichZ0eiACIiACIiACIiACIiACIiACKHn95AAACAASURBVIiACIiACIiACIiACIiARGRdAyIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAlkJSETOikYHREAEREAEREAEREAEREAEREAEREAEREAEREAEREAEJCLrGhABERABERABERCB3SQQ6upCd3g3C3mTZd8b+/QmQ6zmiMAbQkD39huCXZWKgAiIgAiIwFuegKeAHrhS0iTXcy3t2O7OJm5bGbZMX8+0nUyXukzmH3PppZceyXI0iYAIiECCQLwLr65Zh/rGJjQ1pc/b0NTuQl0VcNO55+D23nk4dn5NZnIs57E7b8M692RMrwtkTpNt7+7kzVbm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bdhJwdYKSTM4R3Ird93JVLu3zFVH7vNRWL9ylW8tz12HpRiZeqykbJNZJfz4x4/CPfMj2CfDr30s3+73I1vtQ98/Em0Zzv059JYOL0e+/mUrtZBnr+Udbvnp9Y5EObnOQ7byi0oq05uibREQAREQgT1IQCLyHoSrokVABERABHaDAH/ieMLZx+Gf19+Gsz9x26CC9j3pfJzUb8sx6AA3Qh1ARyT5pWr60ddn+83Qhnw9nX38FzE7XyIdF4HdIPBWuA92o3t7R9ZhPmf3js6rF4MI9P/Kx76kjbvH4cJzjsnw66VBObTxJiWgZ++b9MSoWSIgAiKwFxBI2lLk6kpqmuR6+tKsI2yy/amz7U/fTu6zZbY53cLC0iXtKmRnQRiaREAERGC0ELCfMG7ZuMkRhv3BCowfPyHnzxYb1q5GvHY6xlUOJ356ZKi+GdowMj1RKSIwfAK6D4bP7vXOOdTn7OvdPtX3ehAIo2HDJrREvJgwZQrK/ck/916PulXHSBLQs3ckaaosERABESicwGiwsyjk00FqmuR6+tJEXptsf+ps+9O3k/tsmW2WiEw4mkRABERABERABERABERABERABERABERABERABN7cBEaDiGwiriYREAEREAEREAEREAEREAEREAEREAEREAEREAEREAERyEhAInJGLNopAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiJgBCQi6zoQAREQAREQAREQAREQAREQAREQAREQAREQAREQARHISkAiclY0OiACIiACIiACIiACIiACIiACIiACIiACIiACIiACIiARWdeACIiACIiACIiACIiACIjA/2fvTOCjKLI//ptckIRTghBEbsIVEJFDEAERARfRXeUQ/COsggJGEAQCIipiMAEBlSCoqOAKqMCCXAoiyLVoVNSABJRDrnAkIIEk5CCZf1X31ExPT18zmYSArz+fpLurq9579a1X1T1vaqqJABEgAkSACBAB6JvycAAAIABJREFUIkAEiAAR0CVAQWRdNHSBCBABIkAEiAARIAJEgAgQASJABIgAESACRIAIEAEiQAQoiEw+QASIABEgAkSACBABIkAEiAARIAJEgAgQASJABIgAESACugQoiKyLhi4QASJABIgAESACRIAIEAEiQASIABEgAkSACBABIkAEiAAFkckHiAARIAJEgAgQASJA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IkAEiAARIAJEgAjoEqAgsi4aukAEiAARIAJEgAgQASJABIgAESACRIAIEAEiQASIABEgAhREJh8gAkSACBABIkAEiAARIAJEgAgQASJABIgAESACRIAIEAFdAhRE1kVDF4gAESACRIAIEAEiQASIABEgAkSACBABIkAEiAARIAJEgILI5ANEgAgQASJABIgAESACRIAIEAEiQASIABEgAkSACBABIqBLgILIumjoAhEgAkSACBABIkAEiAARIAJEgAgQASJABIgAESACRIAIUBCZfIAIEAEiQASIABEgAkSACBABIkAEiAARIAJEgAgQASJABHQJUBBZFw1dIAJEgAgQASJABIgAESACRIAIEAEiQASIABEgAkSACBABCiKTDxABIkAEiAARIAJEgAgQASJABIgAESACRIAIEAEiQASIgC4BCiLroqELRIAIEAEiQASIABEgAkSACBABIkAEiAARIAJEgAgQASJAQWTyASJABIgAESACRIAIEAEiQASIABEgAkSACBABIkAEiAAR0CVAQWRdNHSBCBABIkAEiAARIAJEgAgQASJABIgAESACRIAIEAEiQAQoiEw+QASIwN+awNlDe/HNxo3YuHELkpJTcD4r7/rjYc/CjuUfY0vKBX3bWZ5FI57EpOW/6efx1xWha8Xv+hKt2KxfutRdKbx4HMl7D+GKXW1aHv5M2SP72KYdOJKWqc5A5zcSASu+X9rqWxr74vXIkbXruWMHsDclBSmOvyOpaSXX2haZuduYzGw9hPQsj4HLoy4HDh1Dhka+YqugqE8J3LPOHjqAg6l+GpvtGdi/NwUX8jyZFhsrfwgWvI3u2/7QY1VGcdkj5Or5lbheFA5WZLA8ps9tVln5K58Vu33RJeTqMfdFJpUhAkSACBCBa0Yg6JppJsVEgAgQgWtKIA/fvDMaH3+f7WbF1TLdsPDdQQi1uSWX6hOb/TzWb9iCy1daoWuTm3RtDSgL2K/qXvb5QsahXdh9qQF6tqrmlCHpys93nqsPrNqsLlcaz8/s34DYhM9gt1XES4lvoUE52XkK/9qHF8a+gdOFdtiCK8KenwEsAbqNnIFB7VysvKmTFmtvylNeYwL+4Gvm+8YWlPzV0toX/cFRqz210vxCnQVK1rw+EzuuuA+y9rLReGnWOOe44BddOkJMmenYyMVF94xBzKNt5HufQb67H5uMod2jdCzwb7JUH3ec/lXApfG6xs/EL53GYN7j0V7LV/uTPfMEEt6YiZ4TEzGgSXmv5fmjgNomLZlaeUz9R0tQMaYVlz1mfuUPvWYytMZdrTbxBm9Ry3NdZnZ7Y48yrxlzZV46JgJEgAgQgdJNgILIpbt9yDoiQASKiUDhud1SALnt4Ml4pqv8gTg3Kx0nL5W9rgLIHI89oBamJs5DQHi4Pi1bMMraiicyvmflIqyNHO0WROaG2IKDde2xZLNu6dJz4dfPp2L2+iOyQbZQN8MCwiqgQfMuePKJAWhYqYwcrEgYjeWLN6FPW9++qNBj7aaYTnwm4C++Obh+Hq9Kc18sKket9tRK89lhVAVD2BBQufN4vDmAByPzcGb/NkybsQTx87dj4fjOqtzFc2o07nKN7jYC/L737dI5WPpVImKzY/D2k20kw9T58jJPY13iVKxe9gG6dIgv/qB4Md6z1OTLsFhv+WDf7o9qf+L8y7F7bePqBvdjtQF+PlfbpCVeL4+Z/2jJKs60oo4BHrZZ9Ct/cDCyXWvc1WsTjzroJBS1vBBrZLfI49XeInOvZFJmIkAEiAARuGYErp9POdcMESkmAkTgRiSQmSHPQL69eQNn9cqER6C+8nMfm6G0dek8LNokLwERUDkaMRNG4I4a5Zxl3A5Y/i0fz8PiLXJ+e0B1PBM3Fe1q8CnABrLYtTUzpiOzdQ9kbVuCncdyJLG3PxCDp/s4ZoaxgMTejZ9gwbLtyLTzn8kGo96dD2HU8AdQGdnYmDgF59qOxdB7akpl7bnpWJY4GxuTT0nnrXoNQGFWoXTs/Md+drtl8Rws3npUSopocT9iY/rj5jLswzSzafWr0xHwz8dg27wQK5LPo07PCZg6oJmzOA+SbJs/CYv2syVA9s/E0O1AUNQgzB3fXsqT8cdOLHj9Hew+8Bc7D0bHfjEY0qslO2Ibk+9us0H9lMHv3OOY/uzLqPn4NDzeUa4rF5f+66cY89YRvPz2JDQIz9ZvN1Z+zqjXED1+Fu5r4JglxvknPI/jrWIR072uxbpzrSxQzgLFnYfFoV+dFIx8ca2cKP6XqYWhY4eIM5Y5HE2ia8B+XD+4zplqt3MPJC/QYD2hG4JN2lH2ra64uHkJvk8tYPYEo8fQCRh4t85sQqc/GpQx8g92zajf8NlS8QnvI1X6uXcwIiMjcPnMGTQc+DKeu+9mXb+7dCwJiz5YhZ+OpUpMub+OH94f1cNlf1XXk88MHxL7IhpmbUd84jqp3/A+PGbyKLSoyoL6bpuOL0t8jevjJsZxUrXgd8yfkoDvjhdIM9R7Dh2DgR2Zb4nNqM14HsawaGOJq+1MOTBdbn2RnZuPR4BhO/J+pNoM20+VV5z6zjHfY2wKjhqIvuU3YrF6vLLQh8zHQmExUBbMH6UtBNWb3oeB7ZbjvUOnpaVuQmHgS1bGJi5XzzciZa2G466cRWEjwO97PdgYdlPIFCRuSURS73fRtqqc0VUXFnwuF4mu97fD6gM/O6Ro7PRsM7sHMlElc8/SsNksSbevevoYv/+9PaImeBBODkrrjefsvq28r3EbnP3O1Xc9xmpTH7nFw++lezL3cWc9dcY6K/dtyU6D5wbd+5ejvrosRZ9xGuk8MBsDzMYVS37l1OY6MOtHZnq5JEPbWXu7xt2btdttfCcc2KTz3OfmPzpteo3uX74yd9GnIyJABIgAESjNBCiIXJpbh2wjAkSg2AhUuDUKVdlD+HvT5yPihcGIqqoODOdhA5s1+llKProPHou2kQX4+uNEvD3p/9k7D/AoqrWP/zcNkgABCRKQTigRBAQEERREsCHXewWxgopwRUQUpdkLIr2ooGJB4RMb2AVFkc5FARFDCSA1dBJKIAXS9jtndmd3djItDRL4n+fZzJlT3/d3zpzZvHP2nSfxxMT30LKK3qW8v3yHOwco5dcuS0DlCtJY5c8zbCtaGGRSDmPR7A9R6+oeeKZ3AySu+gJzfpyGj6qNx8AOVZGx5zdM/HQZZNsd6lfEib1rsXxPhM8YcPJwCjYdPin6EoZV8c/JV6+OxML9wG2PjsCVFY5jzsQPsSsnF/V8q34mfp08FJ/Eu9Gt31NoGr4fM6fNxYhREXh71L8g99SePitkmjwOwZe1R/8BcQir5LUs+EYlDPU7/Qf11n6IxJqdMbjH5cLSUFP5ZzUiwoW0rcuwU+rzvFefL6cgJHo8HvK6ctDKbKefr8syMbiqfghmz/kF/2n/EMrLf6SEviu/XISgSl1wWWSW5bhdGZ6BHWczUVvnaePkkSzsOJbm68Zed0/RZrcNQTMRPfXPH7665pFMJGw6iOBwwckkmHMwY20/jp65NRux19+NkX0uw7YlX+CbD0YjN2I87m9l7FbDSR1jRjZzvfw/GPXa+zjb9i6Mu7s1ktd/jwmzl6PuTY+gd/vLBJUs03l3fOcG7IloiEEj+iAiZQMmv/sTRn/eGG893EKh6ZO5c18807cSVvyfeKAzdpiSJ6+7lpWP48s3ZmPS2G/w7sS7db84MOebv3UAkHN/+6/zUPtawfveOti18hN8+f7LyA1XeduMmcvPsOBriRhvpxwEIe21KIHZrUc4s81mHBXsAX/sxi+gsDgp1FtK5gAAIABJREFULEejtekSd6TBemUzHkIW47mul9j4PCUlFzkZMs8/rkb3AWdrk7+NvHMjXWFmt+4aSwm07nE/yi0Zg/3HsoQR2XN/y8iSDyzFVenORObJw8Jt0krkhrZHVe3DVl+DVrL584x0bxmdcY7uWT5hHUas54bRHAsrVwZ3dL4JFYTV1nw9Nzaa+tYwk7XanWV3/zJbx7Tqmpexv29b88Beq+8p1nWNXIjZrwGA5bri6LuQlo0nbs/Bpl/RjBPZteuu0VzKtuSpldtsTG2uuzzfY53IbTOO4kGZ/fdPreyMkwAJkAAJlDYCPnNCaROc8pIACZBAoQiUrY+RI+7DS+PmYPTQNQiKqom7HuiHm1vVUZrNObpWMSB3Ev5r7/MaPRuOHo0T/Z7FrJ+2oKXOd6Javm3/8egvjL4yNG/VwVlbvevCLYwMoU37YtSjHZU6jWOHIfH3wdi0L0mcV0Vm+iklvcEVTRFXW+ygjYvDNUqK+OP5P99nUM45uA4/7BfG76en4M5mHh/JL0yKRP8npyI321NJyvtJfCa6Cb+NvRS/jc3xyvBUDBz3PRLTuqOR10gQVOMWTH9Nb3BTOxYm67g2iKv4Mc5c0RbNmnl3top/3NLT3Yo+E3T6bNgm9NH4A1Z3ulnq5+9OxMLQ9o6b8clr3+PPxHvRqXZZ5J7crujbaeD1CEuyGbde/v1YAc2KE1UWNd1Od7Wc0+OhdXPwlXgocevT1+sMmP4WrDgYsc45usp2HOXcimj3CF540DNj4uIaI/vAQMz/5g/0aCkeGBjYM2zreEXWM5LyyAcvZtdN/dabkeQOwbO9b0aM8B0dc0NvdJu/Gn+6olE5MkzMZY91X9+u7K5O5/9icmeVVRwe3/UnJq3aiIy+LZSHHlLmsBZCzwc8ejYcdC9WDpsZIEv//v9g5Ht/4UDaXXl+jm/G10of/TogpVPn/qv9PNdyXNxouI71w+efeXjLOWp17cWme+ZwYdaSfHHwXuva+W+3HqXs2mA9juowaY6W42cwBwvLsZHR2oSKedYrJ9eQVMNoTmrU80XTUpKRlJSE1OTDWD1/JhaK6+Ga/kWzNlndZ+R9QGVmt+76hNVGxLV3RvzKJeWU/JVOOcUIdvK3CXjgN20h4NEx93oe3gUmw0o2Nc9sXWh+w7Fzds/SiW15anufNJxjQLc+dyrtpljdtw16tl13Lf5rU69fo3VM35VhGQf3bTseMRb62tVt5H2XgFZWdT6braXy3mW1roQ5+C6k7U+Nq/1aXUdW/cqH8GobprJ7O7Mat5QtFt/7VGG9R6MxtbsfF8v9K8X++6dOdJ6SAAmQAAmUMgIWX0dKmSYUlwRIgATySSA6riumf3QNtvy5Ct//32f47M2XML9dX0we0BHpyfuVn6Ff2+RSX6vuoGrodl0Epvy9Sfw0uWmA8S3VW/7GFv7yakU1z7QtYUSWIbqG2JKsCdInpfoPRlT9driq0kJ89OIgfF67De7p2Q0dm9XRlPZHU8WuZvkz2Ga1KvkSgyo2RLvwEOzwpkgDhwwLJg3ByogIJZ6SIl78JsLf+1LRqHGQYtiOad8yQE+lgPaP1/DgNniJnpE+4SZ+J/OjX1RsR7QOmY8vF21EJ+G/M3HNb8gSrkM6CvapO5daj1svz65VrQpGcfnPvK3uRhVN0lISfsLIt5ai6g1DcFezqkqpQ/EL8O0fBxAu7NqZOTHo2fs2XGI1zgasnYyj7CwqKkojWRjimlfDd0s9463JCIja1TFiZDfXg2+qJ/rIwl/bjqKR2AXtTt2N9SeyUa6Cv2ujdmXumaSdWPzLL1i6JgHH09KFvTkLQdGBDwUqx/j1DKpQQ/m1QVQFz/yWbVSMriwM1ZtkNG8w5Ju/dUBtVD/3a9erJtyYeHjbjVmM29NnYdaSQnHwKqHXQbselYuWa5b1OKos1KOT8VPLqke9DPnhKNcwaRQNWJsMx7iI1kIhtNx9eGr1TAxd7dUgLAb/fvRl/OfqqkjZUvi1Sb2+jOaGGTM5bmbrrlpHHqUPWOliIUIuSCJII1gFcT98VvzCRDJMS96FRXNnYsZzL+GSKWOFMT7Q8m8lm5pndg9MbiV7PEf3LNmVw2B3rRrOMU3b+bmvqdXs1l21nOnRYI7nKWtRRn/NaeePLQ+L+5dtXZOXEOrl0a4BUi+rdcXJd6E8bLwJ+n61HOz6VdvUt6GXXS2nHA3GJF/zx6C+3XWn/x6rymMlt904xrjtv3+q/fBIAiRAAiRQOgnQiFw6x41SkwAJFBUB4af28tY3Kh/5krRJC77C3vuvQxWz9kPlHpO8wRXqWU6lx1nHwaQtw/rCv+6gqe9id/wa/Cj+kZ85aQ1m1e2BN17qDq9nX181KYvbFQFhMw4IFYSBQw3iPSdK6HTnw2ga5YLcoCyNCOL/ENSpJV17eHxGBxhgPFWK56+VftJlhSa4xa7V7r0ux9rPv0PSQ5dj6bcJiGg7APWEL2dTs6iOdZCOjdFLB4tKd2lAHjz2c8UgM7qP34idKYz923YmCt+Zwoic6xYGL6GkFQcNAzXqdBzV8tqj2CuuPXUU19dxzMjLP/jSFuh7dTRmvjkcP6k9Vu6ICV0aqGfKUd9uztE1eGzYdOQKn8Z39uyDetUq4p9vx2LeoYBqupNsiGcBAcG7ET8grUAnuvnkpA2Vnd2YuQ4W9VpS9BycjqPKpWDjp9YOPDrlqK5hgbXzntmNh9qOfk7mbcljeK0oHhS9Ia7zzMxMhIWJ3fV2QTeXrNamAt1n7Pr35qfv2yV2lwu64j6ghsioaFSr4r0bVq+O2LqRWDdoKjYeShVG5MA7T4Fk8+qu3HtK4D3L6dxQeeU5Wq3nuvtanrqaBHXOq0lWc0QtUxxHWx7iDYVm31Ns6+ZDYJWH3bri5LtQPrr1FbXr11fQIKLKbpCVN6mI5k+ehnVrTp58gwRVbrtxlPcvu++fBs0ziQRIgARIoBQR0P0bXYokp6gkQAIkUMQEYps2FltzVymtyp12LvcCrBe7cmO9O2Rc7mSsWHwc4VfVz7M7NzQ0SpRP8ezi1e2osW3LsR5hqNusAx4Xn4Or38DIGYtwRLieKO/9ObraTGhohCJLvEZ2nN2PNcezxet+PCEs3LNjM6JWU7TWyauU8LrIUNu0OxbFm8ylqwpD/fTuqoUwtdsLvT8bg0/nfIr49Gzc3UWMnQh2rMtmuxTXBwePCCN5A68RRLCRu2GLI6gG5Do3DxEvJfQbkGVfta/ti6nXGvVqwsE7zlrWTsdR3WWu9rZ31yHhm7mJemp4LEgdO/7y58eZp04hrMndGNO/tXwzIaIr6iawgTS71/+s7DYfLfx41wzyPFTYmWpQsAiStHyd6GPUpZ7dwX2HfbztxizjnKwlRlLnLy0/41jQ8SsMR9XNj3Y8VQ21aXbjobaj1rU7hnuNsHoDst1ccrI2Wd1n7OTS5qsGITXNnboTMybORW5IU1zbWPMQUfegKTcjXXngqNbTHq1ks9O9fFjyOb9naWWXce2cUPOczg2jumob+bmvyTr6Oa9dq93iNiUfYzu5f1nL5JHOSRlPSc9fWx5KMeP7Vw277xzajjRxPQ/tWmq3rjj5LqTpynHUrl+1ISvZ1TL6Y94xMeZZ3uB7kWxLW9/uujNyZSXbsJLbbg5kOPj+KftgIAESIAESKL0E9G+GKr2aUHISIAESyAeBjD1LMemdL/BXQgISDx7ElnW/YNSEn8RLg5oK36xAcJUm6F4jFD+Oew6LEw4g9eQh/PDO61iXnYMeXoOltrvw2u1w3SXB+HH8a1iyZQ+Sju7FGvHT++1JZx23dcbCWpFxYBU++Gw5dh1MUvxt7tyVpO1eiav1w2tfI1xXBOObCW9h7Y6jQpad+OT18couM/maPxnKXtZO0W/+2CH45vctSps7tqzEnHmrhasOTxn5V23Tn6KLiW0pURVcOLRqKbYfFH0lp/kK2NbVtO9EP1/DIuIq1wi92kRg/aKVyIwQ7i3qe/6jshs3V2QNNKsUjDVfzcOWA0dxUrD56PVxOCR2Aqts1H6cyK+WNTpKf4RyB7I7qCZubh6Gv//8E3+Kz7o//sS+kxrImsqWHAxYOxlH+RP79NUz8MEvm5GSmoT1P0xR/Ba3vK1DnochqihO6+gZ2fGX7Z844kb2wU1Y9sd6/L5iPub9+Bt2JQVahPXtVqlVD67cw/h9zT/KXF355Xh8uVu4syirSuw56usF5tqcGfB1oo++1UB2J7Fx4QzFB7LK227Minst0curnuvZ6c/VcurRyTiqZZ2On1peHgvLUVhT8q5NBml246HKZMdDLWd2tJtLTtYmq7mh9utEzpMHtyJB3PsSEuKxYM5kPPjYq9hwJge9hw1QXMCobfnLJWDdcvHi1eHvK+6CrqiW14JlJZud7sV6zzqbiFf6PoT+4xcJByzm4diO9VgfH6+s0XKd/uPPBLjt7pMG80nbg+V6ri3ojQfO+bxrtZM5Yjjv9X1ZyG01f+yuFSt97erqRZTngTzyrqV264qTeWXUr0yz4mDXr6xvJ7ssI4OvH4MxseLpqa35a1Df7rrT1PZF7eS2G0dHzB1ekz6hGCEBEiABEihRBNRNaSVKKApDAiRAAsVNQHzfxpbfFyBefNRQtk4nvDTkQcUvJBCJni+OQtrklzFrrHiZnijkdkXhjifGo2ts4M94lfrCLUbfUc8hd/x4fDzuJbVJ9G7YDg2rlLduS7zQRobKFQJ/+iy/zKvBJf79XfHzR+KjpoSi+8CXPS8H89ojffWFnP8dMwLHR4zFtFHDlArRV3QSPz9ejjPqT5WFvD1eHIvMt0bj23fG4Vtvs5HNe6OX7FbfptptnmMYOtx1B74f9wVGP7MKuZFd8N70O5RSPnm8dbT6qM2oZSz1Uwvrjm1u7Y6Zf3yOy2+73jtmooDQy27c/v1Eb8S//DHGPbtGabFy4/aoX2a1eIDg/xm3zFBlUwo5+eMKR5CmiTTFN7UQKXcf3h03LqAF+ULDmrqfg8sC1hyMWPe2HUfp27RK0zbY+ukEDJ7jGdjYmwZh4PU1AmTSnjitk4eRDf+MA2uw8FgWclz7sHbpMcidjUdOpuCHuZ9h6Bvv4wqvS2N9u1H1bxAvUVyBH98ZjR8lp0vaoOetl2OeZwh9ouvryV17umEVlQPHyVdZ7ITPO5d7284nf31PLMMdjJZd25vztrv2xNpT1GuJEw56dvpz7fWbcWCD9Tjq/OU6HT8ty8JzNB5PozEumrXQYzjS6hAQt7k2ZFnbtUm0YTo3oj37QqzGTfYhH/qdif8KY+PlmQyhaHLtPbj3nptQI9J/z8lbDqhUpz1GPHJvHn/ISjNWstndA0UDxXbPEj6aTouHhNnihYHZYvkzcssvdT0r3A69IT5qkPf7F6e9Yb2+mqwZ6g5P6/Vc7cl/tF13BWPbOWIjk6c3o2vDwX1b9G91reRYfU8R65pVXT8Ff8xuDbBdV5x8F/J3FxCzuo5s+xUt2cmudubvJ++YvPlsTfPvfWoDvmPe+u9NPx/3LwffPx1ckz61GCEBEiABEihxBPzfFs1F05ZR4/qjuqNZpms/Ml1/rqbJo9kn2Jsnj/q4NHzLejJdxtUy+qNapkl6evpzohwDCZAACeQhcDYtzesPOBIRgTZcX1l3ZhrSxRamsMhI3Y97fUUCImqbRuXz21ZAw+IkTcgrQ6SQxUnwlA8V5U2UE42oMoWGRgofnk5aNSqTKWTLciyXUQsyLT/6Ja37CEPfWuUxPuqMVrItVS+jcVD7cgmdzcZdljlfwZqDMWtV34BxFA8oZj81GAntR2BMz4aQczPHTueC1DEApcrj4y/a/fLpJ7CoZm+8N6Sjv8aZbXhswBh0HPEWehm5VvGXVOTPFleh1XzWFC9g1JqvTx8HrctxtJpjKqOAMdO0W5xriaab/EULMY4effI/foXjaDSeRmn+NcNsPPIHyry0Ou5mc8lOX9my1dww7/nc5FjJ5kR3adi2usbVNpyO09m0k2Ldq1iotd66T+P5pNK2Xs+9pfK57trPEWuZPL06KaNqEXi04mGnr1XdwF78Z1b6OllXPDJZzyt/b85iTvqVLVnJnrenvGNixzOwjbz1Zb7K3GzNCWzDc2Ynt9qm2XVoxbworkkjmZlGAiRAAuebQERExGghw2bxka9KyvUeZVz/kb4U1TJqXD1Xy6r15dHsI3cIqXkyrn5kmhpXjyJJKSuPMk0G/VGbphTQ/+FOZD0RnpMACVxUBMoIY6zejYEegCssEhY2WH1xWLWZ37b0jTs1Hqv1nJQvrEyevsIs/+lX5bE7OpFXtuFO3Ya3316OoPr3obGBAVmWsdPLaV+yrXMdrGUzZm2lr/pSMDk3nYaC1NG2bSRPuvCVIncESpcpnt16mdi2ZhVSxQu9wjW7uLXtaONW15a2XOHi+edr1p/1ONrPUSt9jfiayVHU6QUdRyt9rGQsHEej8TRKsx8PKxnzk2c3dnb6yr4KyjI/cha0rJVsRaG7XRt6uctEVtQn5fvcuk/j+aR24mQ81bJO1137Nq1l8vTnpIwqWeDRioedbFZ1A3vxn1m1aTXf1Bas6qtl8nt00q9sM3995x2TwtaXMhQ1cydtWsldFNeklIGBBEiABEjg3BOgEfncM2ePJEACJEACBSXg3bUqjY7uoBgMffQGR7vDC9rdhVDv7GngdJb6kNmZRgWpY9uy+Cn0zQO6YsnkzzHgwc8Dil/RfQi6G7mJCSjFkxJBgONYIoaBQlx4BIpl3b3wMFEjEiABEiABEiCB80hAdUthJYK2jBrXH6XrCBlkuvYj0/Xnapo8mn30LixkOdVdBd1ZCBgMJEACJHBxEsjEkb37cCIrBNVr1UKFMPV2dHHScKL1kR1b4Y6ui5iKdnvu/a0VpI6/tnVM/gT2QOI+xbAdFhGFatWqF+pn5ta9Mbe4CHAci4ss271YCRTnunuxMqXeJEACJEACJHAuCVwM7iyc/PetLaPG9Udp5JVBpms/Ml1/rqbJo9mHRmQBh4EESIAESIAESIAESIAESIAESIAESIAESIAESKBkE7gYjMjSiMtAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAoYEaEQ2xMJEEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABSYBGZM4DEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABUwI0IpuiYQYJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkACNyJwDJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACpgRoRDZFwwwSIAESIAESIAESIAESIAESIAESIAESIAESIAESIAEakTkHSIAESIAESIAESIAESIAESIAESIAESIAESIAESIAETAnQiGyKhhkkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAI0InMOkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJmBKgEdkUDTNIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARoROYcIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESMCVAI7IpGmaQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAnQiMw5QAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkYEqARmRTNMwgARIgARIgARIgARIgARIgARIgARIgARIgARIgARKgEZlzgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIwJQAjcimaJhBAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAIzLnAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQgCkBGpFN0TCDBEiABEiABEiABEiABEiABEiABEiABEiABEiABEiARmTOARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgAVMCNCKbomEGCZAACZAACZAACZAACZAACZAACZAACZAACZAACZAAjcicAyRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAqYEaEQ2RcMMEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABGpE5B0iABEiABEoHAXcaMtwaUcV5eqbmnNGSR4BjVvLGhBKRAAmQAAmQAAmQAAmQ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I0B3FqVvzCgxCZAACZBAERCQRlZpbD2dk4Gc3Fyxy7J0706ULizkDuTyIeE0IBfB/GATfgKVqtRCpSr+89IcqxrbuDSLT9lJgARIgARIgARIgARIgASKkQDdWRQjXDZNAiRAAqWZgDQkVwwpV5pVoOwkQAIkQAIkQAIkQAIkQAIkQAIkQAJFQEC6iWAgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgAUMCNCIbYmEiCZAACZAACZAACZAACZAACZAACZAACZAACZAACZCAJEAjMucBCZAACZAACZAACZAACZAACZAACZAACZAACZAACZCAKQEakU3RMIMESIAESIAESIAESIAESIAESIAESIAESIAESIAESIBGZM4BEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABUwI0IpuiYQYJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkACNyJwDJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACpgRoRDZFwwwSIAESIAESIAESIAESIAESIAESIAESIAESIAESIAEakTkHSIAESIAESIAESIAESIAESIAESIAESIAESIAESIAETAnQiGyKhhkkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIhREACJEACJEACdgRy3Dk4nZOBnNxcuF1uu+LnNd/ldiE4KAjlg8MR7Ao+r7KwcxIgARIozQRK09pvx5n3BjtCzCcBEiABEiABEiABawLciWzNh7kkQAIkcNETkEaEE1mpyBbHkm5AloMlZZSySpml7AwkQAIkQAL5J1Da1n47DXlvsCPEfBIgARIgARIgARKwJkAjsjUf5pIACZDARU9A7kCGqxRiEDIrspdC0SkyCZAACZxvAqV27bcDx3uDHSHmlwICZ9PSkJ5ZCgSliCRAAiRAAhcUARqRL6jhpDIkQAL5IXB071ZsTEhAgvhsiY/Htr1HkZWfBgpT1p2Gjx99GM/M2+5pRX/upO2C1HHSrq5Mdu753c176lgyTp7J60Ij5Ugy0rLzpmvFl+43SlwQ47Zi7mwsTjhe4kSjQAYEztF1ZtDzhZ2kcp27uVj0PLJjK7YdTPW1rV3vExLixbq/A8lp1uuHr3J+I6pu6vqe3/olpPz5XvvtMFxw9wY7hZlvTkC95oppPTHv+NznuNzJ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pDuhW3IKW8riVrKwHJN9rel0nDwQiUT2cjlfjaX2terMKKfc2pdbnY3qVdDpcmt3QetF8okAESACRIAIEIGSQYCcyCWjnslKIkAESiiBer3eQL0SajuZffcSKJbt2jFDkzvYbOZAjBvRLc9PNBip4bTbwO0McZKBkRySNIWks0QDChZVAmxpid7De2DHnOUYPnS5m5ZN+45BX8dyT24nCvugOOpc2MyofCJABIgAESACRIAISAiIy1JIonIEpWnEsHzPl47gG4+Xfni8/FiM43u1j3wJC55OXK6ClrNgMGgjAkSACBABIkAEihOBdFw9dwE3M7xRtUYNlPMRf0oVrA1XT5+ALaA2AsvrzeVX0qNwdFbShOKKJgG+vMLF8xeEGxU+Vn9UqVJVf5mVQjalOOpcyMioeCJABIgAESACRMAAgZKwnIWRfzDSNGJYvudOXr7xeOmHx8uPxTi+V/uQE5nBoY0IEAEiQASIABEgAkSACBABIkAEiAARIAJEgAgQgaJNoCQ4kbkTlzYiQASIABEgAkSACBABIkAEiAARIAJEgAgQASJABIgAESACigRoTWRFLBRJBIhASSCQZcvC7awUZGVnw2bK5ZqhJQEU2UgEiECRJmCymeBlNqOsly+8TPxhLtqIABEgAkSACBABIkAEiAARIAL5S4BmIucvT5JGBIhAMSHAHcg3MxKRyfbkQC4mlUZqEgEioEiAj2F8LONjGh/baCMCRIAIEAEiQASIABEgAkSACOQ3AXIi5zd5xvOxAAAgAElEQVRRkkcEiECxIMBnIAsrthcLbUlJIkAEiIABAuwtFMLYZiApJSECRIAIEAEiQASIABEgAkSACHhCgJzIntCitESACNw1BDKzabbeXVOZZAgRIAJOAnx5njxttiTsWfkttkfdUBfD0iwe8SImrTqlnobOGCdghLlxacop70QZyiVTLBEgAkSACBABIkAEiMBdQoCcyHdJRZIZRIAIeEiAzdhT26J/+wW7fzujdhq2zGTciIvD7aR01TTqJzJw63ocblxPUklil61+ns00jE9AYmKyYn6uG5efO90URXoYqWeftri0VLv+avYB+ny0Ssir/ILnq8dPz36988hj+9Vuf1rsjZ3T1z8tkfUf1v+SMnOuY65fv8a00Eql1f+08tnP6dunJ0N3fMrj+u4m23Vs3LQdq3+/5FQl4XQk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4k5Y2ogAESACJY8AHy4993EJnEzeVrbecW6RMeevY61kJQlGZGvlV5J5Z+O07dPTxYex9dFga4SPVhkFLV+rbGPntPnp2a93nutgJI2Wrlrtr5RwY0Urt/Y5I7ppla9Xv9qlGzurVb6eBCP26cnQO2+y5XJg0xMMH+b49NAz65BpYktgaGXVd6gaK1uvHC0T85JXKlfPFr3zUlla4eQU+4xhtnPMzE7HyQOR7AWNNvgqeepVhbmzLeWnMQCryqATRIAIEAEiQASIABEgAiWBADmRS0Itk41EgAjkIOBt9mKP6/KbfLQRASJABO4eAl5m/iAWbXc1AbZ8Ru/hPbBjznIMH7rczdSmfcegr2O5ELcTdEAEiAARIAJEgAgQASJABPJIgJzIeQRI2YkAESieBMp6+eJmRmKuZyMXT6tJayJABO5qAmxWallv37vaRDLOTiCw+dNY/GVfXDx/AbczbPCx+qNKlaq0DAU1ECJABIgAESACRIAIEIECI0BO5AJDS4KJABEoygS8TF6oYCmD21kpyMrOZi98EpcDKspak25EgAgQgZwE+BIWfAYydyDzsY22kkGAL8ERFNywZBhLVhIBIkAEiAARIAJEgAgUOgFyIhd6FZACRIAIFBYB7mwp712msIqncokAESACRIAIEAEiQASIABEgAkSACBABIlAsCNDCecWimkhJIkAEiAARIAJEgAgQASJABIgAESACRIAIEAEiQASIQOEQICdy4XCnUokAESACRIAIEAEiQASIABEgAkSACBABIkAEiAARIALFggA5kYtFNZGSRIAIEAEiQASIABEgAkSACBABIkAEiAARIAJEgAgQgcIhQE7kwuFOpRIBIkAEiAARIAJEgAgQASJABIgAESACRIAIEAEiQASKBQFyIheLaiIliQARIAJEgAgQASJABIgAESACRIAIEAEiQASIABEgAoVDgJzIhcOdSiUCRIAIEAEiQASIABEgAkSACBABIkAEiAARIAJEgAgUCwLkRC4W1URKEgEiQASIABEgAkSACBABIkAEiAARIAJEgAgQASJABAqHADmRC4c7lUoEiAARIAJEgAgQASJABIgAESACRIAIEAEiQASIABEoFgTIiVwsqomUJAJEgAgQASJABIgAESACRIAIEAEiQASIABEgAkSACBQOAXIiFw53KpUIEAEiQASIABEgAkSA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IUZQlzAVh59B/olZsJcC2wee2AtRH3lqKo9TgAIUoAAFKFCwBTidRcHuP9aeAhSgAAUoQAEKUMClQABuq1IDt7k8lr2dMggrg7HxGcnIyMwUN8pTp1fLXj55lVpOYSFHIIf6i5tgFoIAsnQraH3gqa8LYx95ajOPU4ACFKAABShAgfwuwOks8nsPsX4UoAAFKEABClAgnwvIIGaEf/F8XsvCXT32QeHuX7aOAhSgAAUoQAEK3GoBOU0EFwpQgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFKCASwEGkV2ycCcFKEABClCAAhSgAAUoQAEKUIACFKAABShAAQpIAQaReR1QgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFKCArgCDyLo0PEABClCAAhSgAAUoQAEKUIACFKAABShAAQpQgAIMIvMaoAAFKEABClCAAhSgAAUoQAEKUIACFKAABShAAV0BBpF1aXiAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoAAFGETmNUABClCAAhSgAAUoQAEKUIACFKAABShAAQpQgAK6Agwi69LwAAUoQAEKUIACFKAABShAAQpQgAIUoAAFKEABCjCIzGuAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoAAFdAUYRNal4QEKUIACFKAABShAAQpQgAIUoAAFKEABClCAAhRgEJnXAAUoQAEKUIACFKAABShAAQpQgAIUoAAFKEABCugKMIisS8MDFKAABShAAQpQgAIUoAAFKEABClCAAhSgAAUowCAyrwEKUIACFKAABShAAQpQgAIUoAAFKEABClCAAhTQFWAQWZeGByhAAQpQgAIUoAAFKEABClCAAhSgAAUoQAEKUIBBZF4DFKAABShAAQpQgAIUoAAFKEABClCAAhSgAAUooCvAILIuDQ9QgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFKAAg8i8BihAAQpQgAIUoAAFKEABClCAAhSgAAUoQAEKUEBXgEFkXRoeoAAFKEABClCAAhSgAAUoQAEKUIACFKAABShAAQaReQ1QgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFKCArgCDyLo0PEABClCAAhSgAAUoQAEKUIACFKAABShAAQpQgAIMIvMaoAAFKEABClCAAhSgAAUoQAEKUIACFKAABShAAV0BBpF1aXiAAhSg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ZHv9ZTcO3r3ts3/x5nb9vv3t1Ac/ub36Zx43JD63/dUn/6x908PPaHtvura9+q03DXmt7dt7S/ufL3lm+4FXnt4+etWn2m99z4faT//R4mszPvHmf9e+7dmXtT/92HXt6re+sD3m5M+2Kya+7vjLv+sZ7Zn3P7s977WXtvf98ve1e1z51vaoJ/9g+97XXNr27r+hveyp17VveOLPtquGA3Dme+1Lf6r9t888oX3iY3/cHnbaod+dafxln310u/yaT7U/+skd7Z989y+0Tw2H46znKT/2jnE9e275eHvCZT/XvvE5r218ecaeWy5vn7htvddNH/lgu2W4/x37P9V+5onf2V55wQ+2y6+/pV3/mU+1J150r/He77//L9r3Pe1N7aff/4n27pf/UPvJn3rt+BUfl//pC9q3/exV7W2fvK5d9db/3J70lWcO+WuHyDuGPxj1jue237/6MYetb2y69rLv029oj3rS09oX/+pb2nW33tqu+sAL2oX33LH0Htptn24v/Il/2C5/1M+0qy57XTvhN/9le+y3/WH7D5d+sv35b/zT9hM/9uZt/QqSut7oIRACIRACIRACIRACIRACIRACIRACIRACIXBnJnB3OEQuv+a6eKt2nvvI9rQzLm9ve+e72jtef2p7/Fd+VXv8F5zR3vOud7U/e+Vft+983EWtDb+x/Hlf+MD27v/xwvbz/+XV7d67dg6nwvvHBjvb4kD1QLtHO/3M81u74Jx2jx37264ThoPVE4fYjsX3OOxou1u78EfbJb/3I+3UE05qD774Ee2c04bj6eE3Zt/5R69oT/yZn2+ff+redlM7uz3l27683bjn8Ldj947T2zkX7mon3/PUdsIJ+9rH3/e61h72n9q3POq+7dprbm+P+/s/3B53/Yvbuz9267CqYb7hQPvlP/0d7Z479g2rO3SM8Qf/XPutH/+OdvL+k9rXfMe/aO2WT7Trbtvb3vf6PxzW8wvjeq67+ZT2Q//uWe3yP3ptu/zWA8O83NP62k5e02/92Pvbr33muvYf//XfayfvvrntHg6Bzzxl4DSMT9+2u73h/7y0ff4ZO9u593/w8DUVZ7Sdw5H0pW96eXvis36iXXyPPe3Wdv7wFR1f3m7wL+kdGNY/sb5rbzv0Pv56OMRv535/e9q3PqLtuemmdsJJJ7V7nbj8Htqem9sXPOst7aee+kVt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QAABBBBAAAEEEEAAgYYqQBC5oY48/UYAAQQQQAABBBBAAAEEEEAAAQQQQAABBGIQIIgcAxJFEEAAAQQQQAABBBBAAAEEEEAAAQQQQACBhipAELmhjjz9RgABBBBAAAEEEEAAAQQQQAABBBBAAAEEYhBIiaFMnS8yd+7cOt8HOoAAAggggAACCCCAAAIIIIAAAggggAACCOwLAWYi7wt1rokAAggggAACCCCAAAIIIIAAAggggAACCNQRgQYxE7lbt251ZDhoJgIIIIAAAggggAACCCCAAAIIIIAAAgggkFwCzEROrvGgNQgggAACCCCAAAIIIIAAAggggAACCCCAQFIJEEROquGgMQgggAACCCCAAAIIIIAAAggggAACCCCAQHIJEEROrvGgNQgggAACCCCAAAIIIIAAAggggAACCCCAQFIJEEROquGgMQgggAACCCCAAAIIIIAAAggggAACCCCAQHIJEEROrvGgNQgggAACCCCAAAIIIIAAAggggAACCCCAQFIJEEROquGgMQgggAACCCCAAAIIIIAAAggggAACCCCAQHIJEEROrvGgNQgggAACCCCAAAIIIIAAAggggAACCCCAQFIJEEROquGgMQgggAACCCCAAAIIIIAAAggggAACCCCAQHIJEEROrvGgNQgggAACCCCAAAIIIIAAAggggAACCCCAQFIJEEROquGgMQgggAACCCCAAAIIIIAAAggggAACCCCAQHIJEEROrvGgNQgggAACCCCAAAIIIIAAAggggAACCCCAQFIJEEROquGgMQgggAACCCCAAAIIIIAAAggggAACCCCAQHIJEEROrvGgNQgggAACCCCAAAIIIIAAAggggAACCCCAQFIJEEROquGgMQgggAACCCCAAAIIIIAAAggggAACCCCAQHIJEEROrvGgNQgggAACCCCAAAIIIIAAAggggAACCCCAQFIJEEROquGgMQgggAACCCCAAAIIIIAAAggggAACCCCAQHIJEEROrvGgNQgggAACCCCAAAIIIIAAAggggAACCCCAQFIJEEROquGgMQgggAACCCCAAAIIIIAAAggggAACCCCAQHIJEEROrvGgNQgggAACCCCAAAIIIIAAAggggAACCCCAQFIJEEROquGgMQgggAACCCCAAAIIIIAAAggggAACCCCAQHIJEEROrvGgNQgggAACCCCAAAIIIIAAAggggAACCCCAQFIJEEROquGgMQgggAACCCCAAAIIIIAAAggggAACCCCAQHIJEEROrvGgNQgggAACCCCAAAIIIIAAAggggAACCCCAQFIJEEROquGgMQgggAACCCCAAAIIIIAAAggggAACCCCAQHIJEEROrvGgNQgggAACCCCAAAIIIIAAAggggAACCCCAQFIJEEROquGgMQgggAACCCCAAAIIIIAAAggggAACCCCAQHIJEEROrvGgNQgggAACCCCAAAIIIIAAAggggAACCCCAQFIJEEROquGgMQgggAACCCCAqn1DPwAAIABJREFUAAIIIIAAAggggAACCCCAQHIJEEROrvGgNQgggAACCCCAAAIIIIAAAggggAACCCCAQFIJEEROquGgMQgggAACCCCAAAIIIIAAAggggAACCCCAQHIJEEROrvGgNQgggAACCCCAAAIIIIAAAggggAACCCCAQFIJEEROquGgMQgggAACCCCAAAIIIIAAAggggAACCCCAQHIJEEROrvGgNQgggAACCCCAAAIIIIAAAggggAACCCCAQFIJEEROquGgMQgggAACCCCAAAIIIIAAAggggAACCCCAQHIJpCRXc2gNAggkk4DL5fI3x+l0+tdZQQABBBBAAAEEEEAAAQQQQAABBBBoOAIEkRvOWNPT+ijgKZJ1K9dKgcdTTe+ckpWTLdnZmZKdmVlNWe/h4l+myZWT3vKXHfn3B2V090b+bVYQQAABBBBAAAEEEEAAAQQQQAABBBqGAEHkhjHO9LKeCniK1spDDz0UQxA5CMCWLT2PHCajRg6Rrs2zgg6ErpZJUegOthBAAAEEEEAAAQQQQAABBBBAAAEEGqQAOZEb5LDT6foiYNOvgRrZ4uyNZ6csm/2e3D/x7/Lom99LWZynUxwBBBBAAAEEEEAAAQQQQAABBBBAoGEJEERuWONNbxuAgC0lRVLCHtG6vfSzZ2TSu8uiHWY/AggggAACCCCAAAIIIIAAAggggAACQjoLXgQI1CeBpsfKI/eMkfQIfSrM3yiLZ0+V59+bF3L0948ny8LBj8tBzflOKQSGDQQQQAABBBBAAAEEEEAAAQQQQAABS4CoES8EBOqRgD1S9Liif1k5reSIEy+UJ++8RFNgBOfAKJPPvvu1HinQFQQQQAABBBBAAAEEEEAAAQQQQACBRAoQRE6k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AhSgAAUoQAEKeASOhSAyy1nwbqcABShAgWNWQP2pf5PW7Y+p8z8Wz/mYusA8WQpQgAIUoAAFKEABClCAAtUgoDKBOVGAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoAAFggowiByUhSspQAEKUIACFKAABShAAQpQgAIUoAAFKEABClBACTCIzPuAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoAAFQgowiByShhsoQAEKUIACFKAABShAAQpQgAIUoAAFKEABClCAQWTeAxSgAAUoQAEKUIACFKAABShAAQpQgAIUoAAFKBBSgEHkkDTcQAEKUIACFKAABShAAQpQgAIUoAAFKEABClCAAgwi8x6gAAUoQAEKUIACFKAABShAAQpQgAIUoAAFKECBkAIMIoek4QYKUIACFKAABShAAQpQgAIUoAAFKEABClCAAhRgEJn3AAUoQAEKUIACFKAABShAAQpQgAIUoAAFKEABCoQUYBA5JA03UIACFKAABShAAQpQgAIUoAAFKEABClCAAhSgAIPIvAcoQAEKUIACFKAABShAAQpQgAIUoAAFKEABClAgpACDyCFpuIECFKAABShAAQpQgAIUoAAFKEABClCAAhSgAAUYROY9QAEKUIACFKAABShAAQpQgAIUoAAFKEABClCAAiEFGEQOScMNFKAABShAAQpQgAIUoAAFKEABClCAAhSgAAUowCAy7wEKUIACFKAABShAAQpQgAIUoAAFKEABClCAAhQIKcAgckgabqAABShAAQpQgAIUoAAFKEABClCAAhSgAAUoQAEGkXkPUIACFKAABShAAQpQgAIUoAAFKEABClCAAhSgQEgBBpFD0nADBShAAQpQgAIUoAAFKEABClCAAhSgAAUoQAEKMIjMe4ACFKAABShAAQpQgAIUoAAFKEABClCAAhSgAAVCCjCIHJKGGyhAAQpQgAIUoAAFKEABClCAAhSgAAUoQAEKUIBBZN4DFKAABShAAQpQgAIUoAAFKEABClCAAhSgAAUoEFKAQeSQNNxAAQpQgAIUoAAFKEABClCAAhSgAAUoQAEKUIACDCLzHqAABShAAQpQgAIUoAAFKEABClCAAhSgAAUoQIGQAgwih6ThBgpQgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFGAQmfcABShAAQpQgAIUoAAFKEABClCAAhSgAAUoQAEKhBRgEDkkDTdQgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFKAAg8i8ByhAAQpQgAIUoAAFKEABClCAAhSgAAUoQAEKUCCkAIPIIWm4gQIUoAAFKEABClCAAhSgAAUoQAEKUIACFKAABRhE5j1AAQpQgAIUoAAFKEABClCAAhSgAAUoQAEKUIACIQUYRA5Jww0UoAAFKEABClCAAhSgAAUoQAEKUIACFKAABSjAIDLvAQpQgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFAgpwCBySBpuoAAFKEABClCAAhSgAAUoQAEKUIACFKAABShAAQaReQ9QgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFKBASAEGkUPScAMFKEABClCAAhSgAAUoQAEKUIACFKAABShAAQowiMx7gAIUoAAFKEABClCAAhSgAAUoQAEKUIACFKAABUIKMIgckoYbKEABClCAAhSgAAUoQAEKUIACFKAABShAAQpQgEFk3gMUoAAFKEABClCAAhSgAAUoQAEKUIACFKAABSgQUoBB5JA03EABClCAAhSgAAUoQAEKUIACFKAABShAAQpQgAIMIvMeoAAFKEABClCAAhSgAAUoQAEKUIACFKAABShAgZACDCKHpOEGClCAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUYBCZ9wAFKEABClCAAhSgAAUoQAEKUIACFKAABShAAQqEFGAQOSQNN1CAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoACDyLwHKEABClCAAhSgAAUoQAEKUIACFKAABShAAQpQIKQAg8ghabiBAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoAAFGETmPUABClCAAhSgAAUoQAEKUIACFKAABShAAQpQgAIhBRhEDknDDRSgAAUoQAEKUIACFKAABShAAQpQgAIUoAAFKMAgMu8BClCAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUCCnAIHJIGm6gAAUoQAEKUIACFKAABShAAQpQgAIUoAAFKEABBpF5D1CAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoEBIAQaRQ9JwAwUoQAEKUIACFKAABShAAQpQgAIUoAAFKEABCjCIzHuAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoAAFQgowiByShhsoQAEKUIACFKAA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KEABClCAAhSgAAUoQAEKUIACFKCAbwkwiOxb54O9oQAFKEABClCAAhSgAAUoQAEKUIACFKAABSjgUwIMIvvU6WBnKEABClCAAhSgAAUoQAEKUIACFKAABShAAQr4lgCDyL51PtgbClCAAhSgAAUoQAEKUIACFKAABShAAQpQgAI+JcAgsk+dDnaGAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoIBvCTCI7Fvng72hAAUoQAEKUIACFKAABShAAQpQgAIUoAAFKOBTAgwi+9TpYGcoQAEKUIACFKAABShAAQpQgAIUoAAFKEABCviWAIPIvnU+2BsKUIACFKAABShAAQpQgAIUoAAFKEABClCAAj4lwCCyT50OdoYCFKAABShAAQpQgAIUoAAFKEABClCAAhSggG8JMIjsW+eDvaEABShAAQpQgAIUoAAFKEABClCAAhSgAAUo4FMCDCL71OlgZyhAAQpQgAIUoAAFKEABClCAAhSgAAUoQAEK+JYAg8i+dT7YGwpQgAIUoAAFKEABClCAAhSgAAUoQAEKUIACPiXAILJPnQ52hgIUoAAFKEABClCAAhSgAAUoQAEKUIACFKCAbwkwiOxb54O9oQAFKEABClCAAhSgAAUoQAEKUIACFKAABSjgUwIMIvvU6WBnKEABClCAAhSgAAUoQAEKUIACFKAABShAAQr4lgCDyL51PtgbClCAAhSgAAUoQAEKUIACFKAABShAAQpQgAI+JcAgsk+dDnaGAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoIBvCTCI7Fvng72hAAUoQAEKUIACFKAABShAAQpQgAIUoAAFKOBTAgwi+9TpYGcoQAEKUIACFKAABShAAQpQgAIUoAAFKEABCviWAIPIvnU+2BsKUIACFKAABShAAQpQgAIUoAAFKEABClCAAj4lwCCyT50OdoYCFKAABShAAQpQgAIUoAAFKEABClCAAhSggG8JMIjsW+eDvaEABShAAQpQgAIUoAAFKEABClCAAhSgAAUo4FMCDCL71OlgZyhAAQpQgAIUoAAFKEABClCAAhSgAAUoQAEK+JYAg8i+dT7YGwpQgAIUoAAFKEABClCAAhSgAAUoQAEKUIACPiXAILJPnQ52hgIUoAAFKEABClCAAhSgAAUoQAEKUIACFKCAbwkwiOxb54O9oQAFKEABClCAAhSg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jkZEBIhAfSEQFtVYMPXnJdPx/vYbZmaXuycgQAjhw+ImK5LOORITp41Gi8buyN7xKd5L+1MhQadEgAgQASJABIgAESACRIBiItMaIAJEgAgQgTudgHsUXnx5Gq5qXREaEQEfCtNwp884jY8INDgCN4utD/m+SUnwYhF89mz4yUywkn251q1PEpqymMgB+TGsnpzIZpCogAgQASJABIgAESACRIA2Y9EaIAJEgAgQgTudgCuaRESjyZ0+TBofESACDZIAj2nct7W4E9kSAF6f0j0CuusspM+3J8xEKl3CDP8QaMuKzOqpgAgQASJABIgAESACRIAIcAIUzoLWAREgAkSACBABIkAEiAARqIcE+k19HzMGNhcsr8w7io27zcNV9H3qcUR7aLAv7SNkVUrvTzEOtuP9SQhku5Bx8zyWLdllrKAcESACRIAIEAEiQASIABGQESAnsgwGZYkAESACRIAIEAEiQASIQH0hsHP1Unya3x7l2UfwLXuhnqW0d90izNzjhL37My1VIyTYm72buwzHN3+JbWX8BeGUiAARIAJEgAgQASJABIiAOQFyIpszoRIiQASIABEgAkSACBABIlDnCdzMPIBv2MdaKj19BntPq0tsfC8VG99Tr6caIkAEiAARIAJEgAgQASLACTgRBiJABIgAESACRIAIEAEiQASIABEgAkSACBABIkAEiAARIAJqBMiJrEaGyokAESACRIAIEAEiQASIABEgAkSACBABIkAEiAARIAJEgHYi0xogAkSACBABIkAEiAARIAJEgAgQASJABIgAESACRIAIEAF1ArQTWZ0N1RABIkAEiAARIAJEgAgQASJABIgAESACRIAIEAEiQAQaPAFyIjf4JUAAiAARIAJEgAgQASJABIgAESACRIAIEAEiQASIABEgAuoEyImszoZqiAARIAJEgAgQASJABIgAESACRIAIEAEiQASIABEgAg2eADmRG/wSIABEgAgQASJABIgAESACRIAIEAEiQASIABEgAkSACBABdQLkRFZnQzVEgAgQASJABIgAESACRIAIEAEiQASIABEgAkSACBCBBk+AnMgNfgkQACJABIgAESACRIAIEAEiQASIABEgAkSACBABIkAEiIA6AXIiq7OhGiJABIgAESACRIAIEAEiQASIABEgAkSACBABIkAEiECDJ0BO5Aa/BAgAESAC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AgQIECBAgAABAgRcIvsbIECAAAECBAgQIECAAAECBAgQIECAAIFDAZfIhzQWCBAgQIAAAQIECBAgQIAAAQIECBAgQMAlsr8BAgQIECBAgAABAgQIECBAgAABAgQIEDgUcIl8SGOBAAECBAgQIECAAAECBAgQIECAAAECBFwi+xsgQIAAAQIECBAgQIAAAQIECBAgQIAAgUMBl8iHNBYIECBAgAABAgQIECBAgAABAgQIECBAwCWyvwECBAgQIECAAAECBAgQIECAAAECBAgQOBRwiXxIY4EAAQIECBAgQIAAAQIECBAgQIAAAQIEXCL7GyBAgAABAgQIECBAgAABAgQIECBAgACBQwGXyIc0FggQIECAAAECBAgQIECAAAECBAgQIEDAJbK/AQIECBAgQIAAAQIECBAgQIAAAQIECBA4FHCJfEhjgQABAgQIECBAgAABAgQIECBAgAABAgRcIvsbIECAAAECBAgQIECAAAECBAgQIECAAIFDAZfIhzQWCBAgQIAAAQIECBAgQIAAAQIECBAgQMAlsr8BAgQIECBAgAABAgQIECBAgAABAgQIEDgUcIl8SGOBAAECBAgQIECAAAECBAgQIECAAAECBFwi+xsgQIAAAQIECBAgQIAAAQIECBAgQIAAgUMBl8iHNBYIECBAgAABAgQIECBAgAABAgQIECBAwCWyvwECBAgQIECAAAECBAgQIECAAAECBAgQOBRwiXxIY4EAAQIECBAgQIAAAQIECBAgQIAAAQIEXCL7GyBAgAABAgQIECBAgAABAgQIECBAgACBQwGXyIc0FggQIECAAAECBAgQIECAAAECBAgQIEDAJbK/AQIECBAgQIAAAQIECBAgQIAAAQIECBA4FHCJfEhjgQABAgQIECBAgAABAgQIECBAgAABAgRcIvsbIECAAAECBAgQIECAAAECBAgQIECAAIFDAZfIhzQWCBAgQIAAAQIECBAgQIAAAQIECBAgQMAlsr8BAgQIECBAgAABAgQIECBAgAABAgQIEDgUcIl8SGOBAAECBAgQIECAAAECBAgQIECAAAECBFwi+xsgQIAAAQIECBAgQIAAAQIECBAgQIAAgUMBl8iHNBYIECBAgAABAgQIECBAgAABAgQIECBAwCWyvwECBAgQIECAAAECBAgQIECAAAECBAgQOBRwiXxIY4EAAQIECBAg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z+VH/bMuJ0CAAAECBAgQIECAAAECBAgQIEDgbQTWi9Y+ddaP8vR27SiuPe1rPfNdbbe+601fxrm1rj82vvsxn9n6rta1i2IvTi9qPtO0O+eS2uxJvs77yLnWnrXWevasa+fOmWvdO+Oat79xPre1xnNr7REJECBAgAABAgQIECBAgAABAgQIEHi5wLnL0kvX2rfGvt2sN89a88TmrXc+13a19idmzP7OHxfe/egZt9Tmnmfze11yHp2z1i+Zz5413813tX7xriU2362ldrT+3Np6XuciAQIECBAgQIAAAQIECBAgQIAAAQKfVuCSi9bZM/O8eedr7LdKfbc26z3nqDbPmnnPnbXmic+tt3fta/3iuF6cXrxx03h01lq/dD771rzzGZvn1Zo37mpzbbc+a8nXse7v+lG96yIBAgQIECBAgAABAgQIECBAgAABAq8rcHRxelTP28y15o19287XOPd3rbXOZ2zenqPz1/ql86O+1q+K977w3J13S617GvOl1nydt+eoPmHa09i9s2etzd727WpdEwkQIECAAAECBAgQIECAAAECBAgQ+HwE5sVt32rWZn5ufe3rvDF7k3feuNY7T8xoX+OsPTa8+zHXW7+01v6r4r0vQc+dt1tba3PevLFfbM6Tr/P0tdZ4VEs9Y9e31h8blx9z37L0fnpJz/tmCQECBAgQIECAAAECBAgQIECAAAECVwvsLlHXQ57rmetHec/semPqzdfYtdY7T+zoWmPqM9/Nj2qpZ6z7n6o3/HyNC85zZ+7W1trRfNZ3+ayFovM1lqn12du1XW32t29X65pIgAABAgQIECBAgAABAgQIECBAgMDnI7C7VF1r6zxvP2szn2utN/Zbd94498x8rs/6ek7nu55L12bfRflrXYIenXtpfe3rvLFfbjdfa+ltrXHWetZam72zZ+aX9Mx+OQECBAgQIECAAAECBAgQIECAAAECn0ZgvajdvcXsmXl7Z615Y3sSU1vrR/Ojes9b12+td9/V8TUvQY/Ovqa+9nbe2C98NF/r6Z+1o7znNs6+c7WuiQQIECBAgAABAgQIECBAgAABAgQIfH4CuwvZXa1vPteO8rV39mXtaH5U73m7vV1b9z5X7/pNcXc5etNBm03PnX20vtbXeR7VWmMfv85n75p3z66+nrPO595z+a37zp1pjQABAgQIECBAgAABAgQIECBAgACB7wocXax+t/PjyrrvuXl3z76Z79ZTa09j++Zaa7ueXV/7G4/2df2m+NqXnM+df7S+q5+rnVtbYWbvzNe+zI/Wj+rrGZf2rfvMCRAgQIAAAQIECBAgQIAAAQIECBC4TuDSC9SjvqN632Kuz7zribt6a42X9s++o7Nnz+78uX5z/haXnM8949z6bu1cbbcWnKN64db1dd6+c/GWPefOs0aAAAECBAgQIECAAAECBAgQIECAwMsEbrlYXfes8/WNjtZbb5z7Lq11z66/a4nPrc/eq/O3vPh87llH6y+pH+0N1Lm1Qp7rObfW/SIBAgQIECBAgAABAgQIECBAgAABAp+PwLnL1nNr/QbneubazLs38V71nnl0XtfvEt/6IvSS5x31XFsP0Lpnne8QL+nZ7Wvtpft7jkiAAAECBAgQIECAAAECBAgQIECAwG0CL71cvWT/2rPO55sfrV1bv+TM2XOX/Iu7nHLdIZdcsp7ruXXt6C3PnXfPPUdnqRMgQIAAAQIECBAgQIAAAQIECBAg8HYCRxe3595gt2dXm2ecW791reef29+eu8VbLlDv9fBLnv1cz0vX+13OnXNurftFAgQIECBAgAABAgQIECBAgAABAgS+vwLnLmXPrc1v/FzfS9fzrOfOmO9zt/xTX5Be8/znep9bD9olPTvcW/ftzlIjQIAAAQIECBAgQIAAAQIECBAgQODzEbj1YvaSfc/1PLc+la7pnftenH8ul6PXvMclvZf0rHi37FnPMCdAgAABAgQIECBAgAABAgQIECBA4IcjcMvF7SV7Lump4jW93XPX+DlenF7zTtf0Bu7a/iPse51zdL46AQIECBAgQIAAAQIECBAgQIAAAQKvI3CvS9lrz7mm/5re11Eap37Ol6HXvtu1/YPhMX3p/vU8cwIECBAgQIAAAQIECBAgQIAAAQIEvt8CL73MvXb/tf1vovt9uTi99T1v3Xcp/muff+l76CNAgAABAgQIECBAgAABAgQIECBA4LzAa1/Q3nr+rfvOf9s7rn4fL0Hv9c73OueOvw5HESBAgAABAgQIECBAgAABAgQIECDwGQvc68L3Xue8CdUP4SL1rb7DWz3nTX7xHkKAAAECBAgQIECAAAECBAgQIECAwMNbXea+1XNe5Vf6Q70Y/aF+r1f5I3AoAQIECBAgQIAAAQIECBAgQIAAAQJ3E/heXxjvFH6Ml60/xu+8+92rESBAgAABAgQIECBAgAABAgQIECBwm8AP7qL4HIML1XM6+zVmexdVAgQIECBAgAABAgQIECBAgAABAt8XgR/VJfD35ZfiPQkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECry3w/wE3OrlYJLDaPQAAAABJRU5ErkJggg=="; - - if (typeof process !== 'undefined' && !process.browser) { - module.exports = bigimage; - } else { - window.bigimage = bigimage; - } - -})();
diff --git a/tests/integration/deps/pouchdb-1.1.0-postfixed.js b/tests/integration/deps/pouchdb-1.1.0-postfixed.js deleted file mode 100644 index b832ce4..0000000 --- a/tests/integration/deps/pouchdb-1.1.0-postfixed.js +++ /dev/null
@@ -1,5892 +0,0 @@ -!function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.PouchDBVersion110=e():"undefined"!=typeof global?global.PouchDBVersion110=e():"undefined"!=typeof self&&(self.PouchDBVersion110=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);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ -/*globals cordova */ - -"use strict"; - -var utils = require('./utils'); -var merge = require('./merge'); -var errors = require('./deps/errors'); -var call = utils.call; - -/* - * A generic pouch adapter - */ - -// returns first element of arr satisfying callback predicate -function arrayFirst(arr, callback) { - for (var i = 0; i < arr.length; i++) { - if (callback(arr[i], i) === true) { - return arr[i]; - } - } - return false; -} - -// Wrapper for functions that call the bulkdocs api with a single doc, -// if the first result is an error, return an error -function yankError(callback) { - return function (err, results) { - if (err || results[0].error) { - call(callback, err || results[0]); - } else { - call(callback, null, results[0]); - } - }; -} - -// for every node in a revision tree computes its distance from the closest -// leaf -function computeHeight(revs) { - var height = {}; - var edges = []; - merge.traverseRevTree(revs, function (isLeaf, pos, id, prnt) { - var rev = pos + "-" + id; - if (isLeaf) { - height[rev] = 0; - } - if (prnt !== undefined) { - edges.push({from: prnt, to: rev}); - } - return rev; - }); - - edges.reverse(); - edges.forEach(function (edge) { - if (height[edge.from] === undefined) { - height[edge.from] = 1 + height[edge.to]; - } else { - height[edge.from] = Math.min(height[edge.from], 1 + height[edge.to]); - } - }); - return height; -} - -module.exports = function (Pouch) { - return function (opts, callback) { - var api = {}; - - var customApi = Pouch.adapters[opts.adapter](opts, function (err, db) { - if (err) { - if (callback) { - callback(err); - } - return; - } - - for (var j in api) { - if (!db.hasOwnProperty(j)) { - db[j] = api[j]; - } - } - - // Don't call Pouch.open for ALL_DBS - // Pouch.open saves the db's name into ALL_DBS - if (opts.name === Pouch.prefix + Pouch.ALL_DBS) { - callback(err, db); - } else { - Pouch.open(opts, function (err) { - callback(err, db); - }); - } - }); - - var auto_compaction = (opts.auto_compaction === true); - - // wraps a callback with a function that runs compaction after each edit - function autoCompact(callback) { - if (!auto_compaction) { - return callback; - } - return function (err, res) { - if (err) { - call(callback, err); - } else { - var count = res.length; - var decCount = function () { - count--; - if (!count) { - call(callback, null, res); - } - }; - res.forEach(function (doc) { - if (doc.ok) { - // TODO: we need better error handling - compactDocument(doc.id, 1, decCount); - } else { - decCount(); - } - }); - } - }; - } - - api.post = function (doc, opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - if (typeof doc !== 'object' || Array.isArray(doc)) { - return call(callback, errors.NOT_AN_OBJECT); - } - return customApi.bulkDocs({docs: [doc]}, opts, - autoCompact(yankError(callback))); - }; - - api.put = function (doc, opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - if (typeof doc !== 'object') { - return call(callback, errors.NOT_AN_OBJECT); - } - if (!utils.isValidId(doc._id)) { - return call(callback, errors.MISSING_ID); - } - return customApi.bulkDocs({docs: [doc]}, opts, - autoCompact(yankError(callback))); - }; - - api.putAttachment = function (docId, attachmentId, rev, blob, type, callback) { - if (!api.taskqueue.ready()) { - api.taskqueue.addTask('putAttachment', arguments); - return; - } - if (typeof type === 'function') { - callback = type; - type = blob; - blob = rev; - rev = null; - } - if (typeof type === 'undefined') { - type = blob; - blob = rev; - rev = null; - } - - function createAttachment(doc) { - doc._attachments = doc._attachments || {}; - doc._attachments[attachmentId] = { - content_type: type, - data: blob - }; - api.put(doc, callback); - } - - api.get(docId, function (err, doc) { - // create new doc - if (err && err.error === errors.MISSING_DOC.error) { - createAttachment({_id: docId}); - return; - } - if (err) { - call(callback, err); - return; - } - - if (doc._rev !== rev) { - call(callback, errors.REV_CONFLICT); - return; - } - - createAttachment(doc); - }); - }; - - api.removeAttachment = function (docId, attachmentId, rev, callback) { - api.get(docId, function (err, obj) { - if (err) { - call(callback, err); - return; - } - if (obj._rev !== rev) { - call(callback, errors.REV_CONFLICT); - return; - } - if (!obj._attachments) { - return call(callback, null); - } - delete obj._attachments[attachmentId]; - if (Object.keys(obj._attachments).length === 0) { - delete obj._attachments; - } - api.put(obj, callback); - }); - }; - - api.remove = function (doc, opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - if (opts === undefined) { - opts = {}; - } - opts.was_delete = true; - var newDoc = {_id: doc._id, _rev: doc._rev}; - newDoc._deleted = true; - return customApi.bulkDocs({docs: [newDoc]}, opts, yankError(callback)); - }; - - api.revsDiff = function (req, opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - var ids = Object.keys(req); - var count = 0; - var missing = {}; - - function addToMissing(id, revId) { - if (!missing[id]) { - missing[id] = {missing: []}; - } - missing[id].missing.push(revId); - } - - function processDoc(id, rev_tree) { - // Is this fast enough? Maybe we should switch to a set simulated by a map - var missingForId = req[id].slice(0); - merge.traverseRevTree(rev_tree, function (isLeaf, pos, revHash, ctx, - opts) { - var rev = pos + '-' + revHash; - var idx = missingForId.indexOf(rev); - if (idx === -1) { - return; - } - - missingForId.splice(idx, 1); - if (opts.status !== 'available') { - addToMissing(id, rev); - } - }); - - // Traversing the tree is synchronous, so now `missingForId` contains - // revisions that were not found in the tree - missingForId.forEach(function (rev) { - addToMissing(id, rev); - }); - } - - ids.map(function (id) { - customApi._getRevisionTree(id, function (err, rev_tree) { - if (err && err.name === 'not_found' && err.message === 'missing') { - missing[id] = {missing: req[id]}; - } else if (err) { - return call(callback, err); - } else { - processDoc(id, rev_tree); - } - - if (++count === ids.length) { - return call(callback, null, missing); - } - }); - }); - }; - - // compact one document and fire callback - // by compacting we mean removing all revisions which - // are further from the leaf in revision tree than max_height - function compactDocument(docId, max_height, callback) { - customApi._getRevisionTree(docId, function (err, rev_tree) { - if (err) { - return call(callback); - } - var height = computeHeight(rev_tree); - var candidates = []; - var revs = []; - Object.keys(height).forEach(function (rev) { - if (height[rev] > max_height) { - candidates.push(rev); - } - }); - - merge.traverseRevTree(rev_tree, function (isLeaf, pos, revHash, ctx, opts) { - var rev = pos + '-' + revHash; - if (opts.status === 'available' && candidates.indexOf(rev) !== -1) { - opts.status = 'missing'; - revs.push(rev); - } - }); - customApi._doCompaction(docId, rev_tree, revs, callback); - }); - } - - // compact the whole database using single document - // compaction - api.compact = function (opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - api.changes({complete: function (err, res) { - if (err) { - call(callback); // TODO: silently fail - return; - } - var count = res.results.length; - if (!count) { - call(callback); - return; - } - res.results.forEach(function (row) { - compactDocument(row.id, 0, function () { - count--; - if (!count) { - call(callback); - } - }); - }); - }}); - }; - - /* Begin api wrappers. Specific functionality to storage belongs in the _[method] */ - api.get = function (id, opts, callback) { - if (!api.taskqueue.ready()) { - api.taskqueue.addTask('get', arguments); - return; - } - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - - var leaves = []; - function finishOpenRevs() { - var result = []; - var count = leaves.length; - if (!count) { - return call(callback, null, result); - } - // order with open_revs is unspecified - leaves.forEach(function (leaf) { - api.get(id, {rev: leaf, revs: opts.revs}, function (err, doc) { - if (!err) { - result.push({ok: doc}); - } else { - result.push({missing: leaf}); - } - count--; - if (!count) { - call(callback, null, result); - } - }); - }); - } - - if (opts.open_revs) { - if (opts.open_revs === "all") { - customApi._getRevisionTree(id, function (err, rev_tree) { - if (err) { - // if there's no such document we should treat this - // situation the same way as if revision tree was empty - rev_tree = []; - } - leaves = merge.collectLeaves(rev_tree).map(function (leaf) { - return leaf.rev; - }); - finishOpenRevs(); - }); - } else { - if (Array.isArray(opts.open_revs)) { - leaves = opts.open_revs; - for (var i = 0; i < leaves.length; i++) { - var l = leaves[i]; - // looks like it's the only thing couchdb checks - if (!(typeof(l) === "string" && /^\d+-/.test(l))) { - return call(callback, errors.error(errors.BAD_REQUEST, - "Invalid rev format")); - } - } - finishOpenRevs(); - } else { - return call(callback, errors.error(errors.UNKNOWN_ERROR, - 'function_clause')); - } - } - return; // open_revs does not like other options - } - - return customApi._get(id, opts, function (err, result) { - if (err) { - return call(callback, err); - } - - var doc = result.doc; - var metadata = result.metadata; - var ctx = result.ctx; - - if (opts.conflicts) { - var conflicts = merge.collectConflicts(metadata); - if (conflicts.length) { - doc._conflicts = conflicts; - } - } - - if (opts.revs || opts.revs_info) { - var paths = merge.rootToLeaf(metadata.rev_tree); - var path = arrayFirst(paths, function (arr) { - return arr.ids.map(function (x) { return x.id; }) - .indexOf(doc._rev.split('-')[1]) !== -1; - }); - - path.ids.splice(path.ids.map(function (x) {return x.id; }) - .indexOf(doc._rev.split('-')[1]) + 1); - path.ids.reverse(); - - if (opts.revs) { - doc._revisions = { - start: (path.pos + path.ids.length) - 1, - ids: path.ids.map(function (rev) { - return rev.id; - }) - }; - } - if (opts.revs_info) { - var pos = path.pos + path.ids.length; - doc._revs_info = path.ids.map(function (rev) { - pos--; - return { - rev: pos + '-' + rev.id, - status: rev.opts.status - }; - }); - } - } - - if (opts.local_seq) { - doc._local_seq = result.metadata.seq; - } - - if (opts.attachments && doc._attachments) { - var attachments = doc._attachments; - var count = Object.keys(attachments).length; - if (count === 0) { - return call(callback, null, doc); - } - Object.keys(attachments).forEach(function (key) { - customApi._getAttachment(attachments[key], {encode: true, ctx: ctx}, function (err, data) { - doc._attachments[key].data = data; - if (!--count) { - call(callback, null, doc); - } - }); - }); - } else { - if (doc._attachments) { - for (var key in doc._attachments) { - doc._attachments[key].stub = true; - } - } - call(callback, null, doc); - } - }); - }; - - api.getAttachment = function (docId, attachmentId, opts, callback) { - if (!api.taskqueue.ready()) { - api.taskqueue.addTask('getAttachment', arguments); - return; - } - if (opts instanceof Function) { - callback = opts; - opts = {}; - } - customApi._get(docId, opts, function (err, res) { - if (err) { - return call(callback, err); - } - if (res.doc._attachments && res.doc._attachments[attachmentId]) { - opts.ctx = res.ctx; - customApi._getAttachment(res.doc._attachments[attachmentId], opts, callback); - } else { - return call(callback, errors.MISSING_DOC); - } - }); - }; - - api.allDocs = function (opts, callback) { - if (!api.taskqueue.ready()) { - api.taskqueue.addTask('allDocs', arguments); - return; - } - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - if ('keys' in opts) { - if ('startkey' in opts) { - call(callback, errors.error(errors.QUERY_PARSE_ERROR, - 'Query parameter `start_key` is not compatible with multi-get' - )); - return; - } - if ('endkey' in opts) { - call(callback, errors.error(errors.QUERY_PARSE_ERROR, - 'Query parameter `end_key` is not compatible with multi-get' - )); - return; - } - } - if (typeof opts.skip === 'undefined') { - opts.skip = 0; - } - - return customApi._allDocs(opts, callback); - }; - - function processChange(doc, metadata, opts) { - var changeList = [{rev: doc._rev}]; - if (opts.style === 'all_docs') { - changeList = merge.collectLeaves(metadata.rev_tree) - .map(function (x) { return {rev: x.rev}; }); - } - var change = { - id: metadata.id, - changes: changeList, - doc: doc - }; - - if (utils.isDeleted(metadata, doc._rev)) { - change.deleted = true; - } - if (opts.conflicts) { - change.doc._conflicts = merge.collectConflicts(metadata); - if (!change.doc._conflicts.length) { - delete change.doc._conflicts; - } - } - return change; - } - api.changes = function (opts) { - if (!api.taskqueue.ready()) { - var task = api.taskqueue.addTask('changes', arguments); - return { - cancel: function () { - if (task.task) { - return task.task.cancel(); - } - if (Pouch.DEBUG) { - //console.log('Cancel Changes Feed'); - } - task.parameters[0].aborted = true; - } - }; - } - opts = utils.extend(true, {}, opts); - opts.processChange = processChange; - - if (!opts.since) { - opts.since = 0; - } - if (opts.since === 'latest') { - var changes; - api.info(function (err, info) { - if (!opts.aborted) { - opts.since = info.update_seq - 1; - api.changes(opts); - } - }); - // Return a method to cancel this method from processing any more - return { - cancel: function () { - if (changes) { - return changes.cancel(); - } - if (Pouch.DEBUG) { - //console.log('Cancel Changes Feed'); - } - opts.aborted = true; - } - }; - } - - if (opts.filter && typeof opts.filter === 'string') { - if (opts.filter === '_view') { - if (opts.view && typeof opts.view === 'string') { - // fetch a view from a design doc, make it behave like a filter - var viewName = opts.view.split('/'); - api.get('_design/' + viewName[0], function (err, ddoc) { - if (ddoc && ddoc.views && ddoc.views[viewName[1]]) { - /*jshint evil: true */ - var filter = eval('(function () {' + - ' return function (doc) {' + - ' var emitted = false;' + - ' var emit = function (a, b) {' + - ' emitted = true;' + - ' };' + - ' var view = ' + ddoc.views[viewName[1]].map + ';' + - ' view(doc);' + - ' if (emitted) {' + - ' return true;' + - ' }' + - ' }' + - '})()'); - if (!opts.aborted) { - opts.filter = filter; - api.changes(opts); - } - } else { - var msg = ddoc.views ? 'missing json key: ' + viewName[1] : - 'missing json key: views'; - err = err || errors.error(errors.MISSING_DOC, msg); - utils.call(opts.complete, err); - } - }); - } else { - var err = errors.error(errors.BAD_REQUEST, - '`view` filter parameter is not provided.'); - utils.call(opts.complete, err); - } - } else { - // fetch a filter from a design doc - var filterName = opts.filter.split('/'); - api.get('_design/' + filterName[0], function (err, ddoc) { - if (ddoc && ddoc.filters && ddoc.filters[filterName[1]]) { - /*jshint evil: true */ - var filter = eval('(function () { return ' + - ddoc.filters[filterName[1]] + ' })()'); - if (!opts.aborted) { - opts.filter = filter; - api.changes(opts); - } - } else { - var msg = (ddoc && ddoc.filters) ? 'missing json key: ' + filterName[1] - : 'missing json key: filters'; - err = err || errors.error(errors.MISSING_DOC, msg); - utils.call(opts.complete, err); - } - }); - } - // Return a method to cancel this method from processing any more - return { - cancel: function () { - if (Pouch.DEBUG) { - console.log('Cancel Changes Feed'); - } - opts.aborted = true; - } - }; - } - - if (!('descending' in opts)) { - opts.descending = false; - } - - // 0 and 1 should return 1 document - opts.limit = opts.limit === 0 ? 1 : opts.limit; - return customApi._changes(opts); - }; - - api.close = function (callback) { - if (!api.taskqueue.ready()) { - api.taskqueue.addTask('close', arguments); - return; - } - return customApi._close(callback); - }; - - api.info = function (callback) { - if (!api.taskqueue.ready()) { - api.taskqueue.addTask('info', arguments); - return; - } - return customApi._info(callback); - }; - - api.id = function () { - return customApi._id(); - }; - - api.type = function () { - return (typeof customApi._type === 'function') ? customApi._type() : opts.adapter; - }; - - api.bulkDocs = function (req, opts, callback) { - if (!api.taskqueue.ready()) { - api.taskqueue.addTask('bulkDocs', arguments); - return; - } - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - if (!opts) { - opts = {}; - } else { - opts = utils.extend(true, {}, opts); - } - - if (!req || !req.docs || req.docs.length < 1) { - return call(callback, errors.MISSING_BULK_DOCS); - } - - if (!Array.isArray(req.docs)) { - return call(callback, errors.QUERY_PARSE_ERROR); - } - - for (var i = 0; i < req.docs.length; ++i) { - if (typeof req.docs[i] !== 'object' || Array.isArray(req.docs[i])) { - return call(callback, errors.NOT_AN_OBJECT); - } - } - - req = utils.extend(true, {}, req); - if (!('new_edits' in opts)) { - opts.new_edits = true; - } - - return customApi._bulkDocs(req, opts, autoCompact(callback)); - }; - - /* End Wrappers */ - var taskqueue = {}; - - taskqueue.ready = false; - taskqueue.queue = []; - - api.taskqueue = {}; - - api.taskqueue.execute = function (db) { - if (taskqueue.ready) { - taskqueue.queue.forEach(function (d) { - d.task = db[d.name].apply(null, d.parameters); - }); - } - }; - - api.taskqueue.ready = function () { - if (arguments.length === 0) { - return taskqueue.ready; - } - taskqueue.ready = arguments[0]; - }; - - api.taskqueue.addTask = function (name, parameters) { - var task = { name: name, parameters: parameters }; - taskqueue.queue.push(task); - return task; - }; - - api.replicate = {}; - - api.replicate.from = function (url, opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - return Pouch.replicate(url, customApi, opts, callback); - }; - - api.replicate.to = function (dbName, opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - return Pouch.replicate(customApi, dbName, opts, callback); - }; - - for (var j in api) { - if (!customApi.hasOwnProperty(j)) { - customApi[j] = api[j]; - } - } - - // Http adapter can skip setup so we force the db to be ready and execute any jobs - if (opts.skipSetup) { - api.taskqueue.ready(true); - api.taskqueue.execute(api); - } - - if (utils.isCordova()) { - //to inform websql adapter that we can use api - cordova.fireWindowEvent(opts.name + "_pouch", {}); - } - return customApi; - }; -}; - -},{"./deps/errors":8,"./merge":13,"./utils":16}],2:[function(require,module,exports){ -"use strict"; - -var utils = require('../utils'); -var errors = require('../deps/errors'); - -// parseUri 1.2.2 -// (c) Steven Levithan <stevenlevithan.com> -// MIT License -function parseUri(str) { - var o = parseUri.options; - var m = o.parser[o.strictMode ? "strict" : "loose"].exec(str); - var uri = {}; - var i = 14; - - while (i--) { - uri[o.key[i]] = m[i] || ""; - } - - uri[o.q.name] = {}; - uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) { - if ($1) { - uri[o.q.name][$1] = $2; - } - }); - - return uri; -} - -function encodeDocId(id) { - if (/^_(design|local)/.test(id)) { - return id; - } - return encodeURIComponent(id); -} - -parseUri.options = { - strictMode: false, - key: ["source", "protocol", "authority", "userInfo", "user", "password", "host", - "port", "relative", "path", "directory", "file", "query", "anchor"], - q: { - name: "queryKey", - parser: /(?:^|&)([^&=]*)=?([^&]*)/g - }, - parser: { - strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, - loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ - } -}; - -// Get all the information you possibly can about the URI given by name and -// return it as a suitable object. -function getHost(name, opts) { - // If the given name contains "http:" - if (/http(s?):/.test(name)) { - // Prase the URI into all its little bits - var uri = parseUri(name); - - // Store the fact that it is a remote URI - uri.remote = true; - - // 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 = 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('/'); - opts = opts || {}; - uri.headers = opts.headers || {}; - - if (opts.auth || uri.auth) { - var nAuth = opts.auth || uri.auth; - var token = utils.btoa(nAuth.username + ':' + nAuth.password); - uri.headers.Authorization = 'Basic ' + token; - } - - if (opts.headers) { - uri.headers = opts.headers; - } - - return uri; - } - - // If the given name does not contain 'http:' then return a very basic object - // with no host, the current path, the given name as the database name and no - // username/password - return {host: '', path: '/', db: name, auth: false}; -} - -// Generate a URL with the host data given by opts and the given path -function genDBUrl(opts, path) { - // If the host is remote - if (opts.remote) { - // If the host already has a path, then we need to have a path delimiter - // Otherwise, the path delimiter is the empty string - var pathDel = !opts.path ? '' : '/'; - - // Return the URL made up of all the host's information and the given path - return opts.protocol + '://' + opts.host + ':' + opts.port + '/' + - opts.path + pathDel + opts.db + '/' + path; - } - - // If the host is not remote, then return the URL made up of just the - // database name and the given path - return '/' + opts.db + '/' + path; -} - -// Generate a URL with the host data given by opts and the given path -function genUrl(opts, path) { - if (opts.remote) { - // If the host already has a path, then we need to have a path delimiter - // Otherwise, the path delimiter is the empty string - var pathDel = !opts.path ? '' : '/'; - - // If the host already has a path, then we need to have a path delimiter - // Otherwise, the path delimiter is the empty string - return opts.protocol + '://' + opts.host + ':' + opts.port + '/' + opts.path + pathDel + path; - } - - return '/' + path; -} - -// Implements the PouchDBVersion110 API for dealing with CouchDB instances over HTTP -function HttpPouch(opts, callback) { - - // Parse the URI given by opts.name into an easy-to-use object - var host = getHost(opts.name, opts); - - // Generate the database URL based on the host - var db_url = genDBUrl(host, ''); - - // The functions that will be publically available for HttpPouch - var api = {}; - var ajaxOpts = opts.ajax || {}; - function ajax(options, callback) { - return utils.ajax(utils.extend({}, ajaxOpts, options), callback); - } - var uuids = { - list: [], - get: function (opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {count: 10}; - } - var cb = function (err, body) { - if (err || !('uuids' in body)) { - utils.call(callback, err || errors.UNKNOWN_ERROR); - } else { - uuids.list = uuids.list.concat(body.uuids); - utils.call(callback, null, "OK"); - } - }; - var params = '?count=' + opts.count; - ajax({ - headers: host.headers, - method: 'GET', - url: genUrl(host, '_uuids') + params - }, cb); - } - }; - - // Create a new CouchDB database based on the given opts - var createDB = function () { - ajax({headers: host.headers, method: 'PUT', url: db_url}, function (err, ret) { - // If we get an "Unauthorized" error - if (err && err.status === 401) { - // Test if the database already exists - ajax({headers: host.headers, method: 'HEAD', url: db_url}, function (err, ret) { - // If there is still an error - if (err) { - // Give the error to the callback to deal with - utils.call(callback, err); - } else { - // Continue as if there had been no errors - utils.call(callback, null, api); - } - }); - // If there were no errros or if the only error is "Precondition Failed" - // (note: "Precondition Failed" occurs when we try to create a database - // that already exists) - } else if (!err || err.status === 412) { - // Continue as if there had been no errors - utils.call(callback, null, api); - } else { - utils.call(callback, errors.UNKNOWN_ERROR); - } - }); - }; - if (!opts.skipSetup) { - ajax({headers: host.headers, method: 'GET', url: db_url}, function (err, ret) { - //check if the db exists - if (err) { - if (err.status === 404) { - //if it doesn't, create it - createDB(); - } else { - utils.call(callback, err); - } - } else { - //go do stuff with the db - utils.call(callback, null, api); - } - }); - } - - api.type = function () { - return 'http'; - }; - - // The HttpPouch's ID is its URL - api.id = function () { - return genDBUrl(host, ''); - }; - - api.request = function (options, callback) { - if (!api.taskqueue.ready()) { - api.taskqueue.addTask('request', arguments); - return; - } - options.headers = host.headers; - options.url = genDBUrl(host, options.url); - ajax(options, callback); - }; - - // Sends a POST request to the host calling the couchdb _compact function - // version: The version of CouchDB it is running - api.compact = function (opts, callback) { - if (!api.taskqueue.ready()) { - api.taskqueue.addTask('compact', arguments); - return; - } - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - ajax({ - headers: host.headers, - url: genDBUrl(host, '_compact'), - method: 'POST' - }, function () { - function ping() { - api.info(function (err, res) { - if (!res.compact_running) { - utils.call(callback, null); - } else { - setTimeout(ping, opts.interval || 200); - } - }); - } - // Ping the http if it's finished compaction - if (typeof callback === "function") { - ping(); - } - }); - }; - - // Calls GET on the host, which gets back a JSON string containing - // couchdb: A welcome string - // version: The version of CouchDB it is running - api.info = function (callback) { - if (!api.taskqueue.ready()) { - api.taskqueue.addTask('info', arguments); - return; - } - ajax({ - headers: host.headers, - method: 'GET', - url: genDBUrl(host, '') - }, callback); - }; - - // Get the document with the given id from the database given by host. - // The id could be solely the _id in the database, or it may be a - // _design/ID or _local/ID path - api.get = function (id, opts, callback) { - if (!api.taskqueue.ready()) { - api.taskqueue.addTask('get', arguments); - return; - } - // If no options were given, set the callback to the second parameter - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - - if (opts.auto_encode === undefined) { - opts.auto_encode = true; - } - - // List of parameters to add to the GET request - var params = []; - - // If it exists, add the opts.revs value to the list of parameters. - // If revs=true then the resulting JSON will include a field - // _revisions containing an array of the revision IDs. - if (opts.revs) { - params.push('revs=true'); - } - - // If it exists, add the opts.revs_info value to the list of parameters. - // If revs_info=true then the resulting JSON will include the field - // _revs_info containing an array of objects in which each object - // representing an available revision. - if (opts.revs_info) { - params.push('revs_info=true'); - } - - if (opts.local_seq) { - params.push('local_seq=true'); - } - // If it exists, add the opts.open_revs value to the list of parameters. - // If open_revs=all then the resulting JSON will include all the leaf - // revisions. If open_revs=["rev1", "rev2",...] then the resulting JSON - // will contain an array of objects containing data of all revisions - if (opts.open_revs) { - if (opts.open_revs !== "all") { - opts.open_revs = JSON.stringify(opts.open_revs); - } - params.push('open_revs=' + opts.open_revs); - } - - // If it exists, add the opts.attachments value to the list of parameters. - // If attachments=true the resulting JSON will include the base64-encoded - // contents in the "data" property of each attachment. - if (opts.attachments) { - params.push('attachments=true'); - } - - // If it exists, add the opts.rev value to the list of parameters. - // If rev is given a revision number then get the specified revision. - if (opts.rev) { - params.push('rev=' + opts.rev); - } - - // If it exists, add the opts.conflicts value to the list of parameters. - // If conflicts=true then the resulting JSON will include the field - // _conflicts containing all the conflicting revisions. - if (opts.conflicts) { - params.push('conflicts=' + opts.conflicts); - } - - // Format the list of parameters into a valid URI query string - params = params.join('&'); - params = params === '' ? '' : '?' + params; - - if (opts.auto_encode) { - id = encodeDocId(id); - } - - // Set the options for the ajax call - var options = { - headers: host.headers, - method: 'GET', - url: genDBUrl(host, id + params) - }; - - // If the given id contains at least one '/' and the part before the '/' - // is NOT "_design" and is NOT "_local" - // OR - // If the given id contains at least two '/' and the part before the first - // '/' is "_design". - // TODO This second condition seems strange since if parts[0] === '_design' - // then we already know that parts[0] !== '_local'. - var parts = id.split('/'); - if ((parts.length > 1 && parts[0] !== '_design' && parts[0] !== '_local') || - (parts.length > 2 && parts[0] === '_design' && parts[0] !== '_local')) { - // Binary is expected back from the server - options.binary = true; - } - - // Get the document - ajax(options, function (err, doc, xhr) { - // If the document does not exist, send an error to the callback - if (err) { - return utils.call(callback, err); - } - - // Send the document to the callback - utils.call(callback, null, doc, xhr); - }); - }; - - // Delete the document given by doc from the database given by host. - api.remove = function (doc, opts, callback) { - if (!api.taskqueue.ready()) { - api.taskqueue.addTask('remove', arguments); - return; - } - // If no options were given, set the callback to be the second parameter - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - - // Delete the document - ajax({ - headers: host.headers, - method: 'DELETE', - url: genDBUrl(host, encodeDocId(doc._id)) + '?rev=' + doc._rev - }, callback); - }; - - // Get the attachment - api.getAttachment = function (docId, attachmentId, opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - if (opts.auto_encode === undefined) { - opts.auto_encode = true; - } - if (opts.auto_encode) { - docId = encodeDocId(docId); - } - opts.auto_encode = false; - api.get(docId + '/' + attachmentId, opts, callback); - }; - - // Remove the attachment given by the id and rev - api.removeAttachment = function (docId, attachmentId, rev, callback) { - if (!api.taskqueue.ready()) { - api.taskqueue.addTask('removeAttachment', arguments); - return; - } - ajax({ - headers: host.headers, - method: 'DELETE', - url: genDBUrl(host, encodeDocId(docId) + '/' + attachmentId) + '?rev=' + rev - }, callback); - }; - - // Add the attachment given by blob and its contentType property - // to the document with the given id, the revision given by rev, and - // add it to the database given by host. - api.putAttachment = function (docId, attachmentId, rev, blob, type, callback) { - if (!api.taskqueue.ready()) { - api.taskqueue.addTask('putAttachment', arguments); - return; - } - if (typeof type === 'function') { - callback = type; - type = blob; - blob = rev; - rev = null; - } - if (typeof type === 'undefined') { - type = blob; - blob = rev; - rev = null; - } - var id = encodeDocId(docId) + '/' + attachmentId; - var url = genDBUrl(host, id); - if (rev) { - url += '?rev=' + rev; - } - - var opts = { - headers: host.headers, - method: 'PUT', - url: url, - processData: false, - body: blob, - timeout: 60000 - }; - opts.headers['Content-Type'] = type; - // Add the attachment - ajax(opts, callback); - }; - - // Add the document given by doc (in JSON string format) to the database - // given by host. This fails if the doc has no _id field. - api.put = function (doc, opts, callback) { - if (!api.taskqueue.ready()) { - api.taskqueue.addTask('put', arguments); - return; - } - // If no options were given, set the callback to be the second parameter - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - if (typeof doc !== 'object') { - return utils.call(callback, errors.NOT_AN_OBJECT); - } - if (!utils.isValidId(doc._id)) { - return utils.call(callback, errors.MISSING_ID); - } - - // List of parameter to add to the PUT request - var params = []; - - // If it exists, add the opts.new_edits value to the list of parameters. - // If new_edits = false then the database will NOT assign this document a - // new revision number - if (opts && typeof opts.new_edits !== 'undefined') { - params.push('new_edits=' + opts.new_edits); - } - - // Format the list of parameters into a valid URI query string - params = params.join('&'); - if (params !== '') { - params = '?' + params; - } - - // Add the document - ajax({ - headers: host.headers, - method: 'PUT', - url: genDBUrl(host, encodeDocId(doc._id)) + params, - body: doc - }, callback); - }; - - // Add the document given by doc (in JSON string format) to the database - // given by host. This does not assume that doc is a new document (i.e. does not - // have a _id or a _rev field. - api.post = function (doc, opts, callback) { - if (!api.taskqueue.ready()) { - api.taskqueue.addTask('post', arguments); - return; - } - // If no options were given, set the callback to be the second parameter - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - if (typeof doc !== 'object') { - return utils.call(callback, errors.NOT_AN_OBJECT); - } - if (! ("_id" in doc)) { - if (uuids.list.length > 0) { - doc._id = uuids.list.pop(); - api.put(doc, opts, callback); - } else { - uuids.get(function (err, resp) { - if (err) { - return utils.call(callback, errors.UNKNOWN_ERROR); - } - doc._id = uuids.list.pop(); - api.put(doc, opts, callback); - }); - } - } else { - api.put(doc, opts, callback); - } - }; - - // Update/create multiple documents given by req in the database - // given by host. - api.bulkDocs = function (req, opts, callback) { - if (!api.taskqueue.ready()) { - api.taskqueue.addTask('bulkDocs', arguments); - return; - } - // If no options were given, set the callback to be the second parameter - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - if (!opts) { - opts = {}; - } - - // If opts.new_edits exists add it to the document data to be - // send to the database. - // If new_edits=false then it prevents the database from creating - // new revision numbers for the documents. Instead it just uses - // the old ones. This is used in database replication. - if (typeof opts.new_edits !== 'undefined') { - req.new_edits = opts.new_edits; - } - - // Update/create the documents - ajax({ - headers: host.headers, - method: 'POST', - url: genDBUrl(host, '_bulk_docs'), - body: req - }, callback); - }; - - // Get a listing of the documents in the database given - // by host and ordered by increasing id. - api.allDocs = function (opts, callback) { - // If no options were given, set the callback to be the second parameter - if (!api.taskqueue.ready()) { - api.taskqueue.addTask('allDocs', arguments); - return; - } - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - - // List of parameters to add to the GET request - var params = []; - var body; - var method = 'GET'; - - // TODO I don't see conflicts as a valid parameter for a - // _all_docs request (see http://wiki.apache.org/couchdb/HTTP_Document_API#all_docs) - if (opts.conflicts) { - params.push('conflicts=true'); - } - - // If opts.descending is truthy add it to params - if (opts.descending) { - params.push('descending=true'); - } - - // If opts.include_docs exists, add the include_docs value to the - // list of parameters. - // If include_docs=true then include the associated document with each - // result. - if (opts.include_docs) { - params.push('include_docs=true'); - } - - // If opts.startkey exists, add the startkey value to the list of - // parameters. - // If startkey is given then the returned list of documents will - // start with the document whose id is startkey. - if (opts.startkey) { - params.push('startkey=' + - encodeURIComponent(JSON.stringify(opts.startkey))); - } - - // If opts.endkey exists, add the endkey value to the list of parameters. - // If endkey is given then the returned list of docuemnts will - // end with the document whose id is endkey. - if (opts.endkey) { - params.push('endkey=' + encodeURIComponent(JSON.stringify(opts.endkey))); - } - - // If opts.limit exists, add the limit value to the parameter list. - if (opts.limit) { - params.push('limit=' + opts.limit); - } - - if (typeof opts.skip !== 'undefined') { - params.push('skip=' + opts.skip); - } - - // Format the list of parameters into a valid URI query string - params = params.join('&'); - if (params !== '') { - params = '?' + params; - } - - // If keys are supplied, issue a POST request to circumvent GET query string limits - // see http://wiki.apache.org/couchdb/HTTP_view_API#Querying_Options - if (typeof opts.keys !== 'undefined') { - method = 'POST'; - body = JSON.stringify({keys: opts.keys}); - } - - // Get the document listing - ajax({ - headers: host.headers, - method: method, - url: genDBUrl(host, '_all_docs' + params), - body: body - }, callback); - }; - - // Get a list of changes made to documents in the database given by host. - // TODO According to the README, there should be two other methods here, - // api.changes.addListener and api.changes.removeListener. - api.changes = function (opts) { - - // We internally page the results of a changes request, this means - // if there is a large set of changes to be returned we can start - // processing them quicker instead of waiting on the entire - // set of changes to return and attempting to process them at once - var CHANGES_LIMIT = 25; - - if (!api.taskqueue.ready()) { - var task = api.taskqueue.addTask('changes', arguments); - return { - cancel: function () { - if (task.task) { - return task.task.cancel(); - } - //console.log(db_url + ': Cancel Changes Feed'); - task.parameters[0].aborted = true; - } - }; - } - - if (opts.since === 'latest') { - var changes; - api.info(function (err, info) { - if (!opts.aborted) { - opts.since = info.update_seq; - changes = api.changes(opts); - } - }); - // Return a method to cancel this method from processing any more - return { - cancel: function () { - if (changes) { - return changes.cancel(); - } - //console.log(db_url + ': Cancel Changes Feed'); - opts.aborted = true; - } - }; - } - - //console.log(db_url + ': Start Changes Feed: continuous=' + opts.continuous); - - var params = {}; - var limit = (typeof opts.limit !== 'undefined') ? opts.limit : false; - if (limit === 0) { - limit = 1; - } - // - var leftToFetch = limit; - - if (opts.style) { - params.style = opts.style; - } - - if (opts.include_docs || opts.filter && typeof opts.filter === 'function') { - params.include_docs = true; - } - - if (opts.continuous) { - params.feed = 'longpoll'; - } - - if (opts.conflicts) { - params.conflicts = true; - } - - if (opts.descending) { - params.descending = true; - } - - if (opts.filter && typeof opts.filter === 'string') { - params.filter = opts.filter; - if (opts.filter === '_view' && opts.view && typeof opts.view === 'string') { - params.view = opts.view; - } - } - - // If opts.query_params exists, pass it through to the changes request. - // These parameters may be used by the filter on the source database. - if (opts.query_params && typeof opts.query_params === 'object') { - for (var param_name in opts.query_params) { - if (opts.query_params.hasOwnProperty(param_name)) { - params[param_name] = opts.query_params[param_name]; - } - } - } - - var xhr; - var lastFetchedSeq; - var remoteLastSeq; - var pagingCount; - - // Get all the changes starting wtih the one immediately after the - // sequence number given by since. - var fetch = function (since, callback) { - params.since = since; - if (!opts.continuous && !pagingCount) { - pagingCount = remoteLastSeq; - } - params.limit = (!limit || leftToFetch > CHANGES_LIMIT) ? - CHANGES_LIMIT : leftToFetch; - - var paramStr = '?' + Object.keys(params).map(function (k) { - return k + '=' + params[k]; - }).join('&'); - - // Set the options for the ajax call - var xhrOpts = { - headers: host.headers, - method: 'GET', - url: genDBUrl(host, '_changes' + paramStr), - // _changes can take a long time to generate, especially when filtered - timeout: null - }; - lastFetchedSeq = since; - - if (opts.aborted) { - return; - } - - // Get the changes - xhr = ajax(xhrOpts, callback); - }; - - // If opts.since exists, get all the changes from the sequence - // number given by opts.since. Otherwise, get all the changes - // from the sequence number 0. - var fetchTimeout = 10; - var fetchRetryCount = 0; - - var results = {results: []}; - - var fetched = function (err, res) { - // If the result of the ajax call (res) contains changes (res.results) - if (res && res.results) { - results.last_seq = res.last_seq; - // For each change - var req = {}; - req.query = opts.query_params; - res.results = res.results.filter(function (c) { - leftToFetch--; - var ret = utils.filterChange(opts)(c); - if (ret) { - results.results.push(c); - utils.call(opts.onChange, c); - } - return ret; - }); - } else if (err) { - // In case of an error, stop listening for changes and call opts.complete - opts.aborted = true; - utils.call(opts.complete, err, null); - } - - // The changes feed may have timed out with no results - // if so reuse last update sequence - if (res && res.last_seq) { - lastFetchedSeq = res.last_seq; - } - - var resultsLength = res && res.results.length || 0; - - pagingCount -= CHANGES_LIMIT; - - var finished = (limit && leftToFetch <= 0) || - (res && !resultsLength && pagingCount <= 0) || - (resultsLength && res.last_seq === remoteLastSeq) || - (opts.descending && lastFetchedSeq !== 0); - - if (opts.continuous || !finished) { - // Increase retry delay exponentially as long as errors persist - if (err) { - fetchRetryCount += 1; - } else { - fetchRetryCount = 0; - } - var timeoutMultiplier = 1 << fetchRetryCount; - var retryWait = fetchTimeout * timeoutMultiplier; - var maximumWait = opts.maximumWait || 30000; - - if (retryWait > maximumWait) { - utils.call(opts.complete, err || errors.UNKNOWN_ERROR, null); - } - - // Queue a call to fetch again with the newest sequence number - setTimeout(function () { fetch(lastFetchedSeq, fetched); }, retryWait); - } else { - // We're done, call the callback - utils.call(opts.complete, null, results); - } - }; - - // If we arent doing a continuous changes request we need to know - // the current update_seq so we know when to stop processing the - // changes - if (opts.continuous) { - fetch(opts.since || 0, fetched); - } else { - api.info(function (err, res) { - if (err) { - return utils.call(opts.complete, err); - } - remoteLastSeq = res.update_seq; - fetch(opts.since || 0, fetched); - }); - } - - // Return a method to cancel this method from processing any more - return { - cancel: function () { - //console.log(db_url + ': Cancel Changes Feed'); - opts.aborted = true; - xhr.abort(); - } - }; - }; - - // Given a set of document/revision IDs (given by req), tets the subset of - // those that do NOT correspond to revisions stored in the database. - // See http://wiki.apache.org/couchdb/HttpPostRevsDiff - api.revsDiff = function (req, opts, callback) { - if (!api.taskqueue.ready()) { - api.taskqueue.addTask('revsDiff', arguments); - return; - } - // If no options were given, set the callback to be the second parameter - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - - // Get the missing document/revision IDs - ajax({ - headers: host.headers, - method: 'POST', - url: genDBUrl(host, '_revs_diff'), - body: req - }, function (err, res) { - utils.call(callback, err, res); - }); - }; - - api.close = function (callback) { - if (!api.taskqueue.ready()) { - api.taskqueue.addTask('close', arguments); - return; - } - utils.call(callback, null); - }; - - api.replicateOnServer = function (target, opts, promise) { - if (!api.taskqueue.ready()) { - api.taskqueue.addTask('replicateOnServer', arguments); - return promise; - } - - var targetHost = getHost(target.id()); - var params = { - source: host.db, - target: targetHost.protocol === host.protocol && targetHost.authority === host.authority ? targetHost.db : targetHost.source - }; - - if (opts.continuous) { - params.continuous = true; - } - - if (opts.create_target) { - params.create_target = true; - } - - if (opts.doc_ids) { - params.doc_ids = opts.doc_ids; - } - - if (opts.filter && typeof opts.filter === 'string') { - params.filter = opts.filter; - } - - if (opts.query_params) { - params.query_params = opts.query_params; - } - - var result = {}; - var repOpts = { - headers: host.headers, - method: 'POST', - url: host.protocol + '://' + host.host + (host.port === 80 ? '' : (':' + host.port)) + '/_replicate', - body: params - }; - var xhr; - promise.cancel = function () { - this.cancelled = true; - if (xhr && !result.ok) { - xhr.abort(); - } - if (result._local_id) { - repOpts.body = { - replication_id: result._local_id - }; - } - repOpts.body.cancel = true; - ajax(repOpts, function (err, resp, xhr) { - // If the replication cancel request fails, send an error to the callback - if (err) { - return utils.call(callback, err); - } - // Send the replication cancel result to the complete callback - utils.call(opts.complete, null, result, xhr); - }); - }; - - if (promise.cancelled) { - return; - } - - xhr = ajax(repOpts, function (err, resp, xhr) { - // If the replication fails, send an error to the callback - if (err) { - return utils.call(callback, err); - } - - result.ok = true; - - // Provided by CouchDB from 1.2.0 onward to cancel replication - if (resp._local_id) { - result._local_id = resp._local_id; - } - - // Send the replication result to the complete callback - utils.call(opts.complete, null, resp, xhr); - }); - }; - - return api; -} - -// Delete the HttpPouch specified by the given name. -HttpPouch.destroy = function (name, opts, callback) { - var host = getHost(name, opts); - opts = opts || {}; - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - opts.headers = host.headers; - opts.method = 'DELETE'; - opts.url = genDBUrl(host, ''); - utils.ajax(opts, callback); -}; - -// HttpPouch is a valid adapter. -HttpPouch.valid = function () { - return true; -}; - -module.exports = HttpPouch; - -},{"../deps/errors":8,"../utils":16}],3:[function(require,module,exports){ -'use strict'; - -var utils = require('../utils'); -var merge = require('../merge'); -var errors = require('../deps/errors'); -function idbError(callback) { - return function (event) { - utils.call(callback, errors.error(errors.IDB_ERROR, event.target, event.type)); - }; -} - -function IdbPouch(opts, callback) { - - // IndexedDB requires a versioned database structure, this is going to make - // it hard to dynamically create object stores if we needed to for things - // like views - var POUCH_VERSION = 1; - - // The object stores created for each database - // DOC_STORE stores the document meta data, its revision history and state - var DOC_STORE = 'document-store'; - // BY_SEQ_STORE stores a particular version of a document, keyed by its - // sequence id - var BY_SEQ_STORE = 'by-sequence'; - // Where we store attachments - var ATTACH_STORE = 'attach-store'; - // Where we store meta data - var META_STORE = 'meta-store'; - // Where we detect blob support - var DETECT_BLOB_SUPPORT_STORE = 'detect-blob-support'; - - - var name = opts.name; - var req = window.indexedDB.open(name, POUCH_VERSION); - - if (!('openReqList' in IdbPouch)) { - IdbPouch.openReqList = {}; - } - IdbPouch.openReqList[name] = req; - - var blobSupport = null; - - var instanceId = null; - var api = {}; - var idb = null; - - req.onupgradeneeded = function (e) { - var db = e.target.result; - var currentVersion = e.oldVersion; - while (currentVersion !== e.newVersion) { - if (currentVersion === 0) { - createSchema(db); - } - currentVersion++; - } - }; - - function createSchema(db) { - db.createObjectStore(DOC_STORE, {keyPath : 'id'}) - .createIndex('seq', 'seq', {unique: true}); - db.createObjectStore(BY_SEQ_STORE, {autoIncrement : true}) - .createIndex('_doc_id_rev', '_doc_id_rev', {unique: true}); - db.createObjectStore(ATTACH_STORE, {keyPath: 'digest'}); - db.createObjectStore(META_STORE, {keyPath: 'id', autoIncrement: false}); - db.createObjectStore(DETECT_BLOB_SUPPORT_STORE); - } - - // From http://stackoverflow.com/questions/14967647/encode-decode-image-with-base64-breaks-image (2013-04-21) - function fixBinary(bin) { - var length = bin.length; - var buf = new ArrayBuffer(length); - var arr = new Uint8Array(buf); - for (var i = 0; i < length; i++) { - arr[i] = bin.charCodeAt(i); - } - return buf; - } - - req.onsuccess = function (e) { - - idb = e.target.result; - - idb.onversionchange = function () { - idb.close(); - }; - - var txn = idb.transaction([META_STORE, DETECT_BLOB_SUPPORT_STORE], - 'readwrite'); - - var req = txn.objectStore(META_STORE).get(META_STORE); - - req.onsuccess = function (e) { - var meta = e.target.result || {id: META_STORE}; - if (name + '_id' in meta) { - instanceId = meta[name + '_id']; - } else { - instanceId = utils.uuid(); - meta[name + '_id'] = instanceId; - txn.objectStore(META_STORE).put(meta); - } - - // detect blob support - try { - txn.objectStore(DETECT_BLOB_SUPPORT_STORE).put(utils.createBlob(), "key"); - blobSupport = true; - } catch (err) { - blobSupport = false; - } finally { - utils.call(callback, null, api); - } - }; - }; - - req.onerror = idbError(callback); - - api.type = function () { - return 'idb'; - }; - - // Each database needs a unique id so that we can store the sequence - // checkpoint without having other databases confuse itself. - api.id = function idb_id() { - return instanceId; - }; - - api._bulkDocs = function idb_bulkDocs(req, opts, callback) { - var newEdits = opts.new_edits; - var userDocs = req.docs; - // Parse the docs, give them a sequence number for the result - var docInfos = userDocs.map(function (doc, i) { - var newDoc = utils.parseDoc(doc, newEdits); - newDoc._bulk_seq = i; - return newDoc; - }); - - var docInfoErrors = docInfos.filter(function (docInfo) { - return docInfo.error; - }); - if (docInfoErrors.length) { - return utils.call(callback, docInfoErrors[0]); - } - - var results = []; - var docsWritten = 0; - - function writeMetaData(e) { - var meta = e.target.result; - meta.updateSeq = (meta.updateSeq || 0) + docsWritten; - txn.objectStore(META_STORE).put(meta); - } - - function processDocs() { - if (!docInfos.length) { - txn.objectStore(META_STORE).get(META_STORE).onsuccess = writeMetaData; - return; - } - var currentDoc = docInfos.shift(); - var req = txn.objectStore(DOC_STORE).get(currentDoc.metadata.id); - req.onsuccess = function process_docRead(event) { - var oldDoc = event.target.result; - if (!oldDoc) { - insertDoc(currentDoc); - } else { - updateDoc(oldDoc, currentDoc); - } - }; - } - - function complete(event) { - var aresults = []; - results.sort(sortByBulkSeq); - results.forEach(function (result) { - delete result._bulk_seq; - if (result.error) { - aresults.push(result); - return; - } - var metadata = result.metadata; - var rev = merge.winningRev(metadata); - - aresults.push({ - ok: true, - id: metadata.id, - rev: rev - }); - - if (utils.isLocalId(metadata.id)) { - return; - } - - IdbPouch.Changes.notify(name); - IdbPouch.Changes.notifyLocalWindows(name); - }); - utils.call(callback, null, aresults); - } - - function preprocessAttachment(att, finish) { - if (att.stub) { - return finish(); - } - if (typeof att.data === 'string') { - var data; - try { - data = atob(att.data); - } catch (e) { - var err = errors.error(errors.BAD_ARG, - "Attachments need to be base64 encoded"); - return utils.call(callback, err); - } - att.digest = 'md5-' + utils.Crypto.MD5(data); - if (blobSupport) { - var type = att.content_type; - data = fixBinary(data); - att.data = utils.createBlob([data], {type: type}); - } - return finish(); - } - var reader = new FileReader(); - reader.onloadend = function (e) { - att.digest = 'md5-' + utils.Crypto.MD5(this.result); - if (!blobSupport) { - att.data = btoa(this.result); - } - finish(); - }; - reader.readAsBinaryString(att.data); - } - - function preprocessAttachments(callback) { - if (!docInfos.length) { - return callback(); - } - - var docv = 0; - docInfos.forEach(function (docInfo) { - var attachments = docInfo.data && docInfo.data._attachments ? - Object.keys(docInfo.data._attachments) : []; - - if (!attachments.length) { - return done(); - } - - var recv = 0; - function attachmentProcessed() { - recv++; - if (recv === attachments.length) { - done(); - } - } - - for (var key in docInfo.data._attachments) { - preprocessAttachment(docInfo.data._attachments[key], attachmentProcessed); - } - }); - - function done() { - docv++; - if (docInfos.length === docv) { - callback(); - } - } - } - - function writeDoc(docInfo, callback) { - var err = null; - var recv = 0; - docInfo.data._id = docInfo.metadata.id; - docInfo.data._rev = docInfo.metadata.rev; - - docsWritten++; - - if (utils.isDeleted(docInfo.metadata, docInfo.metadata.rev)) { - docInfo.data._deleted = true; - } - - var attachments = docInfo.data._attachments ? - Object.keys(docInfo.data._attachments) : []; - - function collectResults(attachmentErr) { - if (!err) { - if (attachmentErr) { - err = attachmentErr; - utils.call(callback, err); - } else if (recv === attachments.length) { - finish(); - } - } - } - - function attachmentSaved(err) { - recv++; - collectResults(err); - } - - for (var key in docInfo.data._attachments) { - if (!docInfo.data._attachments[key].stub) { - var data = docInfo.data._attachments[key].data; - delete docInfo.data._attachments[key].data; - var digest = docInfo.data._attachments[key].digest; - saveAttachment(docInfo, digest, data, attachmentSaved); - } else { - recv++; - collectResults(); - } - } - - function finish() { - docInfo.data._doc_id_rev = docInfo.data._id + "::" + docInfo.data._rev; - var dataReq = txn.objectStore(BY_SEQ_STORE).put(docInfo.data); - dataReq.onsuccess = function (e) { - //console.log(name + ': Wrote Document ', docInfo.metadata.id); - docInfo.metadata.seq = e.target.result; - // Current _rev is calculated from _rev_tree on read - delete docInfo.metadata.rev; - var metaDataReq = txn.objectStore(DOC_STORE).put(docInfo.metadata); - metaDataReq.onsuccess = function () { - results.push(docInfo); - utils.call(callback); - }; - }; - } - - if (!attachments.length) { - finish(); - } - } - - function updateDoc(oldDoc, docInfo) { - var merged = merge.merge(oldDoc.rev_tree, docInfo.metadata.rev_tree[0], 1000); - var wasPreviouslyDeleted = utils.isDeleted(oldDoc); - var inConflict = (wasPreviouslyDeleted && - utils.isDeleted(docInfo.metadata)) || - (!wasPreviouslyDeleted && newEdits && merged.conflicts !== 'new_leaf'); - - if (inConflict) { - results.push(makeErr(errors.REV_CONFLICT, docInfo._bulk_seq)); - return processDocs(); - } - - docInfo.metadata.rev_tree = merged.tree; - writeDoc(docInfo, processDocs); - } - - function insertDoc(docInfo) { - // Cant insert new deleted documents - if ('was_delete' in opts && utils.isDeleted(docInfo.metadata)) { - results.push(errors.MISSING_DOC); - return processDocs(); - } - writeDoc(docInfo, processDocs); - } - - // Insert sequence number into the error so we can sort later - function makeErr(err, seq) { - err._bulk_seq = seq; - return err; - } - - function saveAttachment(docInfo, digest, data, callback) { - var objectStore = txn.objectStore(ATTACH_STORE); - var getReq = objectStore.get(digest).onsuccess = function (e) { - var originalRefs = e.target.result && e.target.result.refs || {}; - var ref = [docInfo.metadata.id, docInfo.metadata.rev].join('@'); - var newAtt = { - digest: digest, - body: data, - refs: originalRefs - }; - newAtt.refs[ref] = true; - var putReq = objectStore.put(newAtt).onsuccess = function (e) { - utils.call(callback); - }; - }; - } - - var txn; - preprocessAttachments(function () { - txn = idb.transaction([DOC_STORE, BY_SEQ_STORE, ATTACH_STORE, META_STORE], - 'readwrite'); - txn.onerror = idbError(callback); - txn.ontimeout = idbError(callback); - txn.oncomplete = complete; - - processDocs(); - }); - }; - - function sortByBulkSeq(a, b) { - return a._bulk_seq - b._bulk_seq; - } - - // First we look up the metadata in the ids database, then we fetch the - // current revision(s) from the by sequence store - api._get = function idb_get(id, opts, callback) { - var doc; - var metadata; - var err; - var txn; - if (opts.ctx) { - txn = opts.ctx; - } else { - txn = idb.transaction([DOC_STORE, BY_SEQ_STORE, ATTACH_STORE], 'readonly'); - } - - function finish() { - utils.call(callback, err, {doc: doc, metadata: metadata, ctx: txn}); - } - - txn.objectStore(DOC_STORE).get(id).onsuccess = function (e) { - metadata = e.target.result; - // we can determine the result here if: - // 1. there is no such document - // 2. the document is deleted and we don't ask about specific rev - // When we ask with opts.rev we expect the answer to be either - // doc (possibly with _deleted=true) or missing error - if (!metadata) { - err = errors.MISSING_DOC; - return finish(); - } - if (utils.isDeleted(metadata) && !opts.rev) { - err = errors.error(errors.MISSING_DOC, "deleted"); - return finish(); - } - - var rev = merge.winningRev(metadata); - var key = metadata.id + '::' + (opts.rev ? opts.rev : rev); - var index = txn.objectStore(BY_SEQ_STORE).index('_doc_id_rev'); - - index.get(key).onsuccess = function (e) { - doc = e.target.result; - if (doc && doc._doc_id_rev) { - delete(doc._doc_id_rev); - } - if (!doc) { - err = errors.MISSING_DOC; - return finish(); - } - finish(); - }; - }; - }; - - api._getAttachment = function (attachment, opts, callback) { - var result; - var txn; - if (opts.ctx) { - txn = opts.ctx; - } else { - txn = idb.transaction([DOC_STORE, BY_SEQ_STORE, ATTACH_STORE], 'readonly'); - } - var digest = attachment.digest; - var type = attachment.content_type; - - txn.objectStore(ATTACH_STORE).get(digest).onsuccess = function (e) { - var data = e.target.result.body; - if (opts.encode) { - if (blobSupport) { - var reader = new FileReader(); - reader.onloadend = function (e) { - result = btoa(this.result); - utils.call(callback, null, result); - }; - reader.readAsBinaryString(data); - } else { - result = data; - utils.call(callback, null, result); - } - } else { - if (blobSupport) { - result = data; - } else { - data = fixBinary(atob(data)); - result = utils.createBlob([data], {type: type}); - } - utils.call(callback, null, result); - } - }; - }; - - api._allDocs = function idb_allDocs(opts, callback) { - var start = 'startkey' in opts ? opts.startkey : false; - var end = 'endkey' in opts ? opts.endkey : false; - - var descending = 'descending' in opts ? opts.descending : false; - descending = descending ? 'prev' : null; - - var keyRange = start && end ? window.IDBKeyRange.bound(start, end) - : start ? window.IDBKeyRange.lowerBound(start) - : end ? window.IDBKeyRange.upperBound(end) : null; - - var transaction = idb.transaction([DOC_STORE, BY_SEQ_STORE], 'readonly'); - transaction.oncomplete = function () { - if ('keys' in opts) { - opts.keys.forEach(function (key) { - if (key in resultsMap) { - results.push(resultsMap[key]); - } else { - results.push({"key": key, "error": "not_found"}); - } - }); - if (opts.descending) { - results.reverse(); - } - } - utils.call(callback, null, { - total_rows: results.length, - offset: opts.skip, - rows: ('limit' in opts) ? results.slice(opts.skip, opts.limit + opts.skip) : - (opts.skip > 0) ? results.slice(opts.skip) : results - }); - }; - - var oStore = transaction.objectStore(DOC_STORE); - var oCursor = descending ? oStore.openCursor(keyRange, descending) - : oStore.openCursor(keyRange); - var results = []; - var resultsMap = {}; - oCursor.onsuccess = function (e) { - if (!e.target.result) { - return; - } - var cursor = e.target.result; - var metadata = cursor.value; - // If opts.keys is set we want to filter here only those docs with - // key in opts.keys. With no performance tests it is difficult to - // guess if iteration with filter is faster than many single requests - function allDocsInner(metadata, data) { - if (utils.isLocalId(metadata.id)) { - return cursor['continue'](); - } - var doc = { - id: metadata.id, - key: metadata.id, - value: { - rev: merge.winningRev(metadata) - } - }; - if (opts.include_docs) { - doc.doc = data; - doc.doc._rev = merge.winningRev(metadata); - if (doc.doc._doc_id_rev) { - delete(doc.doc._doc_id_rev); - } - if (opts.conflicts) { - doc.doc._conflicts = merge.collectConflicts(metadata); - } - for (var att in doc.doc._attachments) { - doc.doc._attachments[att].stub = true; - } - } - if ('keys' in opts) { - if (opts.keys.indexOf(metadata.id) > -1) { - if (utils.isDeleted(metadata)) { - doc.value.deleted = true; - doc.doc = null; - } - resultsMap[doc.id] = doc; - } - } else { - if (!utils.isDeleted(metadata)) { - results.push(doc); - } - } - cursor['continue'](); - } - - if (!opts.include_docs) { - allDocsInner(metadata); - } else { - var index = transaction.objectStore(BY_SEQ_STORE).index('_doc_id_rev'); - var mainRev = merge.winningRev(metadata); - var key = metadata.id + "::" + mainRev; - index.get(key).onsuccess = function (event) { - allDocsInner(cursor.value, event.target.result); - }; - } - }; - }; - - api._info = function idb_info(callback) { - var count = 0; - var update_seq = 0; - var txn = idb.transaction([DOC_STORE, META_STORE], 'readonly'); - - function fetchUpdateSeq(e) { - update_seq = e.target.result && e.target.result.updateSeq || 0; - } - - function countDocs(e) { - var cursor = e.target.result; - if (!cursor) { - txn.objectStore(META_STORE).get(META_STORE).onsuccess = fetchUpdateSeq; - return; - } - if (cursor.value.deleted !== true) { - count++; - } - cursor['continue'](); - } - - txn.oncomplete = function () { - callback(null, { - db_name: name, - doc_count: count, - update_seq: update_seq - }); - }; - - txn.objectStore(DOC_STORE).openCursor().onsuccess = countDocs; - }; - - api._changes = function idb_changes(opts) { - //console.log(name + ': Start Changes Feed: continuous=' + opts.continuous); - - if (opts.continuous) { - var id = name + ':' + utils.uuid(); - opts.cancelled = false; - IdbPouch.Changes.addListener(name, id, api, opts); - IdbPouch.Changes.notify(name); - return { - cancel: function () { - //console.log(name + ': Cancel Changes Feed'); - opts.cancelled = true; - IdbPouch.Changes.removeListener(name, id); - } - }; - } - - var descending = opts.descending ? 'prev' : null; - var last_seq = 0; - - // Ignore the `since` parameter when `descending` is true - opts.since = opts.since && !descending ? opts.since : 0; - - var results = [], resultIndices = {}, dedupResults = []; - var txn; - - function fetchChanges() { - txn = idb.transaction([DOC_STORE, BY_SEQ_STORE]); - txn.oncomplete = onTxnComplete; - - var req; - - if (descending) { - req = txn.objectStore(BY_SEQ_STORE) - .openCursor(window.IDBKeyRange.lowerBound(opts.since, true), descending); - } else { - req = txn.objectStore(BY_SEQ_STORE) - .openCursor(window.IDBKeyRange.lowerBound(opts.since, true)); - } - - req.onsuccess = onsuccess; - req.onerror = onerror; - } - - fetchChanges(); - - function onsuccess(event) { - if (!event.target.result) { - // Filter out null results casued by deduping - for (var i = 0, l = results.length; i < l; i++) { - var result = results[i]; - if (result) { - dedupResults.push(result); - } - } - return false; - } - - var cursor = event.target.result; - - // Try to pre-emptively dedup to save us a bunch of idb calls - var changeId = cursor.value._id; - var changeIdIndex = resultIndices[changeId]; - if (changeIdIndex !== undefined) { - results[changeIdIndex].seq = cursor.key; - // update so it has the later sequence number - results.push(results[changeIdIndex]); - results[changeIdIndex] = null; - resultIndices[changeId] = results.length - 1; - return cursor['continue'](); - } - - var index = txn.objectStore(DOC_STORE); - index.get(cursor.value._id).onsuccess = function (event) { - var metadata = event.target.result; - if (utils.isLocalId(metadata.id)) { - return cursor['continue'](); - } - - if (last_seq < metadata.seq) { - last_seq = metadata.seq; - } - - var mainRev = merge.winningRev(metadata); - var key = metadata.id + "::" + mainRev; - var index = txn.objectStore(BY_SEQ_STORE).index('_doc_id_rev'); - index.get(key).onsuccess = function (docevent) { - var doc = docevent.target.result; - delete doc['_doc_id_rev']; - - doc._rev = mainRev; - var change = opts.processChange(doc, metadata, opts); - change.seq = cursor.key; - - // Dedupe the changes feed - var changeId = change.id, changeIdIndex = resultIndices[changeId]; - if (changeIdIndex !== undefined) { - results[changeIdIndex] = null; - } - results.push(change); - resultIndices[changeId] = results.length - 1; - cursor['continue'](); - }; - }; - } - - function onTxnComplete() { - utils.processChanges(opts, dedupResults, last_seq); - } - - function onerror(error) { - // TODO: shouldn't we pass some params here? - utils.call(opts.complete); - } - }; - - api._close = function (callback) { - if (idb === null) { - return utils.call(callback, errors.NOT_OPEN); - } - - // https://developer.mozilla.org/en-US/docs/IndexedDB/IDBDatabase#close - // "Returns immediately and closes the connection in a separate thread..." - idb.close(); - utils.call(callback, null); - }; - - api._getRevisionTree = function (docId, callback) { - var txn = idb.transaction([DOC_STORE], 'readonly'); - var req = txn.objectStore(DOC_STORE).get(docId); - req.onsuccess = function (event) { - var doc = event.target.result; - if (!doc) { - utils.call(callback, errors.MISSING_DOC); - } else { - utils.call(callback, null, doc.rev_tree); - } - }; - }; - - // This function removes revisions of document docId - // which are listed in revs and sets this document - // revision to to rev_tree - api._doCompaction = function (docId, rev_tree, revs, callback) { - var txn = idb.transaction([DOC_STORE, BY_SEQ_STORE], 'readwrite'); - - var index = txn.objectStore(DOC_STORE); - index.get(docId).onsuccess = function (event) { - var metadata = event.target.result; - metadata.rev_tree = rev_tree; - - var count = revs.length; - revs.forEach(function (rev) { - var index = txn.objectStore(BY_SEQ_STORE).index('_doc_id_rev'); - var key = docId + "::" + rev; - index.getKey(key).onsuccess = function (e) { - var seq = e.target.result; - if (!seq) { - return; - } - var req = txn.objectStore(BY_SEQ_STORE)['delete'](seq); - - count--; - if (!count) { - txn.objectStore(DOC_STORE).put(metadata); - } - }; - }); - }; - txn.oncomplete = function () { - utils.call(callback); - }; - }; - - return api; -} - -IdbPouch.valid = function idb_valid() { - return typeof window !== 'undefined' && !!window.indexedDB; -}; - -IdbPouch.destroy = function idb_destroy(name, opts, callback) { - if (!('openReqList' in IdbPouch)) { - IdbPouch.openReqList = {}; - } - IdbPouch.Changes.clearListeners(name); - - //Close open request for "name" database to fix ie delay. - if (IdbPouch.openReqList[name] && IdbPouch.openReqList[name].result) { - IdbPouch.openReqList[name].result.close(); - } - var req = window.indexedDB.deleteDatabase(name); - - req.onsuccess = function () { - //Remove open request from the list. - if (IdbPouch.openReqList[name]) { - IdbPouch.openReqList[name] = null; - } - utils.call(callback, null); - }; - - req.onerror = idbError(callback); -}; - -IdbPouch.Changes = new utils.Changes(); - -module.exports = IdbPouch; - -},{"../deps/errors":8,"../merge":13,"../utils":16}],4:[function(require,module,exports){ -'use strict'; - -var utils = require('../utils'); -var merge = require('../merge'); -var errors = require('../deps/errors'); -function quote(str) { - return "'" + str + "'"; -} - -function openDB() { - if (typeof window !== 'undefined') { - if (window.navigator && window.navigator.sqlitePlugin && window.navigator.sqlitePlugin.openDatabase) { - return navigator.sqlitePlugin.openDatabase.apply(navigator.sqlitePlugin, arguments); - } else if (window.sqlitePlugin && window.sqlitePlugin.openDatabase) { - return window.sqlitePlugin.openDatabase.apply(window.sqlitePlugin, arguments); - } else { - return window.openDatabase.apply(window, arguments); - } - } -} - -var POUCH_VERSION = 1; -var POUCH_SIZE = 5 * 1024 * 1024; - -// The object stores created for each database -// DOC_STORE stores the document meta data, its revision history and state -var DOC_STORE = quote('document-store'); -// BY_SEQ_STORE stores a particular version of a document, keyed by its -// sequence id -var BY_SEQ_STORE = quote('by-sequence'); -// Where we store attachments -var ATTACH_STORE = quote('attach-store'); -var META_STORE = quote('metadata-store'); - -function unknownError(callback) { - return function (event) { - utils.call(callback, { - status: 500, - error: event.type, - reason: event.target - }); - }; -} -function idbError(callback) { - return function (event) { - utils.call(callback, errors.error(errors.WSQ_ERROR, event.target, event.type)); - }; -} -function webSqlPouch(opts, callback) { - - var api = {}; - var instanceId = null; - var name = opts.name; - - var db = openDB(name, POUCH_VERSION, name, POUCH_SIZE); - if (!db) { - return utils.call(callback, errors.UNKNOWN_ERROR); - } - - function dbCreated() { - callback(null, api); - } - - function setup() { - db.transaction(function (tx) { - var meta = 'CREATE TABLE IF NOT EXISTS ' + META_STORE + - ' (update_seq, dbid)'; - var attach = 'CREATE TABLE IF NOT EXISTS ' + ATTACH_STORE + - ' (digest, json, body BLOB)'; - var doc = 'CREATE TABLE IF NOT EXISTS ' + DOC_STORE + - ' (id unique, seq, json, winningseq)'; - var seq = 'CREATE TABLE IF NOT EXISTS ' + BY_SEQ_STORE + - ' (seq INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, doc_id_rev UNIQUE, json)'; - - tx.executeSql(attach); - tx.executeSql(doc); - tx.executeSql(seq); - tx.executeSql(meta); - - var updateseq = 'SELECT update_seq FROM ' + META_STORE; - tx.executeSql(updateseq, [], function (tx, result) { - if (!result.rows.length) { - var initSeq = 'INSERT INTO ' + META_STORE + ' (update_seq) VALUES (?)'; - tx.executeSql(initSeq, [0]); - return; - } - }); - - var dbid = 'SELECT dbid FROM ' + META_STORE + ' WHERE dbid IS NOT NULL'; - tx.executeSql(dbid, [], function (tx, result) { - if (!result.rows.length) { - var initDb = 'UPDATE ' + META_STORE + ' SET dbid=?'; - instanceId = utils.uuid(); - tx.executeSql(initDb, [instanceId]); - return; - } - instanceId = result.rows.item(0).dbid; - }); - }, unknownError(callback), dbCreated); - } - if (utils.isCordova() && typeof window !== 'undefined') { - //to wait until custom api is made in pouch.adapters before doing setup - window.addEventListener(name + '_pouch', function cordova_init() { - window.removeEventListener(name + '_pouch', cordova_init, false); - setup(); - }, false); - } else { - setup(); - } - - - api.type = function () { - return 'websql'; - }; - - api.id = function () { - return instanceId; - }; - - api._info = function (callback) { - db.transaction(function (tx) { - var sql = 'SELECT COUNT(id) AS count FROM ' + DOC_STORE; - tx.executeSql(sql, [], function (tx, result) { - var doc_count = result.rows.item(0).count; - var updateseq = 'SELECT update_seq FROM ' + META_STORE; - tx.executeSql(updateseq, [], function (tx, result) { - var update_seq = result.rows.item(0).update_seq; - callback(null, { - db_name: name, - doc_count: doc_count, - update_seq: update_seq - }); - }); - }); - }); - }; - - api._bulkDocs = function (req, opts, callback) { - - var newEdits = opts.new_edits; - var userDocs = req.docs; - var docsWritten = 0; - - // Parse the docs, give them a sequence number for the result - var docInfos = userDocs.map(function (doc, i) { - var newDoc = utils.parseDoc(doc, newEdits); - newDoc._bulk_seq = i; - return newDoc; - }); - - var docInfoErrors = docInfos.filter(function (docInfo) { - return docInfo.error; - }); - if (docInfoErrors.length) { - return utils.call(callback, docInfoErrors[0]); - } - - var tx; - var results = []; - var fetchedDocs = {}; - - function sortByBulkSeq(a, b) { - return a._bulk_seq - b._bulk_seq; - } - - function complete(event) { - var aresults = []; - results.sort(sortByBulkSeq); - results.forEach(function (result) { - delete result._bulk_seq; - if (result.error) { - aresults.push(result); - return; - } - var metadata = result.metadata; - var rev = merge.winningRev(metadata); - - aresults.push({ - ok: true, - id: metadata.id, - rev: rev - }); - - if (utils.isLocalId(metadata.id)) { - return; - } - - docsWritten++; - - webSqlPouch.Changes.notify(name); - webSqlPouch.Changes.notifyLocalWindows(name); - }); - - var updateseq = 'SELECT update_seq FROM ' + META_STORE; - tx.executeSql(updateseq, [], function (tx, result) { - var update_seq = result.rows.item(0).update_seq + docsWritten; - var sql = 'UPDATE ' + META_STORE + ' SET update_seq=?'; - tx.executeSql(sql, [update_seq], function () { - utils.call(callback, null, aresults); - }); - }); - } - - function preprocessAttachment(att, finish) { - if (att.stub) { - return finish(); - } - if (typeof att.data === 'string') { - try { - att.data = atob(att.data); - } catch (e) { - var err = errors.error(errors.BAD_ARG, - "Attachments need to be base64 encoded"); - return utils.call(callback, err); - } - att.digest = 'md5-' + utils.Crypto.MD5(att.data); - return finish(); - } - var reader = new FileReader(); - reader.onloadend = function (e) { - att.data = this.result; - att.digest = 'md5-' + utils.Crypto.MD5(this.result); - finish(); - }; - reader.readAsBinaryString(att.data); - } - - function preprocessAttachments(callback) { - if (!docInfos.length) { - return callback(); - } - - var docv = 0; - var recv = 0; - - docInfos.forEach(function (docInfo) { - var attachments = docInfo.data && docInfo.data._attachments ? - Object.keys(docInfo.data._attachments) : []; - - if (!attachments.length) { - return done(); - } - - function processedAttachment() { - recv++; - if (recv === attachments.length) { - done(); - } - } - - for (var key in docInfo.data._attachments) { - preprocessAttachment(docInfo.data._attachments[key], processedAttachment); - } - }); - - function done() { - docv++; - if (docInfos.length === docv) { - callback(); - } - } - } - - function writeDoc(docInfo, callback, isUpdate) { - - function finish() { - var data = docInfo.data; - var sql = 'INSERT INTO ' + BY_SEQ_STORE + ' (doc_id_rev, json) VALUES (?, ?);'; - tx.executeSql(sql, [data._id + "::" + data._rev, - JSON.stringify(data)], dataWritten); - } - - function collectResults(attachmentErr) { - if (!err) { - if (attachmentErr) { - err = attachmentErr; - utils.call(callback, err); - } else if (recv === attachments.length) { - finish(); - } - } - } - - var err = null; - var recv = 0; - - docInfo.data._id = docInfo.metadata.id; - docInfo.data._rev = docInfo.metadata.rev; - - if (utils.isDeleted(docInfo.metadata, docInfo.metadata.rev)) { - docInfo.data._deleted = true; - } - - var attachments = docInfo.data._attachments ? - Object.keys(docInfo.data._attachments) : []; - - function attachmentSaved(err) { - recv++; - collectResults(err); - } - - for (var key in docInfo.data._attachments) { - if (!docInfo.data._attachments[key].stub) { - var data = docInfo.data._attachments[key].data; - delete docInfo.data._attachments[key].data; - var digest = docInfo.data._attachments[key].digest; - saveAttachment(docInfo, digest, data, attachmentSaved); - } else { - recv++; - collectResults(); - } - } - - if (!attachments.length) { - finish(); - } - - function dataWritten(tx, result) { - var seq = docInfo.metadata.seq = result.insertId; - delete docInfo.metadata.rev; - - var mainRev = merge.winningRev(docInfo.metadata); - - var sql = isUpdate ? - 'UPDATE ' + DOC_STORE + ' SET seq=?, json=?, winningseq=(SELECT seq FROM ' + - BY_SEQ_STORE + ' WHERE doc_id_rev=?) WHERE id=?' : - 'INSERT INTO ' + DOC_STORE + ' (id, seq, winningseq, json) VALUES (?, ?, ?, ?);'; - var metadataStr = JSON.stringify(docInfo.metadata); - var key = docInfo.metadata.id + "::" + mainRev; - var params = isUpdate ? - [seq, metadataStr, key, docInfo.metadata.id] : - [docInfo.metadata.id, seq, seq, metadataStr]; - tx.executeSql(sql, params, function (tx, result) { - results.push(docInfo); - utils.call(callback, null); - }); - } - } - - function updateDoc(oldDoc, docInfo) { - var merged = merge.merge(oldDoc.rev_tree, docInfo.metadata.rev_tree[0], 1000); - var inConflict = (utils.isDeleted(oldDoc) && - utils.isDeleted(docInfo.metadata)) || - (!utils.isDeleted(oldDoc) && - newEdits && merged.conflicts !== 'new_leaf'); - - if (inConflict) { - results.push(makeErr(errors.REV_CONFLICT, docInfo._bulk_seq)); - return processDocs(); - } - - docInfo.metadata.rev_tree = merged.tree; - writeDoc(docInfo, processDocs, true); - } - - function insertDoc(docInfo) { - // Cant insert new deleted documents - if ('was_delete' in opts && utils.isDeleted(docInfo.metadata)) { - results.push(errors.MISSING_DOC); - return processDocs(); - } - writeDoc(docInfo, processDocs, false); - } - - function processDocs() { - if (!docInfos.length) { - return complete(); - } - var currentDoc = docInfos.shift(); - var id = currentDoc.metadata.id; - if (id in fetchedDocs) { - updateDoc(fetchedDocs[id], currentDoc); - } else { - // if we have newEdits=false then we can update the same - // document twice in a single bulk docs call - fetchedDocs[id] = currentDoc.metadata; - insertDoc(currentDoc); - } - } - - // Insert sequence number into the error so we can sort later - function makeErr(err, seq) { - err._bulk_seq = seq; - return err; - } - - function saveAttachment(docInfo, digest, data, callback) { - var ref = [docInfo.metadata.id, docInfo.metadata.rev].join('@'); - var newAtt = {digest: digest}; - var sql = 'SELECT digest, json FROM ' + ATTACH_STORE + ' WHERE digest=?'; - tx.executeSql(sql, [digest], function (tx, result) { - if (!result.rows.length) { - newAtt.refs = {}; - newAtt.refs[ref] = true; - sql = 'INSERT INTO ' + ATTACH_STORE + '(digest, json, body) VALUES (?, ?, ?)'; - tx.executeSql(sql, [digest, JSON.stringify(newAtt), data], function () { - utils.call(callback, null); - }); - } else { - newAtt.refs = JSON.parse(result.rows.item(0).json).refs; - sql = 'UPDATE ' + ATTACH_STORE + ' SET json=?, body=? WHERE digest=?'; - tx.executeSql(sql, [JSON.stringify(newAtt), data, digest], function () { - utils.call(callback, null); - }); - } - }); - } - - function metadataFetched(tx, results) { - for (var j = 0; j < results.rows.length; j++) { - var row = results.rows.item(j); - fetchedDocs[row.id] = JSON.parse(row.json); - } - processDocs(); - } - - preprocessAttachments(function () { - db.transaction(function (txn) { - tx = txn; - var ids = '(' + docInfos.map(function (d) { - return quote(d.metadata.id); - }).join(',') + ')'; - var sql = 'SELECT * FROM ' + DOC_STORE + ' WHERE id IN ' + ids; - tx.executeSql(sql, [], metadataFetched); - }, unknownError(callback)); - }); - }; - - api._get = function (id, opts, callback) { - var doc; - var metadata; - var err; - if (!opts.ctx) { - db.transaction(function (txn) { - opts.ctx = txn; - api._get(id, opts, callback); - }); - return; - } - var tx = opts.ctx; - - function finish() { - utils.call(callback, err, {doc: doc, metadata: metadata, ctx: tx}); - } - - var sql = 'SELECT * FROM ' + DOC_STORE + ' WHERE id=?'; - tx.executeSql(sql, [id], function (a, results) { - if (!results.rows.length) { - err = errors.MISSING_DOC; - return finish(); - } - metadata = JSON.parse(results.rows.item(0).json); - if (utils.isDeleted(metadata) && !opts.rev) { - err = errors.error(errors.MISSING_DOC, "deleted"); - return finish(); - } - - var rev = merge.winningRev(metadata); - var key = opts.rev ? opts.rev : rev; - key = metadata.id + '::' + key; - var sql = 'SELECT * FROM ' + BY_SEQ_STORE + ' WHERE doc_id_rev=?'; - tx.executeSql(sql, [key], function (tx, results) { - if (!results.rows.length) { - err = errors.MISSING_DOC; - return finish(); - } - doc = JSON.parse(results.rows.item(0).json); - - finish(); - }); - }); - }; - - function makeRevs(arr) { - return arr.map(function (x) { return {rev: x.rev}; }); - } - - api._allDocs = function (opts, callback) { - var results = []; - var resultsMap = {}; - var start = 'startkey' in opts ? opts.startkey : false; - var end = 'endkey' in opts ? opts.endkey : false; - var descending = 'descending' in opts ? opts.descending : false; - var sql = 'SELECT ' + DOC_STORE + '.id, ' + BY_SEQ_STORE + '.seq, ' + - BY_SEQ_STORE + '.json AS data, ' + DOC_STORE + '.json AS metadata FROM ' + - BY_SEQ_STORE + ' JOIN ' + DOC_STORE + ' ON ' + BY_SEQ_STORE + '.seq = ' + - DOC_STORE + '.winningseq'; - - var sqlArgs = []; - if ('keys' in opts) { - sql += ' WHERE ' + DOC_STORE + '.id IN (' + opts.keys.map(function () { - return '?'; - }).join(',') + ')'; - sqlArgs = sqlArgs.concat(opts.keys); - } else { - if (start) { - sql += ' WHERE ' + DOC_STORE + '.id >= ?'; - sqlArgs.push(start); - } - if (end) { - sql += (start ? ' AND ' : ' WHERE ') + DOC_STORE + '.id <= ?'; - sqlArgs.push(end); - } - sql += ' ORDER BY ' + DOC_STORE + '.id ' + (descending ? 'DESC' : 'ASC'); - } - - db.transaction(function (tx) { - tx.executeSql(sql, sqlArgs, function (tx, result) { - for (var i = 0, l = result.rows.length; i < l; i++) { - var doc = result.rows.item(i); - var metadata = JSON.parse(doc.metadata); - var data = JSON.parse(doc.data); - if (!(utils.isLocalId(metadata.id))) { - doc = { - id: metadata.id, - key: metadata.id, - value: {rev: merge.winningRev(metadata)} - }; - if (opts.include_docs) { - doc.doc = data; - doc.doc._rev = merge.winningRev(metadata); - if (opts.conflicts) { - doc.doc._conflicts = merge.collectConflicts(metadata); - } - for (var att in doc.doc._attachments) { - doc.doc._attachments[att].stub = true; - } - } - if ('keys' in opts) { - if (opts.keys.indexOf(metadata.id) > -1) { - if (utils.isDeleted(metadata)) { - doc.value.deleted = true; - doc.doc = null; - } - resultsMap[doc.id] = doc; - } - } else { - if (!utils.isDeleted(metadata)) { - results.push(doc); - } - } - } - } - }); - }, unknownError(callback), function () { - if ('keys' in opts) { - opts.keys.forEach(function (key) { - if (key in resultsMap) { - results.push(resultsMap[key]); - } else { - results.push({"key": key, "error": "not_found"}); - } - }); - if (opts.descending) { - results.reverse(); - } - } - utils.call(callback, null, { - total_rows: results.length, - offset: opts.skip, - rows: ('limit' in opts) ? results.slice(opts.skip, opts.limit + opts.skip) : - (opts.skip > 0) ? results.slice(opts.skip) : results - }); - }); - }; - - api._changes = function idb_changes(opts) { - - - //console.log(name + ': Start Changes Feed: continuous=' + opts.continuous); - - - if (opts.continuous) { - var id = name + ':' + utils.uuid(); - opts.cancelled = false; - webSqlPouch.Changes.addListener(name, id, api, opts); - webSqlPouch.Changes.notify(name); - return { - cancel: function () { - //console.log(name + ': Cancel Changes Feed'); - opts.cancelled = true; - webSqlPouch.Changes.removeListener(name, id); - } - }; - } - - var descending = opts.descending; - - // Ignore the `since` parameter when `descending` is true - opts.since = opts.since && !descending ? opts.since : 0; - - var results = []; - var txn; - - function fetchChanges() { - var sql = 'SELECT ' + DOC_STORE + '.id, ' + BY_SEQ_STORE + '.seq, ' + - BY_SEQ_STORE + '.json AS data, ' + DOC_STORE + '.json AS metadata FROM ' + - BY_SEQ_STORE + ' JOIN ' + DOC_STORE + ' ON ' + BY_SEQ_STORE + '.seq = ' + - DOC_STORE + '.winningseq WHERE ' + DOC_STORE + '.seq > ' + opts.since + - ' ORDER BY ' + DOC_STORE + '.seq ' + (descending ? 'DESC' : 'ASC'); - - db.transaction(function (tx) { - tx.executeSql(sql, [], function (tx, result) { - var last_seq = 0; - for (var i = 0, l = result.rows.length; i < l; i++) { - var res = result.rows.item(i); - var metadata = JSON.parse(res.metadata); - if (!utils.isLocalId(metadata.id)) { - if (last_seq < res.seq) { - last_seq = res.seq; - } - var doc = JSON.parse(res.data); - var change = opts.processChange(doc, metadata, opts); - change.seq = res.seq; - - results.push(change); - } - } - utils.processChanges(opts, results, last_seq); - }); - }); - } - - fetchChanges(); - }; - - api._close = function (callback) { - //WebSQL databases do not need to be closed - utils.call(callback, null); - }; - - api._getAttachment = function (attachment, opts, callback) { - var res; - var tx = opts.ctx; - var digest = attachment.digest; - var type = attachment.content_type; - var sql = 'SELECT body FROM ' + ATTACH_STORE + ' WHERE digest=?'; - tx.executeSql(sql, [digest], function (tx, result) { - var data = result.rows.item(0).body; - if (opts.encode) { - res = btoa(data); - } else { - res = utils.createBlob([data], {type: type}); - } - utils.call(callback, null, res); - }); - }; - - api._getRevisionTree = function (docId, callback) { - db.transaction(function (tx) { - var sql = 'SELECT json AS metadata FROM ' + DOC_STORE + ' WHERE id = ?'; - tx.executeSql(sql, [docId], function (tx, result) { - if (!result.rows.length) { - utils.call(callback, errors.MISSING_DOC); - } else { - var data = JSON.parse(result.rows.item(0).metadata); - utils.call(callback, null, data.rev_tree); - } - }); - }); - }; - - api._doCompaction = function (docId, rev_tree, revs, callback) { - db.transaction(function (tx) { - var sql = 'SELECT json AS metadata FROM ' + DOC_STORE + ' WHERE id = ?'; - tx.executeSql(sql, [docId], function (tx, result) { - if (!result.rows.length) { - return utils.call(callback); - } - var metadata = JSON.parse(result.rows.item(0).metadata); - metadata.rev_tree = rev_tree; - - var sql = 'DELETE FROM ' + BY_SEQ_STORE + ' WHERE doc_id_rev IN (' + - revs.map(function (rev) {return quote(docId + '::' + rev); }).join(',') + ')'; - - tx.executeSql(sql, [], function (tx, result) { - var sql = 'UPDATE ' + DOC_STORE + ' SET json = ? WHERE id = ?'; - - tx.executeSql(sql, [JSON.stringify(metadata), docId], function (tx, result) { - callback(); - }); - }); - }); - }); - }; - - return api; -} - -webSqlPouch.valid = function () { - if (typeof window !== 'undefined') { - if (window.navigator && window.navigator.sqlitePlugin && window.navigator.sqlitePlugin.openDatabase) { - return true; - } else if (window.sqlitePlugin && window.sqlitePlugin.openDatabase) { - return true; - } else if (window.openDatabase) { - return true; - } - } - return false; -}; - -webSqlPouch.destroy = function (name, opts, callback) { - var db = openDB(name, POUCH_VERSION, name, POUCH_SIZE); - db.transaction(function (tx) { - tx.executeSql('DROP TABLE IF EXISTS ' + DOC_STORE, []); - tx.executeSql('DROP TABLE IF EXISTS ' + BY_SEQ_STORE, []); - tx.executeSql('DROP TABLE IF EXISTS ' + ATTACH_STORE, []); - tx.executeSql('DROP TABLE IF EXISTS ' + META_STORE, []); - }, unknownError(callback), function () { - utils.call(callback, null); - }); -}; - -webSqlPouch.Changes = new utils.Changes(); - -module.exports = webSqlPouch; - -},{"../deps/errors":8,"../merge":13,"../utils":16}],5:[function(require,module,exports){ -"use strict"; - -var Adapter = require('./adapter')(PouchDBVersion110); -function PouchDBVersion110(name, opts, callback) { - - if (!(this instanceof PouchDBVersion110)) { - return new PouchDBVersion110(name, opts, callback); - } - - if (typeof opts === 'function' || typeof opts === 'undefined') { - callback = opts; - opts = {}; - } - - if (typeof name === 'object') { - opts = name; - name = undefined; - } - - if (typeof callback === 'undefined') { - callback = function () {}; - } - - var originalName = opts.name || name; - var backend = PouchDBVersion110.parseAdapter(originalName); - - opts.originalName = originalName; - opts.name = backend.name; - opts.adapter = opts.adapter || backend.adapter; - - if (!PouchDBVersion110.adapters[opts.adapter]) { - throw 'Adapter is missing'; - } - - if (!PouchDBVersion110.adapters[opts.adapter].valid()) { - throw 'Invalid Adapter'; - } - - var adapter = new Adapter(opts, function (err, db) { - if (err) { - if (callback) { - callback(err); - } - return; - } - - for (var plugin in PouchDBVersion110.plugins) { - // In future these will likely need to be async to allow the plugin - // to initialise - var pluginObj = PouchDBVersion110.plugins[plugin](db); - for (var api in pluginObj) { - // We let things like the http adapter use its own implementation - // as it shares a lot of code - if (!(api in db)) { - db[api] = pluginObj[api]; - } - } - } - db.taskqueue.ready(true); - db.taskqueue.execute(db); - callback(null, db); - }); - for (var j in adapter) { - this[j] = adapter[j]; - } - for (var plugin in PouchDBVersion110.plugins) { - // In future these will likely need to be async to allow the plugin - // to initialise - var pluginObj = PouchDBVersion110.plugins[plugin](this); - for (var api in pluginObj) { - // We let things like the http adapter use its own implementation - // as it shares a lot of code - if (!(api in this)) { - this[api] = pluginObj[api]; - } - } - } -} - -module.exports = PouchDBVersion110; -},{"./adapter":1}],6:[function(require,module,exports){ -var process=require("__browserify_process");"use strict"; - -var request = require('request'); -var extend = require('./extend.js'); -var createBlob = require('./blob.js'); -var errors = require('./errors'); - -function ajax(options, callback) { - - if (typeof options === "function") { - callback = options; - options = {}; - } - - function call(fun) { - /* jshint validthis: true */ - var args = Array.prototype.slice.call(arguments, 1); - if (typeof fun === typeof Function) { - fun.apply(this, args); - } - } - - var defaultOptions = { - method : "GET", - headers: {}, - json: true, - processData: true, - timeout: 10000 - }; - - options = extend(true, defaultOptions, options); - - function onSuccess(obj, resp, cb) { - if (!options.binary && !options.json && options.processData && - typeof obj !== 'string') { - obj = JSON.stringify(obj); - } else if (!options.binary && options.json && typeof obj === 'string') { - try { - obj = JSON.parse(obj); - } catch (e) { - // Probably a malformed JSON from server - call(cb, e); - return; - } - } - if (Array.isArray(obj)) { - obj = obj.map(function (v) { - var obj; - if (v.ok) { - return v; - } else if (v.error && v.error === 'conflict') { - obj = errors.REV_CONFLICT; - obj.id = v.id; - return obj; - } else if (v.missing) { - obj = errors.MISSING_DOC; - obj.missing = v.missing; - return obj; - } - }); - } - call(cb, null, obj, resp); - } - - function onError(err, cb) { - var errParsed, errObj, errType, key; - try { - errParsed = JSON.parse(err.responseText); - //would prefer not to have a try/catch clause - for (key in errors) { - if (errors[key].name === errParsed.error) { - errType = errors[key]; - break; - } - } - errType = errType || errors.UNKNOWN_ERROR; - errObj = errors.error(errType, errParsed.reason); - } catch (e) { - errObj = errors.error(errors.UNKNOWN_ERROR); - } - call(cb, errObj); - } - - if (process.browser && typeof XMLHttpRequest !== 'undefined') { - var timer, timedout = false; - var xhr = new XMLHttpRequest(); - - xhr.open(options.method, options.url); - xhr.withCredentials = true; - - if (options.json) { - options.headers.Accept = 'application/json'; - options.headers['Content-Type'] = options.headers['Content-Type'] || - 'application/json'; - if (options.body && options.processData && typeof options.body !== "string") { - options.body = JSON.stringify(options.body); - } - } - - if (options.binary) { - xhr.responseType = 'arraybuffer'; - } - - var createCookie = function (name, value, days) { - var expires = ""; - if (days) { - var date = new Date(); - date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); - expires = "; expires=" + date.toGMTString(); - } - document.cookie = name + "=" + value + expires + "; path=/"; - }; - - for (var key in options.headers) { - if (key === 'Cookie') { - var cookie = options.headers[key].split('='); - createCookie(cookie[0], cookie[1], 10); - } else { - xhr.setRequestHeader(key, options.headers[key]); - } - } - - if (!("body" in options)) { - options.body = null; - } - - var abortReq = function () { - timedout = true; - xhr.abort(); - call(onError, xhr, callback); - }; - - xhr.onreadystatechange = function () { - if (xhr.readyState !== 4 || timedout) { - return; - } - clearTimeout(timer); - if (xhr.status >= 200 && xhr.status < 300) { - var data; - if (options.binary) { - data = createBlob([xhr.response || ''], { - type: xhr.getResponseHeader('Content-Type') - }); - } else { - data = xhr.responseText; - } - call(onSuccess, data, xhr, callback); - } else { - call(onError, xhr, callback); - } - }; - - if (options.timeout > 0) { - timer = setTimeout(abortReq, options.timeout); - xhr.upload.onprogress = xhr.onprogress = function () { - clearTimeout(timer); - timer = setTimeout(abortReq, options.timeout); - }; - } - xhr.send(options.body); - return {abort: abortReq}; - - } else { - - if (options.json) { - if (!options.binary) { - options.headers.Accept = 'application/json'; - } - options.headers['Content-Type'] = options.headers['Content-Type'] || - 'application/json'; - } - - if (options.binary) { - options.encoding = null; - options.json = false; - } - - if (!options.processData) { - options.json = false; - } - - return request(options, function (err, response, body) { - if (err) { - err.status = response ? response.statusCode : 400; - return call(onError, err, callback); - } - var error; - var content_type = response.headers['content-type']; - var data = (body || ''); - - // CouchDB doesn't always return the right content-type for JSON data, so - // we check for ^{ and }$ (ignoring leading/trailing whitespace) - if (!options.binary && (options.json || !options.processData) && - typeof data !== 'object' && - (/json/.test(content_type) || - (/^[\s]*\{/.test(data) && /\}[\s]*$/.test(data)))) { - data = JSON.parse(data); - } - - if (response.statusCode >= 200 && response.statusCode < 300) { - call(onSuccess, data, response, callback); - } - else { - if (options.binary) { - data = JSON.parse(data.toString()); - } - if (data.reason === 'missing') { - error = errors.MISSING_DOC; - } else if (data.reason === 'no_db_file') { - error = errors.error(errors.DB_MISSING, data.reason); - } else if (data.error === 'conflict') { - error = errors.REV_CONFLICT; - } else { - error = errors.error(errors.UNKNOWN_ERROR, data.reason, data.error); - } - error.status = response.statusCode; - call(callback, error); - } - }); - } -} - -module.exports = ajax; - -},{"./blob.js":7,"./errors":8,"./extend.js":9,"__browserify_process":19,"request":18}],7:[function(require,module,exports){ -"use strict"; - -//Abstracts constructing a Blob object, so it also works in older -//browsers that don't support the native Blob constructor. (i.e. -//old QtWebKit versions, at least). -function createBlob(parts, properties) { - parts = parts || []; - properties = properties || {}; - try { - return new Blob(parts, properties); - } catch (e) { - if (e.name !== "TypeError") { - throw e; - } - var BlobBuilder = window.BlobBuilder || window.MSBlobBuilder || window.MozBlobBuilder || window.WebKitBlobBuilder; - var builder = new BlobBuilder(); - for (var i = 0; i < parts.length; i += 1) { - builder.append(parts[i]); - } - return builder.getBlob(properties.type); - } -} - -module.exports = createBlob; - - -},{}],8:[function(require,module,exports){ -"use strict"; - -function PouchError(opts) { - this.status = opts.status; - this.name = opts.error; - this.message = opts.reason; - this.error = true; -} -PouchError.prototype = new Error(); - - -exports.MISSING_BULK_DOCS = new PouchError({ - status: 400, - error: 'bad_request', - reason: "Missing JSON list of 'docs'" -}); -exports.MISSING_DOC = new PouchError({ - status: 404, - error: 'not_found', - reason: 'missing' -}); -exports.REV_CONFLICT = new PouchError({ - status: 409, - error: 'conflict', - reason: 'Document update conflict' -}); -exports.INVALID_ID = new PouchError({ - status: 400, - error: 'invalid_id', - reason: '_id field must contain a string' -}); -exports.MISSING_ID = new PouchError({ - status: 412, - error: 'missing_id', - reason: '_id is required for puts' -}); -exports.RESERVED_ID = new PouchError({ - status: 400, - error: 'bad_request', - reason: 'Only reserved document ids may start with underscore.' -}); -exports.NOT_OPEN = new PouchError({ - status: 412, - error: 'precondition_failed', - reason: 'Database not open so cannot close' -}); -exports.UNKNOWN_ERROR = new PouchError({ - status: 500, - error: 'unknown_error', - reason: 'Database encountered an unknown error' -}); -exports.BAD_ARG = new PouchError({ - status: 500, - error: 'badarg', - reason: 'Some query argument is invalid' -}); -exports.INVALID_REQUEST = new PouchError({ - status: 400, - error: 'invalid_request', - reason: 'Request was invalid' -}); -exports.QUERY_PARSE_ERROR = new PouchError({ - status: 400, - error: 'query_parse_error', - reason: 'Some query parameter is invalid' -}); -exports.DOC_VALIDATION = new PouchError({ - status: 500, - error: 'doc_validation', - reason: 'Bad special document member' -}); -exports.BAD_REQUEST = new PouchError({ - status: 400, - error: 'bad_request', - reason: 'Something wrong with the request' -}); -exports.NOT_AN_OBJECT = new PouchError({ - status: 400, - error: 'bad_request', - reason: 'Document must be a JSON object' -}); -exports.DB_MISSING = new PouchError({ - status: 404, - error: 'not_found', - reason: 'Database not found' -}); -exports.IDB_ERROR = new PouchError({ - status: 500, - error: 'indexed_db_went_bad', - reason: 'unknown' -}); -exports.WSQ_ERROR = new PouchError({ - status: 500, - error: 'web_sql_went_bad', - reason: 'unknown' -}); -exports.LDB_ERROR = new PouchError({ - status: 500, - error: 'levelDB_went_went_bad', - reason: 'unknown' -}); -exports.error = function (error, reason, name) { - function CustomPouchError(msg) { - this.message = reason; - if (name) { - this.name = name; - } - } - CustomPouchError.prototype = error; - return new CustomPouchError(reason); -}; -},{}],9:[function(require,module,exports){ -"use strict"; - -// Extends method -// (taken from http://code.jquery.com/jquery-1.9.0.js) -// Populate the class2type map -var class2type = {}; - -var types = ["Boolean", "Number", "String", "Function", "Array", "Date", "RegExp", "Object", "Error"]; -for (var i = 0; i < types.length; i++) { - var typename = types[i]; - class2type["[object " + typename + "]"] = typename.toLowerCase(); -} - -var core_toString = class2type.toString; -var core_hasOwn = class2type.hasOwnProperty; - -function type(obj) { - if (obj === null) { - return String(obj); - } - return typeof obj === "object" || typeof obj === "function" ? - class2type[core_toString.call(obj)] || "object" : - typeof obj; -} - -function isWindow(obj) { - return obj !== null && obj === obj.window; -} - -function isPlainObject(obj) { - // Must be an Object. - // Because of IE, we also have to check the presence of the constructor property. - // Make sure that DOM nodes and window objects don't pass through, as well - if (!obj || type(obj) !== "object" || obj.nodeType || isWindow(obj)) { - return false; - } - - try { - // Not own constructor property must be Object - if (obj.constructor && - !core_hasOwn.call(obj, "constructor") && - !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) { - return false; - } - } catch ( e ) { - // IE8,9 Will throw exceptions on certain host objects #9897 - return false; - } - - // Own properties are enumerated firstly, so to speed up, - // if last one is own, then all properties are own. - var key; - for (key in obj) {} - - return key === undefined || core_hasOwn.call(obj, key); -} - - -function isFunction(obj) { - return type(obj) === "function"; -} - -var isArray = Array.isArray || function (obj) { - return type(obj) === "array"; -}; - -function extend() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[0] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if (typeof target === "boolean") { - deep = target; - target = arguments[1] || {}; - // skip the boolean and the target - i = 2; - } - - // Handle case when target is a string or something (possible in deep copy) - if (typeof target !== "object" && !isFunction(target)) { - target = {}; - } - - // extend jQuery itself if only one argument is passed - if (length === i) { - /* jshint validthis: true */ - target = this; - --i; - } - - for (; i < length; i++) { - // Only deal with non-null/undefined values - if ((options = arguments[i]) != null) { - // Extend the base object - for (name in options) { - src = target[name]; - copy = options[name]; - - // Prevent never-ending loop - if (target === copy) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if (deep && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) { - if (copyIsArray) { - copyIsArray = false; - clone = src && isArray(src) ? src : []; - - } else { - clone = src && isPlainObject(src) ? src : {}; - } - - // Never move original objects, clone them - target[name] = extend(deep, clone, copy); - - // Don't bring in undefined values - } else if (copy !== undefined) { - if (!(isArray(options) && isFunction(copy))) { - target[name] = copy; - } - } - } - } - } - - // Return the modified object - return target; -} - - -module.exports = extend; - - -},{}],10:[function(require,module,exports){ -var process=require("__browserify_process");"use strict"; - -/** -* -* MD5 (Message-Digest Algorithm) -* -* For original source see http://www.webtoolkit.info/ -* Download: 15.02.2009 from http://www.webtoolkit.info/javascript-md5.html -* -* Licensed under CC-BY 2.0 License -* (http://creativecommons.org/licenses/by/2.0/uk/) -* -**/ -var crypto = require('crypto'); - -exports.MD5 = function (string) { - if (!process.browser) { - return crypto.createHash('md5').update(string).digest('hex'); - } - function rotateLeft(lValue, iShiftBits) { - return (lValue<<iShiftBits) | (lValue>>>(32 - iShiftBits)); - } - - function addUnsigned(lX, lY) { - var lX4, lY4, lX8, lY8, lResult; - lX8 = (lX & 0x80000000); - lY8 = (lY & 0x80000000); - lX4 = (lX & 0x40000000); - lY4 = (lY & 0x40000000); - lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF); - if (lX4 & lY4) { - return (lResult ^ 0x80000000 ^ lX8 ^ lY8); - } - if (lX4 | lY4) { - if (lResult & 0x40000000) { - return (lResult ^ 0xC0000000 ^ lX8 ^ lY8); - } else { - return (lResult ^ 0x40000000 ^ lX8 ^ lY8); - } - } else { - return (lResult ^ lX8 ^ lY8); - } - } - - function f(x, y, z) { return (x & y) | ((~x) & z); } - function g(x, y, z) { return (x & z) | (y & (~z)); } - function h(x, y, z) { return (x ^ y ^ z); } - function i(x, y, z) { return (y ^ (x | (~z))); } - - function ff(a, b, c, d, x, s, ac) { - a = addUnsigned(a, addUnsigned(addUnsigned(f(b, c, d), x), ac)); - return addUnsigned(rotateLeft(a, s), b); - } - - function gg(a, b, c, d, x, s, ac) { - a = addUnsigned(a, addUnsigned(addUnsigned(g(b, c, d), x), ac)); - return addUnsigned(rotateLeft(a, s), b); - } - - function hh(a, b, c, d, x, s, ac) { - a = addUnsigned(a, addUnsigned(addUnsigned(h(b, c, d), x), ac)); - return addUnsigned(rotateLeft(a, s), b); - } - - function ii(a, b, c, d, x, s, ac) { - a = addUnsigned(a, addUnsigned(addUnsigned(i(b, c, d), x), ac)); - return addUnsigned(rotateLeft(a, s), b); - } - - function convertToWordArray(string) { - var lWordCount; - var lMessageLength = string.length; - var lNumberOfWords_temp1 = lMessageLength + 8; - var lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64; - var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16; - var lWordArray = new Array(lNumberOfWords - 1); - var lBytePosition = 0; - var lByteCount = 0; - while (lByteCount < lMessageLength) { - lWordCount = (lByteCount - (lByteCount % 4)) / 4; - lBytePosition = (lByteCount % 4) * 8; - lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount)<<lBytePosition)); - lByteCount++; - } - lWordCount = (lByteCount - (lByteCount % 4)) / 4; - lBytePosition = (lByteCount % 4) * 8; - lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80<<lBytePosition); - lWordArray[lNumberOfWords - 2] = lMessageLength<<3; - lWordArray[lNumberOfWords - 1] = lMessageLength>>>29; - return lWordArray; - } - - function wordToHex(lValue) { - var wordToHexValue = "", wordToHexValue_temp = "", lByte, lCount; - for (lCount = 0;lCount <= 3;lCount++) { - lByte = (lValue>>>(lCount * 8)) & 255; - wordToHexValue_temp = "0" + lByte.toString(16); - wordToHexValue = wordToHexValue + wordToHexValue_temp.substr(wordToHexValue_temp.length - 2, 2); - } - return wordToHexValue; - } - - //** function Utf8Encode(string) removed. Aready defined in pidcrypt_utils.js - - var x = []; - var k, AA, BB, CC, DD, a, b, c, d; - var S11 = 7, S12 = 12, S13 = 17, S14 = 22; - var S21 = 5, S22 = 9, S23 = 14, S24 = 20; - var S31 = 4, S32 = 11, S33 = 16, S34 = 23; - var S41 = 6, S42 = 10, S43 = 15, S44 = 21; - - // string = Utf8Encode(string); #function call removed - - x = convertToWordArray(string); - - a = 0x67452301; - b = 0xEFCDAB89; - c = 0x98BADCFE; - d = 0x10325476; - - for (k = 0;k < x.length;k += 16) { - AA = a; - BB = b; - CC = c; - DD = d; - a = ff(a, b, c, d, x[k + 0], S11, 0xD76AA478); - d = ff(d, a, b, c, x[k + 1], S12, 0xE8C7B756); - c = ff(c, d, a, b, x[k + 2], S13, 0x242070DB); - b = ff(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE); - a = ff(a, b, c, d, x[k + 4], S11, 0xF57C0FAF); - d = ff(d, a, b, c, x[k + 5], S12, 0x4787C62A); - c = ff(c, d, a, b, x[k + 6], S13, 0xA8304613); - b = ff(b, c, d, a, x[k + 7], S14, 0xFD469501); - a = ff(a, b, c, d, x[k + 8], S11, 0x698098D8); - d = ff(d, a, b, c, x[k + 9], S12, 0x8B44F7AF); - c = ff(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1); - b = ff(b, c, d, a, x[k + 11], S14, 0x895CD7BE); - a = ff(a, b, c, d, x[k + 12], S11, 0x6B901122); - d = ff(d, a, b, c, x[k + 13], S12, 0xFD987193); - c = ff(c, d, a, b, x[k + 14], S13, 0xA679438E); - b = ff(b, c, d, a, x[k + 15], S14, 0x49B40821); - a = gg(a, b, c, d, x[k + 1], S21, 0xF61E2562); - d = gg(d, a, b, c, x[k + 6], S22, 0xC040B340); - c = gg(c, d, a, b, x[k + 11], S23, 0x265E5A51); - b = gg(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA); - a = gg(a, b, c, d, x[k + 5], S21, 0xD62F105D); - d = gg(d, a, b, c, x[k + 10], S22, 0x2441453); - c = gg(c, d, a, b, x[k + 15], S23, 0xD8A1E681); - b = gg(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8); - a = gg(a, b, c, d, x[k + 9], S21, 0x21E1CDE6); - d = gg(d, a, b, c, x[k + 14], S22, 0xC33707D6); - c = gg(c, d, a, b, x[k + 3], S23, 0xF4D50D87); - b = gg(b, c, d, a, x[k + 8], S24, 0x455A14ED); - a = gg(a, b, c, d, x[k + 13], S21, 0xA9E3E905); - d = gg(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8); - c = gg(c, d, a, b, x[k + 7], S23, 0x676F02D9); - b = gg(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A); - a = hh(a, b, c, d, x[k + 5], S31, 0xFFFA3942); - d = hh(d, a, b, c, x[k + 8], S32, 0x8771F681); - c = hh(c, d, a, b, x[k + 11], S33, 0x6D9D6122); - b = hh(b, c, d, a, x[k + 14], S34, 0xFDE5380C); - a = hh(a, b, c, d, x[k + 1], S31, 0xA4BEEA44); - d = hh(d, a, b, c, x[k + 4], S32, 0x4BDECFA9); - c = hh(c, d, a, b, x[k + 7], S33, 0xF6BB4B60); - b = hh(b, c, d, a, x[k + 10], S34, 0xBEBFBC70); - a = hh(a, b, c, d, x[k + 13], S31, 0x289B7EC6); - d = hh(d, a, b, c, x[k + 0], S32, 0xEAA127FA); - c = hh(c, d, a, b, x[k + 3], S33, 0xD4EF3085); - b = hh(b, c, d, a, x[k + 6], S34, 0x4881D05); - a = hh(a, b, c, d, x[k + 9], S31, 0xD9D4D039); - d = hh(d, a, b, c, x[k + 12], S32, 0xE6DB99E5); - c = hh(c, d, a, b, x[k + 15], S33, 0x1FA27CF8); - b = hh(b, c, d, a, x[k + 2], S34, 0xC4AC5665); - a = ii(a, b, c, d, x[k + 0], S41, 0xF4292244); - d = ii(d, a, b, c, x[k + 7], S42, 0x432AFF97); - c = ii(c, d, a, b, x[k + 14], S43, 0xAB9423A7); - b = ii(b, c, d, a, x[k + 5], S44, 0xFC93A039); - a = ii(a, b, c, d, x[k + 12], S41, 0x655B59C3); - d = ii(d, a, b, c, x[k + 3], S42, 0x8F0CCC92); - c = ii(c, d, a, b, x[k + 10], S43, 0xFFEFF47D); - b = ii(b, c, d, a, x[k + 1], S44, 0x85845DD1); - a = ii(a, b, c, d, x[k + 8], S41, 0x6FA87E4F); - d = ii(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0); - c = ii(c, d, a, b, x[k + 6], S43, 0xA3014314); - b = ii(b, c, d, a, x[k + 13], S44, 0x4E0811A1); - a = ii(a, b, c, d, x[k + 4], S41, 0xF7537E82); - d = ii(d, a, b, c, x[k + 11], S42, 0xBD3AF235); - c = ii(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB); - b = ii(b, c, d, a, x[k + 9], S44, 0xEB86D391); - a = addUnsigned(a, AA); - b = addUnsigned(b, BB); - c = addUnsigned(c, CC); - d = addUnsigned(d, DD); - } - var temp = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d); - return temp.toLowerCase(); -}; -},{"__browserify_process":19,"crypto":18}],11:[function(require,module,exports){ -"use strict"; - -// BEGIN Math.uuid.js - -/*! -Math.uuid.js (v1.4) -http://www.broofa.com -mailto:robert@broofa.com - -Copyright (c) 2010 Robert Kieffer -Dual licensed under the MIT and GPL licenses. -*/ - -/* - * Generate a random uuid. - * - * USAGE: Math.uuid(length, radix) - * length - the desired number of characters - * radix - the number of allowable values for each character. - * - * EXAMPLES: - * // No arguments - returns RFC4122, version 4 ID - * >>> Math.uuid() - * "92329D39-6F5C-4520-ABFC-AAB64544E172" - * - * // One argument - returns ID of the specified length - * >>> Math.uuid(15) // 15 character ID (default base=62) - * "VcydxgltxrVZSTV" - * - * // Two arguments - returns ID of the specified length, and radix. (Radix must be <= 62) - * >>> Math.uuid(8, 2) // 8 character ID (base=2) - * "01001010" - * >>> Math.uuid(8, 10) // 8 character ID (base=10) - * "47473046" - * >>> Math.uuid(8, 16) // 8 character ID (base=16) - * "098F4D35" - */ - - -function uuid(len, radix) { - var chars = uuid.CHARS; - var uuidInner = []; - var i; - - radix = radix || chars.length; - - if (len) { - // Compact form - for (i = 0; i < len; i++) { - uuidInner[i] = chars[0 | Math.random() * radix]; - } - } else { - // rfc4122, version 4 form - var r; - - // rfc4122 requires these characters - uuidInner[8] = uuidInner[13] = uuidInner[18] = uuidInner[23] = '-'; - uuidInner[14] = '4'; - - // Fill in random data. At i==19 set the high bits of clock sequence as - // per rfc4122, sec. 4.1.5 - for (i = 0; i < 36; i++) { - if (!uuidInner[i]) { - r = 0 | Math.random() * 16; - uuidInner[i] = chars[(i === 19) ? (r & 0x3) | 0x8 : r]; - } - } - } - - return uuidInner.join(''); -} - -uuid.CHARS = ( - '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' + - 'abcdefghijklmnopqrstuvwxyz' -).split(''); - -module.exports = uuid; - - -},{}],12:[function(require,module,exports){ -var process=require("__browserify_process");"use strict"; - -var PouchDBVersion110 = require('./setup'); - -module.exports = PouchDBVersion110; - -PouchDBVersion110.ajax = require('./deps/ajax'); -PouchDBVersion110.extend = require('./deps/extend'); -PouchDBVersion110.utils = require('./utils'); -PouchDBVersion110.Errors = require('./deps/errors'); -PouchDBVersion110.replicate = require('./replicate').replicate; -PouchDBVersion110.version = require('./version'); -var httpAdapter = require('./adapters/http'); -PouchDBVersion110.adapter('http', httpAdapter); -PouchDBVersion110.adapter('https', httpAdapter); - -PouchDBVersion110.adapter('idb', require('./adapters/idb')); -PouchDBVersion110.adapter('websql', require('./adapters/websql')); -PouchDBVersion110.plugin('mapreduce', require('pouchdb-mapreduce')); - -if (!process.browser) { - var ldbAdapter = require('./adapters/leveldb'); - PouchDBVersion110.adapter('ldb', ldbAdapter); - PouchDBVersion110.adapter('leveldb', ldbAdapter); -} - -},{"./adapters/http":2,"./adapters/idb":3,"./adapters/leveldb":18,"./adapters/websql":4,"./deps/ajax":6,"./deps/errors":8,"./deps/extend":9,"./replicate":14,"./setup":15,"./utils":16,"./version":17,"__browserify_process":19,"pouchdb-mapreduce":20}],13:[function(require,module,exports){ -'use strict'; - -var extend = require('./deps/extend'); - - -// for a better overview of what this is doing, read: -// https://github.com/apache/couchdb/blob/master/src/couchdb/couch_key_tree.erl -// -// But for a quick intro, CouchDB uses a revision tree to store a documents -// history, A -> B -> C, when a document has conflicts, that is a branch in the -// tree, A -> (B1 | B2 -> C), We store these as a nested array in the format -// -// KeyTree = [Path ... ] -// Path = {pos: position_from_root, ids: Tree} -// Tree = [Key, Opts, [Tree, ...]], in particular single node: [Key, []] - -// Turn a path as a flat array into a tree with a single branch -function pathToTree(path) { - var doc = path.shift(); - var root = [doc.id, doc.opts, []]; - var leaf = root; - var nleaf; - - while (path.length) { - doc = path.shift(); - nleaf = [doc.id, doc.opts, []]; - leaf[2].push(nleaf); - leaf = nleaf; - } - return root; -} - -// Merge two trees together -// The roots of tree1 and tree2 must be the same revision -function mergeTree(in_tree1, in_tree2) { - var queue = [{tree1: in_tree1, tree2: in_tree2}]; - var conflicts = false; - while (queue.length > 0) { - var item = queue.pop(); - var tree1 = item.tree1; - var tree2 = item.tree2; - - if (tree1[1].status || tree2[1].status) { - tree1[1].status = (tree1[1].status === 'available' || - tree2[1].status === 'available') ? 'available' : 'missing'; - } - - for (var i = 0; i < tree2[2].length; i++) { - if (!tree1[2][0]) { - conflicts = 'new_leaf'; - tree1[2][0] = tree2[2][i]; - continue; - } - - var merged = false; - for (var j = 0; j < tree1[2].length; j++) { - if (tree1[2][j][0] === tree2[2][i][0]) { - queue.push({tree1: tree1[2][j], tree2: tree2[2][i]}); - merged = true; - } - } - if (!merged) { - conflicts = 'new_branch'; - tree1[2].push(tree2[2][i]); - tree1[2].sort(); - } - } - } - return {conflicts: conflicts, tree: in_tree1}; -} - -function doMerge(tree, path, dontExpand) { - var restree = []; - var conflicts = false; - var merged = false; - var res, branch; - - if (!tree.length) { - return {tree: [path], conflicts: 'new_leaf'}; - } - - tree.forEach(function (branch) { - if (branch.pos === path.pos && branch.ids[0] === path.ids[0]) { - // Paths start at the same position and have the same root, so they need - // merged - res = mergeTree(branch.ids, path.ids); - restree.push({pos: branch.pos, ids: res.tree}); - conflicts = conflicts || res.conflicts; - merged = true; - } else if (dontExpand !== true) { - // The paths start at a different position, take the earliest path and - // traverse up until it as at the same point from root as the path we want to - // merge. If the keys match we return the longer path with the other merged - // After stemming we dont want to expand the trees - - var t1 = branch.pos < path.pos ? branch : path; - var t2 = branch.pos < path.pos ? path : branch; - var diff = t2.pos - t1.pos; - - var candidateParents = []; - - var trees = []; - trees.push({ids: t1.ids, diff: diff, parent: null, parentIdx: null}); - while (trees.length > 0) { - var item = trees.pop(); - if (item.diff === 0) { - if (item.ids[0] === t2.ids[0]) { - candidateParents.push(item); - } - continue; - } - if (!item.ids) { - continue; - } - /*jshint loopfunc:true */ - item.ids[2].forEach(function (el, idx) { - trees.push({ids: el, diff: item.diff - 1, parent: item.ids, parentIdx: idx}); - }); - } - - var el = candidateParents[0]; - - if (!el) { - restree.push(branch); - } else { - res = mergeTree(el.ids, t2.ids); - el.parent[2][el.parentIdx] = res.tree; - restree.push({pos: t1.pos, ids: t1.ids}); - conflicts = conflicts || res.conflicts; - merged = true; - } - } else { - restree.push(branch); - } - }); - - // We didnt find - if (!merged) { - restree.push(path); - } - - restree.sort(function (a, b) { - return a.pos - b.pos; - }); - - return { - tree: restree, - conflicts: conflicts || 'internal_node' - }; -} - -// To ensure we dont grow the revision tree infinitely, we stem old revisions -function stem(tree, depth) { - // First we break out the tree into a complete list of root to leaf paths, - // we cut off the start of the path and generate a new set of flat trees - var stemmedPaths = PouchMerge.rootToLeaf(tree).map(function (path) { - var stemmed = path.ids.slice(-depth); - return { - pos: path.pos + (path.ids.length - stemmed.length), - ids: pathToTree(stemmed) - }; - }); - // Then we remerge all those flat trees together, ensuring that we dont - // connect trees that would go beyond the depth limit - return stemmedPaths.reduce(function (prev, current, i, arr) { - return doMerge(prev, current, true).tree; - }, [stemmedPaths.shift()]); -} - -var PouchMerge = {}; - -PouchMerge.merge = function (tree, path, depth) { - // Ugh, nicer way to not modify arguments in place? - tree = extend(true, [], tree); - path = extend(true, {}, path); - var newTree = doMerge(tree, path); - return { - tree: stem(newTree.tree, depth), - conflicts: newTree.conflicts - }; -}; - -// We fetch all leafs of the revision tree, and sort them based on tree length -// and whether they were deleted, undeleted documents with the longest revision -// tree (most edits) win -// The final sort algorithm is slightly documented in a sidebar here: -// http://guide.couchdb.org/draft/conflicts.html -PouchMerge.winningRev = function (metadata) { - var leafs = []; - PouchMerge.traverseRevTree(metadata.rev_tree, - function (isLeaf, pos, id, something, opts) { - if (isLeaf) { - leafs.push({pos: pos, id: id, deleted: !!opts.deleted}); - } - }); - leafs.sort(function (a, b) { - if (a.deleted !== b.deleted) { - return a.deleted > b.deleted ? 1 : -1; - } - if (a.pos !== b.pos) { - return b.pos - a.pos; - } - return a.id < b.id ? 1 : -1; - }); - - return leafs[0].pos + '-' + leafs[0].id; -}; - -// Pretty much all below can be combined into a higher order function to -// traverse revisions -// The return value from the callback will be passed as context to all -// children of that node -PouchMerge.traverseRevTree = function (revs, callback) { - var toVisit = []; - - revs.forEach(function (tree) { - toVisit.push({pos: tree.pos, ids: tree.ids}); - }); - while (toVisit.length > 0) { - var node = toVisit.pop(); - var pos = node.pos; - var tree = node.ids; - var newCtx = callback(tree[2].length === 0, pos, tree[0], node.ctx, tree[1]); - /*jshint loopfunc: true */ - tree[2].forEach(function (branch) { - toVisit.push({pos: pos + 1, ids: branch, ctx: newCtx}); - }); - } -}; - -PouchMerge.collectLeaves = function (revs) { - var leaves = []; - PouchMerge.traverseRevTree(revs, function (isLeaf, pos, id, acc, opts) { - if (isLeaf) { - leaves.unshift({rev: pos + "-" + id, pos: pos, opts: opts}); - } - }); - leaves.sort(function (a, b) { - return b.pos - a.pos; - }); - leaves.map(function (leaf) { delete leaf.pos; }); - return leaves; -}; - -// returns revs of all conflicts that is leaves such that -// 1. are not deleted and -// 2. are different than winning revision -PouchMerge.collectConflicts = function (metadata) { - var win = PouchMerge.winningRev(metadata); - var leaves = PouchMerge.collectLeaves(metadata.rev_tree); - var conflicts = []; - leaves.forEach(function (leaf) { - if (leaf.rev !== win && !leaf.opts.deleted) { - conflicts.push(leaf.rev); - } - }); - return conflicts; -}; - -PouchMerge.rootToLeaf = function (tree) { - var paths = []; - PouchMerge.traverseRevTree(tree, function (isLeaf, pos, id, history, opts) { - history = history ? history.slice(0) : []; - history.push({id: id, opts: opts}); - if (isLeaf) { - var rootPos = pos + 1 - history.length; - paths.unshift({pos: rootPos, ids: history}); - } - return history; - }); - return paths; -}; - - -module.exports = PouchMerge; - -},{"./deps/extend":9}],14:[function(require,module,exports){ -var process=require("__browserify_process");'use strict'; - -var PouchUtils = require('./utils'); -var Pouch = require('./index'); - -// We create a basic promise so the caller can cancel the replication possibly -// before we have actually started listening to changes etc -function Promise() { - var that = this; - this.cancelled = false; - this.cancel = function () { - that.cancelled = true; - }; -} - -// The RequestManager ensures that only one database request is active at -// at time, it ensures we dont max out simultaneous HTTP requests and makes -// the replication process easier to reason about - -function RequestManager(promise) { - var queue = []; - var api = {}; - var processing = false; - - // Add a new request to the queue, if we arent currently processing anything - // then process it immediately - api.enqueue = function (fun, args) { - queue.push({fun: fun, args: args}); - if (!processing) { - api.process(); - } - }; - - // Process the next request - api.process = function () { - if (processing || !queue.length || promise.cancelled) { - return; - } - processing = true; - var task = queue.shift(); - process.nextTick(function () { - task.fun.apply(null, task.args); - }); - }; - - // We need to be notified whenever a request is complete to process - // the next request - api.notifyRequestComplete = function () { - processing = false; - api.process(); - }; - - return api; -} - -// TODO: check CouchDB's replication id generation, generate a unique id particular -// to this replication - -function genReplicationId(src, target, opts) { - var filterFun = opts.filter ? opts.filter.toString() : ''; - return '_local/' + PouchUtils.Crypto.MD5(src.id() + target.id() + filterFun); -} - -// A checkpoint lets us restart replications from when they were last cancelled - -function fetchCheckpoint(src, target, id, callback) { - target.get(id, function (err, targetDoc) { - if (err && err.status === 404) { - callback(null, 0); - } else if (err) { - callback(err); - } else { - src.get(id, function (err, sourceDoc) { - if (err && err.status === 404 || (!err && (targetDoc.last_seq !== sourceDoc.last_seq))) { - callback(null, 0); - } else if (err) { - callback(err); - } else { - callback(null, sourceDoc.last_seq); - } - }); - } - }); -} - -function writeCheckpoint(src, target, id, checkpoint, callback) { - function updateCheckpoint(db, callback) { - db.get(id, function (err, doc) { - if (err && err.status === 404) { - doc = {_id: id}; - } - doc.last_seq = checkpoint; - db.put(doc, callback); - }); - } - updateCheckpoint(target, function (err, doc) { - updateCheckpoint(src, function (err, doc) { - callback(); - }); - }); -} - -function replicate(src, target, opts, promise) { - - var requests = new RequestManager(promise); - var writeQueue = []; - var repId = genReplicationId(src, target, opts); - var results = []; - var completed = false; - var pendingRevs = 0; - var last_seq = 0; - var continuous = opts.continuous || false; - var doc_ids = opts.doc_ids; - var result = { - ok: true, - start_time: new Date(), - docs_read: 0, - docs_written: 0 - }; - - function docsWritten(err, res, len) { - if (opts.onChange) { - for (var i = 0; i < len; i++) { - /*jshint validthis:true */ - opts.onChange.apply(this, [result]); - } - } - pendingRevs -= len; - result.docs_written += len; - - writeCheckpoint(src, target, repId, last_seq, function (err, res) { - requests.notifyRequestComplete(); - isCompleted(); - }); - } - - function writeDocs() { - if (!writeQueue.length) { - return requests.notifyRequestComplete(); - } - var len = writeQueue.length; - target.bulkDocs({docs: writeQueue}, {new_edits: false}, function (err, res) { - docsWritten(err, res, len); - }); - writeQueue = []; - } - - function eachRev(id, rev) { - src.get(id, {revs: true, rev: rev, attachments: true}, function (err, doc) { - result.docs_read++; - requests.notifyRequestComplete(); - writeQueue.push(doc); - requests.enqueue(writeDocs); - }); - } - - function onRevsDiff(diffCounts) { - return function (err, diffs) { - requests.notifyRequestComplete(); - if (err) { - if (continuous) { - promise.cancel(); - } - PouchUtils.call(opts.complete, err, null); - return; - } - - // We already have all diffs passed in `diffCounts` - if (Object.keys(diffs).length === 0) { - for (var docid in diffCounts) { - pendingRevs -= diffCounts[docid]; - } - isCompleted(); - return; - } - - var _enqueuer = function (rev) { - requests.enqueue(eachRev, [id, rev]); - }; - - for (var id in diffs) { - var diffsAlreadyHere = diffCounts[id] - diffs[id].missing.length; - pendingRevs -= diffsAlreadyHere; - diffs[id].missing.forEach(_enqueuer); - } - }; - } - - function fetchRevsDiff(diff, diffCounts) { - target.revsDiff(diff, onRevsDiff(diffCounts)); - } - - function onChange(change) { - last_seq = change.seq; - results.push(change); - var diff = {}; - diff[change.id] = change.changes.map(function (x) { return x.rev; }); - var counts = {}; - counts[change.id] = change.changes.length; - pendingRevs += change.changes.length; - requests.enqueue(fetchRevsDiff, [diff, counts]); - } - - function complete() { - completed = true; - isCompleted(); - } - - function isCompleted() { - if (completed && pendingRevs === 0) { - result.end_time = new Date(); - PouchUtils.call(opts.complete, null, result); - } - } - - fetchCheckpoint(src, target, repId, function (err, checkpoint) { - - if (err) { - return PouchUtils.call(opts.complete, err); - } - - last_seq = checkpoint; - - // Was the replication cancelled by the caller before it had a chance - // to start. Shouldnt we be calling complete? - if (promise.cancelled) { - return; - } - - var repOpts = { - continuous: continuous, - since: last_seq, - style: 'all_docs', - onChange: onChange, - complete: complete, - doc_ids: doc_ids - }; - - if (opts.filter) { - repOpts.filter = opts.filter; - } - - if (opts.query_params) { - repOpts.query_params = opts.query_params; - } - - var changes = src.changes(repOpts); - - if (opts.continuous) { - var cancel = promise.cancel; - promise.cancel = function () { - cancel(); - changes.cancel(); - }; - } - }); - -} - -function toPouch(db, callback) { - if (typeof db === 'string') { - return new Pouch(db, callback); - } - callback(null, db); -} - -exports.replicate = function (src, target, opts, callback) { - if (opts instanceof Function) { - callback = opts; - opts = {}; - } - if (opts === undefined) { - opts = {}; - } - if (!opts.complete) { - opts.complete = callback; - } - var replicateRet = new Promise(); - toPouch(src, function (err, src) { - if (err) { - return PouchUtils.call(callback, err); - } - toPouch(target, function (err, target) { - if (err) { - return PouchUtils.call(callback, err); - } - if (opts.server) { - if (typeof src.replicateOnServer !== 'function') { - return PouchUtils.call(callback, { error: 'Server replication not supported for ' + src.type() + ' adapter' }); - } - if (src.type() !== target.type()) { - return PouchUtils.call(callback, { error: 'Server replication for different adapter types (' + src.type() + ' and ' + target.type() + ') is not supported' }); - } - src.replicateOnServer(target, opts, replicateRet); - } else { - replicate(src, target, opts, replicateRet); - } - }); - }); - return replicateRet; -}; - -},{"./index":12,"./utils":16,"__browserify_process":19}],15:[function(require,module,exports){ -"use strict"; - -var PouchDBVersion110 = require("./constructor"); - -PouchDBVersion110.adapters = {}; -PouchDBVersion110.plugins = {}; - -PouchDBVersion110.prefix = '_pouch_'; - -PouchDBVersion110.parseAdapter = function (name) { - var match = name.match(/([a-z\-]*):\/\/(.*)/); - var adapter; - if (match) { - // the http adapter expects the fully qualified name - name = /http(s?)/.test(match[1]) ? match[1] + '://' + match[2] : match[2]; - adapter = match[1]; - if (!PouchDBVersion110.adapters[adapter].valid()) { - throw 'Invalid adapter'; - } - return {name: name, adapter: match[1]}; - } - - var preferredAdapters = ['idb', 'leveldb', 'websql']; - for (var i = 0; i < preferredAdapters.length; ++i) { - if (preferredAdapters[i] in PouchDBVersion110.adapters) { - adapter = PouchDBVersion110.adapters[preferredAdapters[i]]; - var use_prefix = 'use_prefix' in adapter ? adapter.use_prefix : true; - - return { - name: use_prefix ? PouchDBVersion110.prefix + name : name, - adapter: preferredAdapters[i] - }; - } - } - - throw 'No valid adapter found'; -}; - -PouchDBVersion110.destroy = function (name, opts, callback) { - if (typeof opts === 'function' || typeof opts === 'undefined') { - callback = opts; - opts = {}; - } - - if (typeof name === 'object') { - opts = name; - name = undefined; - } - - if (typeof callback === 'undefined') { - callback = function () {}; - } - var backend = PouchDBVersion110.parseAdapter(opts.name || name); - var dbName = backend.name; - - var cb = function (err, response) { - if (err) { - callback(err); - return; - } - - for (var plugin in PouchDBVersion110.plugins) { - PouchDBVersion110.plugins[plugin]._delete(dbName); - } - //console.log(dbName + ': Delete Database'); - - // call destroy method of the particular adaptor - PouchDBVersion110.adapters[backend.adapter].destroy(dbName, opts, callback); - }; - - // remove PouchDBVersion110 from allDBs - PouchDBVersion110.removeFromAllDbs(backend, cb); -}; - -PouchDBVersion110.removeFromAllDbs = function (opts, callback) { - // Only execute function if flag is enabled - if (!PouchDBVersion110.enableAllDbs) { - callback(); - return; - } - - // skip http and https adaptors for allDbs - var adapter = opts.adapter; - if (adapter === "http" || adapter === "https") { - callback(); - return; - } - - // remove db from PouchDBVersion110.ALL_DBS - new PouchDBVersion110(PouchDBVersion110.allDBName(opts.adapter), function (err, db) { - if (err) { - // don't fail when allDbs fail - //console.error(err); - callback(); - return; - } - // check if db has been registered in PouchDBVersion110.ALL_DBS - var dbname = PouchDBVersion110.dbName(opts.adapter, opts.name); - db.get(dbname, function (err, doc) { - if (err) { - callback(); - } else { - db.remove(doc, function (err, response) { - if (err) { - //console.error(err); - } - callback(); - }); - } - }); - }); - -}; - -PouchDBVersion110.adapter = function (id, obj) { - if (obj.valid()) { - PouchDBVersion110.adapters[id] = obj; - } -}; - -PouchDBVersion110.plugin = function (id, obj) { - PouchDBVersion110.plugins[id] = obj; -}; - -// flag to toggle allDbs (off by default) -PouchDBVersion110.enableAllDbs = false; - -// name of database used to keep track of databases -PouchDBVersion110.ALL_DBS = "_allDbs"; -PouchDBVersion110.dbName = function (adapter, name) { - return [adapter, "-", name].join(''); -}; -PouchDBVersion110.realDBName = function (adapter, name) { - return [adapter, "://", name].join(''); -}; -PouchDBVersion110.allDBName = function (adapter) { - return [adapter, "://", PouchDBVersion110.prefix + PouchDBVersion110.ALL_DBS].join(''); -}; - -PouchDBVersion110.open = function (opts, callback) { - // Only register pouch with allDbs if flag is enabled - if (!PouchDBVersion110.enableAllDbs) { - callback(); - return; - } - - var adapter = opts.adapter; - // skip http and https adaptors for allDbs - if (adapter === "http" || adapter === "https") { - callback(); - return; - } - - new PouchDBVersion110(PouchDBVersion110.allDBName(adapter), function (err, db) { - if (err) { - // don't fail when allDb registration fails - //console.error(err); - callback(); - return; - } - - // check if db has been registered in PouchDBVersion110.ALL_DBS - var dbname = PouchDBVersion110.dbName(adapter, opts.name); - db.get(dbname, function (err, response) { - if (err && err.status === 404) { - db.put({ - _id: dbname, - dbname: opts.originalName - }, function (err) { - if (err) { - //console.error(err); - } - - callback(); - }); - } else { - callback(); - } - }); - }); -}; - -PouchDBVersion110.allDbs = function (callback) { - var accumulate = function (adapters, all_dbs) { - if (adapters.length === 0) { - // remove duplicates - var result = []; - all_dbs.forEach(function (doc) { - var exists = result.some(function (db) { - return db.id === doc.id; - }); - - if (!exists) { - result.push(doc); - } - }); - - // return an array of dbname - callback(null, result.map(function (row) { - return row.doc.dbname; - })); - return; - } - - var adapter = adapters.shift(); - - // skip http and https adaptors for allDbs - if (adapter === "http" || adapter === "https") { - accumulate(adapters, all_dbs); - return; - } - - new PouchDBVersion110(PouchDBVersion110.allDBName(adapter), function (err, db) { - if (err) { - callback(err); - return; - } - db.allDocs({include_docs: true}, function (err, response) { - if (err) { - callback(err); - return; - } - - // append from current adapter rows - all_dbs.unshift.apply(all_dbs, response.rows); - - // code to clear allDbs. - // response.rows.forEach(function (row) { - // db.remove(row.doc, function () { - // //console.log(arguments); - // }); - // }); - - // recurse - accumulate(adapters, all_dbs); - }); - }); - }; - var adapters = Object.keys(PouchDBVersion110.adapters); - accumulate(adapters, []); -}; - -module.exports = PouchDBVersion110; - -},{"./constructor":5}],16:[function(require,module,exports){ -/*jshint strict: false */ -/*global chrome */ - -var merge = require('./merge'); -exports.extend = require('./deps/extend'); -exports.ajax = require('./deps/ajax'); -exports.createBlob = require('./deps/blob'); -var uuid = require('./deps/uuid'); -exports.Crypto = require('./deps/md5.js'); -var buffer = require('./deps/buffer'); -var errors = require('./deps/errors'); - -// List of top level reserved words for doc -var reservedWords = [ - '_id', - '_rev', - '_attachments', - '_deleted', - '_revisions', - '_revs_info', - '_conflicts', - '_deleted_conflicts', - '_local_seq', - '_rev_tree' -]; -exports.uuids = function (count, options) { - - if (typeof(options) !== 'object') { - options = {}; - } - - var length = options.length; - var radix = options.radix; - var uuids = []; - - while (uuids.push(uuid(length, radix)) < count) { } - - return uuids; -}; - -// Give back one UUID -exports.uuid = function (options) { - return exports.uuids(1, options)[0]; -}; -// Determine id an ID is valid -// - invalid IDs begin with an underescore that does not begin '_design' or '_local' -// - any other string value is a valid id -exports.isValidId = function (id) { - if (!id || (typeof id !== 'string')) { - return false; - } - if (/^_/.test(id)) { - return (/^_(design|local)/).test(id); - } - return true; -}; - -function isChromeApp() { - return (typeof chrome !== "undefined" && - typeof chrome.storage !== "undefined" && - typeof chrome.storage.local !== "undefined"); -} - -// Pretty dumb name for a function, just wraps callback calls so we dont -// to if (callback) callback() everywhere -exports.call = function (fun) { - if (typeof fun === typeof Function) { - var args = Array.prototype.slice.call(arguments, 1); - fun.apply(this, args); - } -}; - -exports.isLocalId = function (id) { - return (/^_local/).test(id); -}; - -// check if a specific revision of a doc has been deleted -// - metadata: the metadata object from the doc store -// - rev: (optional) the revision to check. defaults to winning revision -exports.isDeleted = function (metadata, rev) { - if (!rev) { - rev = merge.winningRev(metadata); - } - if (rev.indexOf('-') >= 0) { - rev = rev.split('-')[1]; - } - var deleted = false; - merge.traverseRevTree(metadata.rev_tree, function (isLeaf, pos, id, acc, opts) { - if (id === rev) { - deleted = !!opts.deleted; - } - }); - - return deleted; -}; - -exports.filterChange = function (opts) { - return function (change) { - var req = {}; - var hasFilter = opts.filter && typeof opts.filter === 'function'; - - req.query = opts.query_params; - if (opts.filter && hasFilter && !opts.filter.call(this, change.doc, req)) { - return false; - } - if (opts.doc_ids && opts.doc_ids.indexOf(change.id) === -1) { - return false; - } - if (!opts.include_docs) { - delete change.doc; - } else { - for (var att in change.doc._attachments) { - change.doc._attachments[att].stub = true; - } - } - return true; - }; -}; - -exports.processChanges = function (opts, changes, last_seq) { - // TODO: we should try to filter and limit as soon as possible - changes = changes.filter(exports.filterChange(opts)); - if (opts.limit) { - if (opts.limit < changes.length) { - changes.length = opts.limit; - } - } - changes.forEach(function (change) { - exports.call(opts.onChange, change); - }); - exports.call(opts.complete, null, {results: changes, last_seq: last_seq}); -}; - -// Preprocess documents, parse their revisions, assign an id and a -// revision for new writes that are missing them, etc -exports.parseDoc = function (doc, newEdits) { - var error = null; - var nRevNum; - var newRevId; - var revInfo; - var opts = {status: 'available'}; - if (doc._deleted) { - opts.deleted = true; - } - - if (newEdits) { - if (!doc._id) { - doc._id = exports.uuid(); - } - newRevId = exports.uuid({length: 32, radix: 16}).toLowerCase(); - if (doc._rev) { - revInfo = /^(\d+)-(.+)$/.exec(doc._rev); - if (!revInfo) { - throw "invalid value for property '_rev'"; - } - doc._rev_tree = [{ - pos: parseInt(revInfo[1], 10), - ids: [revInfo[2], {status: 'missing'}, [[newRevId, opts, []]]] - }]; - nRevNum = parseInt(revInfo[1], 10) + 1; - } else { - doc._rev_tree = [{ - pos: 1, - ids : [newRevId, opts, []] - }]; - nRevNum = 1; - } - } else { - if (doc._revisions) { - doc._rev_tree = [{ - pos: doc._revisions.start - doc._revisions.ids.length + 1, - ids: doc._revisions.ids.reduce(function (acc, x) { - if (acc === null) { - return [x, opts, []]; - } else { - return [x, {status: 'missing'}, [acc]]; - } - }, null) - }]; - nRevNum = doc._revisions.start; - newRevId = doc._revisions.ids[0]; - } - if (!doc._rev_tree) { - revInfo = /^(\d+)-(.+)$/.exec(doc._rev); - if (!revInfo) { - return errors.BAD_ARG; - } - nRevNum = parseInt(revInfo[1], 10); - newRevId = revInfo[2]; - doc._rev_tree = [{ - pos: parseInt(revInfo[1], 10), - ids: [revInfo[2], opts, []] - }]; - } - } - - if (typeof doc._id !== 'string') { - error = errors.INVALID_ID; - } - else if (!exports.isValidId(doc._id)) { - error = errors.RESERVED_ID; - } - - for (var key in doc) { - if (doc.hasOwnProperty(key) && key[0] === '_' && reservedWords.indexOf(key) === -1) { - error = exports.extend({}, errors.DOC_VALIDATION); - error.reason += ': ' + key; - } - } - - doc._id = decodeURIComponent(doc._id); - doc._rev = [nRevNum, newRevId].join('-'); - - if (error) { - return error; - } - - return Object.keys(doc).reduce(function (acc, key) { - if (/^_/.test(key) && key !== '_attachments') { - acc.metadata[key.slice(1)] = doc[key]; - } else { - acc.data[key] = doc[key]; - } - return acc; - }, {metadata : {}, data : {}}); -}; - -exports.isCordova = function () { - return (typeof cordova !== "undefined" || - typeof PhoneGap !== "undefined" || - typeof phonegap !== "undefined"); -}; - -exports.Changes = function () { - - var api = {}; - var listeners = {}; - - if (isChromeApp()) { - chrome.storage.onChanged.addListener(function (e) { - // make sure it's event addressed to us - if (e.db_name != null) { - api.notify(e.db_name.newValue);//object only has oldValue, newValue members - } - }); - } else if (typeof window !== 'undefined') { - window.addEventListener("storage", function (e) { - api.notify(e.key); - }); - } - - api.addListener = function (db_name, id, db, opts) { - if (!listeners[db_name]) { - listeners[db_name] = {}; - } - listeners[db_name][id] = { - db: db, - opts: opts - }; - }; - - api.removeListener = function (db_name, id) { - if (listeners[db_name]) { - delete listeners[db_name][id]; - } - }; - - api.clearListeners = function (db_name) { - delete listeners[db_name]; - }; - - api.notifyLocalWindows = function (db_name) { - //do a useless change on a storage thing - //in order to get other windows's listeners to activate - if (!isChromeApp()) { - localStorage[db_name] = (localStorage[db_name] === "a") ? "b" : "a"; - } else { - chrome.storage.local.set({db_name: db_name}); - } - }; - - api.notify = function (db_name) { - if (!listeners[db_name]) { return; } - - Object.keys(listeners[db_name]).forEach(function (i) { - var opts = listeners[db_name][i].opts; - listeners[db_name][i].db.changes({ - include_docs: opts.include_docs, - conflicts: opts.conflicts, - continuous: false, - descending: false, - filter: opts.filter, - view: opts.view, - since: opts.since, - query_params: opts.query_params, - onChange: function (c) { - if (c.seq > opts.since && !opts.cancelled) { - opts.since = c.seq; - exports.call(opts.onChange, c); - } - } - }); - }); - }; - - return api; -}; - -if (typeof window === 'undefined' || !('atob' in window)) { - exports.atob = function (str) { - var base64 = new buffer(str, 'base64'); - // Node.js will just skip the characters it can't encode instead of - // throwing and exception - if (base64.toString('base64') !== str) { - throw ("Cannot base64 encode full string"); - } - return base64.toString('binary'); - }; -} else { - exports.atob = function (str) { - return atob(str); - }; -} - -if (typeof window === 'undefined' || !('btoa' in window)) { - exports.btoa = function (str) { - return new buffer(str, 'binary').toString('base64'); - }; -} else { - exports.btoa = function (str) { - return btoa(str); - }; -} - - -module.exports = exports; - -},{"./deps/ajax":6,"./deps/blob":7,"./deps/buffer":18,"./deps/errors":8,"./deps/extend":9,"./deps/md5.js":10,"./deps/uuid":11,"./merge":13}],17:[function(require,module,exports){ -module.exports = '1.1.0'; - -},{}],18:[function(require,module,exports){ - -},{}],19:[function(require,module,exports){ -// shim for using process in browser - -var process = module.exports = {}; - -process.nextTick = (function () { - var canSetImmediate = typeof window !== 'undefined' - && window.setImmediate; - var canPost = typeof window !== 'undefined' - && window.postMessage && window.addEventListener - ; - - if (canSetImmediate) { - return function (f) { return window.setImmediate(f) }; - } - - if (canPost) { - var queue = []; - window.addEventListener('message', function (ev) { - var source = ev.source; - if ((source === window || source === null) && ev.data === 'process-tick') { - ev.stopPropagation(); - if (queue.length > 0) { - var fn = queue.shift(); - fn(); - } - } - }, true); - - return function nextTick(fn) { - queue.push(fn); - window.postMessage('process-tick', '*'); - }; - } - - return function nextTick(fn) { - setTimeout(fn, 0); - }; -})(); - -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; - -process.binding = function (name) { - throw new Error('process.binding is not supported'); -} - -// TODO(shtylman) -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; - -},{}],20:[function(require,module,exports){ -/*global Pouch: true, pouchCollate: true */ - -"use strict"; - -var pouchCollate = require('pouchdb-collate'); - -// This is the first implementation of a basic plugin, we register the -// plugin object with pouch and it is mixin'd to each database created -// (regardless of adapter), adapters can override plugins by providing -// their own implementation. functions on the plugin object that start -// with _ are reserved function that are called by pouchdb for special -// notifications. - -// If we wanted to store incremental views we can do it here by listening -// to the changes feed (keeping track of our last update_seq between page loads) -// and storing the result of the map function (possibly using the upcoming -// extracted adapter functions) - - - -function MapReduce(db) { - if(!(this instanceof MapReduce)){ - return new MapReduce(db); - } - function viewQuery(fun, options) { - if (!options.complete) { - return; - } - - if (!options.skip) { - options.skip = 0; - } - - if (!fun.reduce) { - options.reduce = false; - } - - function sum(values) { - return values.reduce(function (a, b) { return a + b; }, 0); - } - - var builtInReduce = { - "_sum": function (keys, values){ - return sum(values); - }, - - "_count": function (keys, values, rereduce){ - if (rereduce){ - return sum(values); - } else { - return values.length; - } - }, - - "_stats": function (keys, values, rereduce) { - return { - 'sum': sum(values), - 'min': Math.min.apply(null, values), - 'max': Math.max.apply(null, values), - 'count': values.length, - 'sumsqr': (function () { - var _sumsqr = 0; - for(var idx in values) { - if (typeof values[idx] === 'number') { - _sumsqr += values[idx] * values[idx]; - } - } - return _sumsqr; - })() - }; - } - }; - - var results = []; - var current = null; - var num_started= 0; - var completed= false; - - function emit(key, val) { - var viewRow = { - id: current.doc._id, - key: key, - value: val - }; - - if (options.startkey && pouchCollate(key, options.startkey) < 0) return; - if (options.endkey && pouchCollate(key, options.endkey) > 0) return; - if (typeof options.key !== 'undefined' && pouchCollate(key, options.key) !== 0) return; - - num_started++; - if (options.include_docs) { - //in this special case, join on _id (issue #106) - if (val && typeof val === 'object' && val._id){ - db.get(val._id, - function (_, joined_doc){ - if (joined_doc) { - viewRow.doc = joined_doc; - } - results.push(viewRow); - checkComplete(); - }); - return; - } else { - viewRow.doc = current.doc; - } - } - results.push(viewRow); - }; - - // ugly way to make sure references to 'emit' in map/reduce bind to the - // above emit - eval('fun.map = ' + fun.map.toString() + ';'); - if (fun.reduce) { - if (builtInReduce[fun.reduce]) { - fun.reduce = builtInReduce[fun.reduce]; - } - - eval('fun.reduce = ' + fun.reduce.toString() + ';'); - } - - //only proceed once all documents are mapped and joined - function checkComplete() { - if (completed && results.length == num_started){ - results.sort(function (a, b) { - return pouchCollate(a.key, b.key); - }); - if (options.descending) { - results.reverse(); - } - if (options.reduce === false) { - return options.complete(null, { - total_rows: results.length, - offset: options.skip, - rows: ('limit' in options) ? results.slice(options.skip, options.limit + options.skip) : - (options.skip > 0) ? results.slice(options.skip) : results - }); - } - - var groups = []; - results.forEach(function (e) { - var last = groups[groups.length-1] || null; - if (last && pouchCollate(last.key[0][0], e.key) === 0) { - last.key.push([e.key, e.id]); - last.value.push(e.value); - return; - } - groups.push({key: [[e.key, e.id]], value: [e.value]}); - }); - groups.forEach(function (e) { - e.value = fun.reduce(e.key, e.value); - e.value = (typeof e.value === 'undefined') ? null : e.value; - e.key = e.key[0][0]; - }); - - options.complete(null, { - total_rows: groups.length, - offset: options.skip, - rows: ('limit' in options) ? groups.slice(options.skip, options.limit + options.skip) : - (options.skip > 0) ? groups.slice(options.skip) : groups - }); - } - }; - - db.changes({ - conflicts: true, - include_docs: true, - onChange: function (doc) { - if (!('deleted' in doc)) { - current = {doc: doc.doc}; - fun.map.call(this, doc.doc); - } - }, - complete: function () { - completed= true; - checkComplete(); - } - }); - } - - function httpQuery(fun, opts, callback) { - - // List of parameters to add to the PUT request - var params = []; - var body = undefined; - var method = 'GET'; - - // If opts.reduce exists and is defined, then add it to the list - // of parameters. - // If reduce=false then the results are that of only the map function - // not the final result of map and reduce. - if (typeof opts.reduce !== 'undefined') { - params.push('reduce=' + opts.reduce); - } - if (typeof opts.include_docs !== 'undefined') { - params.push('include_docs=' + opts.include_docs); - } - if (typeof opts.limit !== 'undefined') { - params.push('limit=' + opts.limit); - } - if (typeof opts.descending !== 'undefined') { - params.push('descending=' + opts.descending); - } - if (typeof opts.startkey !== 'undefined') { - params.push('startkey=' + encodeURIComponent(JSON.stringify(opts.startkey))); - } - if (typeof opts.endkey !== 'undefined') { - params.push('endkey=' + encodeURIComponent(JSON.stringify(opts.endkey))); - } - if (typeof opts.key !== 'undefined') { - params.push('key=' + encodeURIComponent(JSON.stringify(opts.key))); - } - if (typeof opts.group !== 'undefined') { - params.push('group=' + opts.group); - } - if (typeof opts.group_level !== 'undefined') { - params.push('group_level=' + opts.group_level); - } - if (typeof opts.skip !== 'undefined') { - params.push('skip=' + opts.skip); - } - - // If keys are supplied, issue a POST request to circumvent GET query string limits - // see http://wiki.apache.org/couchdb/HTTP_view_API#Querying_Options - if (typeof opts.keys !== 'undefined') { - method = 'POST'; - body = JSON.stringify({keys:opts.keys}); - } - - // Format the list of parameters into a valid URI query string - params = params.join('&'); - params = params === '' ? '' : '?' + params; - - // We are referencing a query defined in the design doc - if (typeof fun === 'string') { - var parts = fun.split('/'); - db.request({ - method: method, - url: '_design/' + parts[0] + '/_view/' + parts[1] + params, - body: body - }, callback); - return; - } - - // We are using a temporary view, terrible for performance but good for testing - var queryObject = JSON.parse(JSON.stringify(fun, function (key, val) { - if (typeof val === 'function') { - return val + ''; // implicitly `toString` it - } - return val; - })); - - db.request({ - method:'POST', - url: '_temp_view' + params, - body: queryObject - }, callback); - } - - this.query = function(fun, opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - - if (callback) { - opts.complete = callback; - } - - if (db.type() === 'http') { - if (typeof fun === 'function'){ - return httpQuery({map: fun}, opts, callback); - } - return httpQuery(fun, opts, callback); - } - - if (typeof fun === 'object') { - return viewQuery(fun, opts); - } - - if (typeof fun === 'function') { - return viewQuery({map: fun}, opts); - } - - var parts = fun.split('/'); - db.get('_design/' + parts[0], function (err, doc) { - if (err) { - if (callback) callback(err); - return; - } - - if (!doc.views[parts[1]]) { - if (callback) callback({ error: 'not_found', reason: 'missing_named_view' }); - return; - } - - viewQuery({ - map: doc.views[parts[1]].map, - reduce: doc.views[parts[1]].reduce - }, opts); - }); - } - -}; - -// Deletion is a noop since we dont store the results of the view -MapReduce._delete = function () { }; -module.exports = MapReduce; - -},{"pouchdb-collate":21}],21:[function(require,module,exports){ -'use strict'; - -function arrayCollate(a, b) { - var len = Math.min(a.length, b.length); - for (var i = 0; i < len; i++) { - var sort = pouchCollate(a[i], b[i]); - if (sort !== 0) { - return sort; - } - } - return (a.length === b.length) ? 0 : - (a.length > b.length) ? 1 : -1; -} -function stringCollate(a, b) { - // See: https://github.com/daleharvey/pouchdb/issues/40 - // This is incompatible with the CouchDB implementation, but its the - // best we can do for now - return (a === b) ? 0 : ((a > b) ? 1 : -1); -} -function objectCollate(a, b) { - var ak = Object.keys(a), bk = Object.keys(b); - var len = Math.min(ak.length, bk.length); - for (var i = 0; i < len; i++) { - // First sort the keys - var sort = pouchCollate(ak[i], bk[i]); - if (sort !== 0) { - return sort; - } - // if the keys are equal sort the values - sort = pouchCollate(a[ak[i]], b[bk[i]]); - if (sort !== 0) { - return sort; - } - - } - return (ak.length === bk.length) ? 0 : - (ak.length > bk.length) ? 1 : -1; -} -// The collation is defined by erlangs ordered terms -// the atoms null, true, false come first, then numbers, strings, -// arrays, then objects -function collationIndex(x) { - var id = ['boolean', 'number', 'string', 'object']; - if (id.indexOf(typeof x) !== -1) { - if (x === null) { - return 1; - } - return id.indexOf(typeof x) + 2; - } - if (Array.isArray(x)) { - return 4.5; - } - if (typeof x === 'undefined') { - // CouchDB indexes both null/undefined as null - return 1; - } -} -module.exports = pouchCollate; -function pouchCollate(a, b) { - var ai = collationIndex(a); - var bi = collationIndex(b); - if ((ai - bi) !== 0) { - return ai - bi; - } - if (a === null || typeof a === 'undefined') { - return 0; - } - if (typeof a === 'number') { - return a - b; - } - if (typeof a === 'boolean') { - return a === b ? 0 : (a < b ? -1 : 1); - } - if (typeof a === 'string') { - return stringCollate(a, b); - } - if (Array.isArray(a)) { - return arrayCollate(a, b); - } - if (typeof a === 'object') { - return objectCollate(a, b); - } -};; -},{}]},{},[12]) -(12) -});
diff --git a/tests/integration/deps/pouchdb-2.0.0-postfixed.js b/tests/integration/deps/pouchdb-2.0.0-postfixed.js deleted file mode 100644 index 716e3e1..0000000 --- a/tests/integration/deps/pouchdb-2.0.0-postfixed.js +++ /dev/null
@@ -1,7569 +0,0 @@ -!function(e){if("object"==typeof exports)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.PouchDBVersion200=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);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ -"use strict"; - -var utils = _dereq_('./utils'); -var merge = _dereq_('./merge'); -var errors = _dereq_('./deps/errors'); -var EventEmitter = _dereq_('events').EventEmitter; -/* - * A generic pouch adapter - */ - -// returns first element of arr satisfying callback predicate -function arrayFirst(arr, callback) { - for (var i = 0; i < arr.length; i++) { - if (callback(arr[i], i) === true) { - return arr[i]; - } - } - return false; -} - -// Wrapper for functions that call the bulkdocs api with a single doc, -// if the first result is an error, return an error -function yankError(callback) { - return function (err, results) { - if (err || results[0].error) { - callback(err || results[0]); - } else { - callback(null, results[0]); - } - }; -} - -// for every node in a revision tree computes its distance from the closest -// leaf -function computeHeight(revs) { - var height = {}; - var edges = []; - merge.traverseRevTree(revs, function (isLeaf, pos, id, prnt) { - var rev = pos + "-" + id; - if (isLeaf) { - height[rev] = 0; - } - if (prnt !== undefined) { - edges.push({from: prnt, to: rev}); - } - return rev; - }); - - edges.reverse(); - edges.forEach(function (edge) { - if (height[edge.from] === undefined) { - height[edge.from] = 1 + height[edge.to]; - } else { - height[edge.from] = Math.min(height[edge.from], 1 + height[edge.to]); - } - }); - return height; -} -utils.inherits(AbstractPouchDBVersion200, EventEmitter); -module.exports = AbstractPouchDBVersion200; -function AbstractPouchDBVersion200() { - var self = this; - EventEmitter.call(this); - self.autoCompact = function (callback) { - if (!self.auto_compaction) { - return callback; - } - return function (err, res) { - if (err) { - callback(err); - } else { - var count = res.length; - var decCount = function () { - count--; - if (!count) { - callback(null, res); - } - }; - res.forEach(function (doc) { - if (doc.ok) { - // TODO: we need better error handling - self.compactDocument(doc.id, 1, decCount); - } else { - decCount(); - } - }); - } - }; - }; - var listeners = 0, changes; - var eventNames = ['change', 'delete', 'create', 'update']; - this.on('newListener', function (eventName) { - if (~eventNames.indexOf(eventName)) { - if (listeners) { - listeners++; - return; - } else { - listeners++; - } - } else { - return; - } - var lastChange = 0; - changes = this.changes({ - conflicts: true, - include_docs: true, - continuous: true, - since: 'latest', - onChange: function (change) { - if (change.seq <= lastChange) { - return; - } - lastChange = change.seq; - self.emit('change', change); - if (change.doc._deleted) { - self.emit('delete', change); - } else if (change.doc._rev.split('-')[0] === '1') { - self.emit('create', change); - } else { - self.emit('update', change); - } - } - }); - }); - this.on('removeListener', function (eventName) { - if (~eventNames.indexOf(eventName)) { - listeners--; - if (listeners) { - return; - } - } else { - return; - } - changes.cancel(); - }); -} -AbstractPouchDBVersion200.prototype.post = utils.toPromise(function (doc, opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - if (typeof doc !== 'object' || Array.isArray(doc)) { - return callback(errors.NOT_AN_OBJECT); - } - return this.bulkDocs({docs: [doc]}, opts, - this.autoCompact(yankError(callback))); -}); - -AbstractPouchDBVersion200.prototype.put = utils.toPromise(function () { - var args = Array.prototype.slice.call(arguments); - var temp, temptype, doc, id, opts, callback; - doc = args.shift(); - if (typeof doc !== 'object' || Array.isArray(doc)) { - callback = args.pop(); - return callback(errors.NOT_AN_OBJECT); - } - doc = utils.extend(true, {}, doc); - while (true) { - temp = args.shift(); - temptype = typeof temp; - if (temptype === "string" && !id) { - doc._id = temp; - id = true; - } else if (temptype === "string" && id) { - doc._rev = temp; - } else if (temptype === "object") { - opts = temp; - } else if (temptype === "function") { - callback = temp; - } - if (!args.length) { - break; - } - } - opts = opts || {}; - var error = utils.invalidIdError(doc._id); - if (error) { - return callback(error); - } - return this.bulkDocs({docs: [doc]}, opts, - this.autoCompact(yankError(callback))); -}); - -AbstractPouchDBVersion200.prototype.putAttachment = utils.toPromise(function (docId, attachmentId, rev, blob, type, callback) { - if (!this.taskqueue.isReady) { - this.taskqueue.addTask('putAttachment', arguments); - return; - } - var api = this; - if (typeof type === 'function') { - callback = type; - type = blob; - blob = rev; - rev = null; - } - if (typeof type === 'undefined') { - type = blob; - blob = rev; - rev = null; - } - - function createAttachment(doc) { - doc._attachments = doc._attachments || {}; - doc._attachments[attachmentId] = { - content_type: type, - data: blob - }; - api.put(doc, callback); - } - - api.get(docId, function (err, doc) { - // create new doc - if (err && err.error === errors.MISSING_DOC.error) { - createAttachment({_id: docId}); - return; - } - if (err) { - callback(err); - return; - } - - if (doc._rev !== rev) { - callback(errors.REV_CONFLICT); - return; - } - - createAttachment(doc); - }); -}); - -AbstractPouchDBVersion200.prototype.removeAttachment = utils.toPromise(function (docId, attachmentId, rev, callback) { - var self = this; - self.get(docId, function (err, obj) { - if (err) { - callback(err); - return; - } - if (obj._rev !== rev) { - callback(errors.REV_CONFLICT); - return; - } - if (!obj._attachments) { - return callback(); - } - delete obj._attachments[attachmentId]; - if (Object.keys(obj._attachments).length === 0) { - delete obj._attachments; - } - self.put(obj, callback); - }); -}); - -AbstractPouchDBVersion200.prototype.remove = utils.toPromise(function (doc, opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - if (opts === undefined) { - opts = {}; - } - opts = utils.extend(true, {}, opts); - opts.was_delete = true; - var newDoc = {_id: doc._id, _rev: doc._rev}; - newDoc._deleted = true; - return this.bulkDocs({docs: [newDoc]}, opts, yankError(callback)); -}); - -AbstractPouchDBVersion200.prototype.revsDiff = utils.toPromise(function (req, opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - opts = utils.extend(true, {}, opts); - var ids = Object.keys(req); - var count = 0; - var missing = {}; - - function addToMissing(id, revId) { - if (!missing[id]) { - missing[id] = {missing: []}; - } - missing[id].missing.push(revId); - } - - function processDoc(id, rev_tree) { - // Is this fast enough? Maybe we should switch to a set simulated by a map - var missingForId = req[id].slice(0); - merge.traverseRevTree(rev_tree, function (isLeaf, pos, revHash, ctx, - opts) { - var rev = pos + '-' + revHash; - var idx = missingForId.indexOf(rev); - if (idx === -1) { - return; - } - - missingForId.splice(idx, 1); - if (opts.status !== 'available') { - addToMissing(id, rev); - } - }); - - // Traversing the tree is synchronous, so now `missingForId` contains - // revisions that were not found in the tree - missingForId.forEach(function (rev) { - addToMissing(id, rev); - }); - } - - ids.map(function (id) { - this._getRevisionTree(id, function (err, rev_tree) { - if (err && err.name === 'not_found' && err.message === 'missing') { - missing[id] = {missing: req[id]}; - } else if (err) { - return callback(err); - } else { - processDoc(id, rev_tree); - } - - if (++count === ids.length) { - return callback(null, missing); - } - }); - }, this); -}); - -// compact one document and fire callback -// by compacting we mean removing all revisions which -// are further from the leaf in revision tree than max_height -AbstractPouchDBVersion200.prototype.compactDocument = function (docId, max_height, callback) { - var self = this; - this._getRevisionTree(docId, function (err, rev_tree) { - if (err) { - return callback(err); - } - var height = computeHeight(rev_tree); - var candidates = []; - var revs = []; - Object.keys(height).forEach(function (rev) { - if (height[rev] > max_height) { - candidates.push(rev); - } - }); - - merge.traverseRevTree(rev_tree, function (isLeaf, pos, revHash, ctx, opts) { - var rev = pos + '-' + revHash; - if (opts.status === 'available' && candidates.indexOf(rev) !== -1) { - opts.status = 'missing'; - revs.push(rev); - } - }); - self._doCompaction(docId, rev_tree, revs, callback); - }); -}; - -// compact the whole database using single document -// compaction -AbstractPouchDBVersion200.prototype.compact = utils.toPromise(function (opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - var self = this; - this.changes({complete: function (err, res) { - if (err) { - callback(); // TODO: silently fail - return; - } - var count = res.results.length; - if (!count) { - callback(); - return; - } - res.results.forEach(function (row) { - self.compactDocument(row.id, 0, function () { - count--; - if (!count) { - callback(); - } - }); - }); - }}); -}); - -/* Begin api wrappers. Specific functionality to storage belongs in the _[method] */ -AbstractPouchDBVersion200.prototype.get = utils.toPromise(function (id, opts, callback) { - if (!this.taskqueue.isReady) { - this.taskqueue.addTask('get', arguments); - return; - } - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - if (typeof id !== 'string') { - return callback(errors.INVALID_ID); - } - var leaves = [], self = this; - function finishOpenRevs() { - var result = []; - var count = leaves.length; - if (!count) { - return callback(null, result); - } - // order with open_revs is unspecified - leaves.forEach(function (leaf) { - self.get(id, {rev: leaf, revs: opts.revs, attachments: opts.attachments}, function (err, doc) { - if (!err) { - result.push({ok: doc}); - } else { - result.push({missing: leaf}); - } - count--; - if (!count) { - callback(null, result); - } - }); - }); - } - - if (opts.open_revs) { - if (opts.open_revs === "all") { - this._getRevisionTree(id, function (err, rev_tree) { - if (err) { - // if there's no such document we should treat this - // situation the same way as if revision tree was empty - rev_tree = []; - } - leaves = merge.collectLeaves(rev_tree).map(function (leaf) { - return leaf.rev; - }); - finishOpenRevs(); - }); - } else { - if (Array.isArray(opts.open_revs)) { - leaves = opts.open_revs; - for (var i = 0; i < leaves.length; i++) { - var l = leaves[i]; - // looks like it's the only thing couchdb checks - if (!(typeof(l) === "string" && /^\d+-/.test(l))) { - return callback(errors.error(errors.BAD_REQUEST, - "Invalid rev format")); - } - } - finishOpenRevs(); - } else { - return callback(errors.error(errors.UNKNOWN_ERROR, - 'function_clause')); - } - } - return; // open_revs does not like other options - } - - return this._get(id, opts, function (err, result) { - opts = utils.extend(true, {}, opts); - if (err) { - return callback(err); - } - - var doc = result.doc; - var metadata = result.metadata; - var ctx = result.ctx; - - if (opts.conflicts) { - var conflicts = merge.collectConflicts(metadata); - if (conflicts.length) { - doc._conflicts = conflicts; - } - } - - if (opts.revs || opts.revs_info) { - var paths = merge.rootToLeaf(metadata.rev_tree); - var path = arrayFirst(paths, function (arr) { - return arr.ids.map(function (x) { return x.id; }) - .indexOf(doc._rev.split('-')[1]) !== -1; - }); - - path.ids.splice(path.ids.map(function (x) {return x.id; }) - .indexOf(doc._rev.split('-')[1]) + 1); - path.ids.reverse(); - - if (opts.revs) { - doc._revisions = { - start: (path.pos + path.ids.length) - 1, - ids: path.ids.map(function (rev) { - return rev.id; - }) - }; - } - if (opts.revs_info) { - var pos = path.pos + path.ids.length; - doc._revs_info = path.ids.map(function (rev) { - pos--; - return { - rev: pos + '-' + rev.id, - status: rev.opts.status - }; - }); - } - } - - if (opts.local_seq) { - doc._local_seq = result.metadata.seq; - } - - if (opts.attachments && doc._attachments) { - var attachments = doc._attachments; - var count = Object.keys(attachments).length; - if (count === 0) { - return callback(null, doc); - } - Object.keys(attachments).forEach(function (key) { - this._getAttachment(attachments[key], {encode: true, ctx: ctx}, function (err, data) { - doc._attachments[key].data = data; - if (!--count) { - callback(null, doc); - } - }); - }, self); - } else { - if (doc._attachments) { - for (var key in doc._attachments) { - if (doc._attachments.hasOwnProperty(key)) { - doc._attachments[key].stub = true; - } - } - } - callback(null, doc); - } - }); -}); - -AbstractPouchDBVersion200.prototype.getAttachment = utils.toPromise(function (docId, attachmentId, opts, callback) { - if (!this.taskqueue.isReady) { - this.taskqueue.addTask('getAttachment', arguments); - return; - } - var self = this; - if (opts instanceof Function) { - callback = opts; - opts = {}; - } - opts = utils.extend(true, {}, opts); - this._get(docId, opts, function (err, res) { - if (err) { - return callback(err); - } - if (res.doc._attachments && res.doc._attachments[attachmentId]) { - opts.ctx = res.ctx; - self._getAttachment(res.doc._attachments[attachmentId], opts, callback); - } else { - return callback(errors.MISSING_DOC); - } - }); -}); - -AbstractPouchDBVersion200.prototype.allDocs = utils.toPromise(function (opts, callback) { - if (!this.taskqueue.isReady) { - this.taskqueue.addTask('allDocs', arguments); - return; - } - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - opts = utils.extend(true, {}, opts); - if ('keys' in opts) { - var incompatibleOpt = ['startkey', 'endkey', 'key'].filter(function (incompatibleOpt) { - return incompatibleOpt in opts; - })[0]; - if (incompatibleOpt) { - callback(errors.error(errors.QUERY_PARSE_ERROR, - 'Query parameter `' + incompatibleOpt + '` is not compatible with multi-get' - )); - return; - } - } - if (typeof opts.skip === 'undefined') { - opts.skip = 0; - } - - return this._allDocs(opts, callback); -}); - -function processChange(doc, metadata, opts) { - var changeList = [{rev: doc._rev}]; - if (opts.style === 'all_docs') { - changeList = merge.collectLeaves(metadata.rev_tree) - .map(function (x) { return {rev: x.rev}; }); - } - var change = { - id: metadata.id, - changes: changeList, - doc: doc - }; - - if (utils.isDeleted(metadata, doc._rev)) { - change.deleted = true; - } - if (opts.conflicts) { - change.doc._conflicts = merge.collectConflicts(metadata); - if (!change.doc._conflicts.length) { - delete change.doc._conflicts; - } - } - return change; -} -AbstractPouchDBVersion200.prototype.changes = function (opts) { - if (!this.taskqueue.isReady) { - var task = this.taskqueue.addTask('changes', arguments); - return { - cancel: function () { - if (task.task) { - return task.task.cancel(); - } - task.parameters[0].aborted = true; - } - }; - } - var api = this; - opts = utils.extend(true, {}, opts); - opts.processChange = processChange; - - if (!opts.since) { - opts.since = 0; - } - if (opts.since === 'latest') { - var changes; - api.info(function (err, info) { - if (!opts.aborted) { - opts.since = info.update_seq - 1; - changes = api.changes(opts); - } - }); - // Return a method to cancel this method from processing any more - return { - cancel: function () { - if (changes) { - return changes.cancel(); - } - opts.aborted = true; - } - }; - } - - if (opts.filter && typeof opts.filter === 'string') { - if (opts.filter === '_view') { - if (opts.view && typeof opts.view === 'string') { - // fetch a view from a design doc, make it behave like a filter - var viewName = opts.view.split('/'); - api.get('_design/' + viewName[0], function (err, ddoc) { - if (ddoc && ddoc.views && ddoc.views[viewName[1]]) { - /*jshint evil: true */ - var filter = eval('(function () {' + - ' return function (doc) {' + - ' var emitted = false;' + - ' var emit = function (a, b) {' + - ' emitted = true;' + - ' };' + - ' var view = ' + ddoc.views[viewName[1]].map + ';' + - ' view(doc);' + - ' if (emitted) {' + - ' return true;' + - ' }' + - ' }' + - '})()'); - if (!opts.aborted) { - opts.filter = filter; - api.changes(opts); - } - } else { - var msg = ddoc.views ? 'missing json key: ' + viewName[1] : - 'missing json key: views'; - err = err || errors.error(errors.MISSING_DOC, msg); - opts.complete(err); - } - }); - } else { - var err = errors.error(errors.BAD_REQUEST, - '`view` filter parameter is not provided.'); - opts.complete(err); - } - } else { - // fetch a filter from a design doc - var filterName = opts.filter.split('/'); - api.get('_design/' + filterName[0], function (err, ddoc) { - if (ddoc && ddoc.filters && ddoc.filters[filterName[1]]) { - /*jshint evil: true */ - var filter = eval('(function () { return ' + - ddoc.filters[filterName[1]] + ' })()'); - if (!opts.aborted) { - opts.filter = filter; - api.changes(opts); - } - } else { - var msg = (ddoc && ddoc.filters) ? 'missing json key: ' + filterName[1] - : 'missing json key: filters'; - err = err || errors.error(errors.MISSING_DOC, msg); - opts.complete(err); - } - }); - } - // Return a method to cancel this method from processing any more - return { - cancel: function () { - opts.complete(null, {status: 'cancelled'}); - opts.complete = null; - opts.aborted = true; - } - }; - } - - if (!('descending' in opts)) { - opts.descending = false; - } - - // 0 and 1 should return 1 document - opts.limit = opts.limit === 0 ? 1 : opts.limit; - return this._changes(opts); -}; - -AbstractPouchDBVersion200.prototype.close = utils.toPromise(function (callback) { - if (!this.taskqueue.isReady) { - this.taskqueue.addTask('close', arguments); - return; - } - return this._close(callback); -}); - -AbstractPouchDBVersion200.prototype.info = utils.toPromise(function (callback) { - if (!this.taskqueue.isReady) { - this.taskqueue.addTask('info', arguments); - return; - } - var self = this; - this._info(function (err, info) { - if (err) { - return callback(err); - } - var len = self.prefix.length; - if (info.db_name.length > len && info.db_name.slice(0, len) === self.prefix) { - info.db_name = info.db_name.slice(len); - } - callback(null, info); - }); -}); - -AbstractPouchDBVersion200.prototype.id = utils.toPromise(function (callback) { - if (!this.taskqueue.isReady) { - this.taskqueue.addTask('id', arguments); - return; - } - return this._id(callback); -}); - -AbstractPouchDBVersion200.prototype.type = function () { - return (typeof this._type === 'function') ? this._type() : this.adapter; -}; - -AbstractPouchDBVersion200.prototype.bulkDocs = utils.toPromise(function (req, opts, callback) { - if (!this.taskqueue.isReady) { - this.taskqueue.addTask('bulkDocs', arguments); - return; - } - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - if (!opts) { - opts = {}; - } else { - opts = utils.extend(true, {}, opts); - } - - if (!req || !req.docs) { - return callback(errors.MISSING_BULK_DOCS); - } - - if (!Array.isArray(req.docs)) { - return callback(errors.QUERY_PARSE_ERROR); - } - - for (var i = 0; i < req.docs.length; ++i) { - if (typeof req.docs[i] !== 'object' || Array.isArray(req.docs[i])) { - return callback(errors.NOT_AN_OBJECT); - } - } - - req = utils.extend(true, {}, req); - if (!('new_edits' in opts)) { - if ('new_edits' in req) { - opts.new_edits = req.new_edits; - } else { - opts.new_edits = true; - } - } - - return this._bulkDocs(req, opts, this.autoCompact(callback)); -}); - -},{"./deps/errors":8,"./merge":14,"./utils":18,"events":21}],2:[function(_dereq_,module,exports){ -"use strict"; - -var utils = _dereq_('../utils'); -var errors = _dereq_('../deps/errors'); -// parseUri 1.2.2 -// (c) Steven Levithan <stevenlevithan.com> -// MIT License -function parseUri(str) { - var o = parseUri.options; - var m = o.parser[o.strictMode ? "strict" : "loose"].exec(str); - var uri = {}; - var i = 14; - - while (i--) { - uri[o.key[i]] = m[i] || ""; - } - - uri[o.q.name] = {}; - uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) { - if ($1) { - uri[o.q.name][$1] = $2; - } - }); - - return uri; -} - -function encodeDocId(id) { - if (/^_(design|local)/.test(id)) { - return id; - } - return encodeURIComponent(id); -} - -parseUri.options = { - strictMode: false, - key: ["source", "protocol", "authority", "userInfo", "user", "password", "host", - "port", "relative", "path", "directory", "file", "query", "anchor"], - q: { - name: "queryKey", - parser: /(?:^|&)([^&=]*)=?([^&]*)/g - }, - parser: { - strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, - loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ - } -}; - -// Get all the information you possibly can about the URI given by name and -// return it as a suitable object. -function getHost(name, opts) { - // If the given name contains "http:" - if (/http(s?):/.test(name)) { - // Prase the URI into all its little bits - var uri = parseUri(name); - - // Store the fact that it is a remote URI - uri.remote = true; - - // 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 = 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('/'); - opts = opts || {}; - opts = utils.extend(true, {}, opts); - uri.headers = opts.headers || {}; - - if (opts.auth || uri.auth) { - var nAuth = opts.auth || uri.auth; - var token = utils.btoa(nAuth.username + ':' + nAuth.password); - uri.headers.Authorization = 'Basic ' + token; - } - - if (opts.headers) { - uri.headers = opts.headers; - } - - return uri; - } - - // If the given name does not contain 'http:' then return a very basic object - // with no host, the current path, the given name as the database name and no - // username/password - return {host: '', path: '/', db: name, auth: false}; -} - -// Generate a URL with the host data given by opts and the given path -function genDBUrl(opts, path) { - // If the host is remote - if (opts.remote) { - // If the host already has a path, then we need to have a path delimiter - // Otherwise, the path delimiter is the empty string - var pathDel = !opts.path ? '' : '/'; - - // Return the URL made up of all the host's information and the given path - return opts.protocol + '://' + opts.host + ':' + opts.port + '/' + - opts.path + pathDel + opts.db + '/' + path; - } - - // If the host is not remote, then return the URL made up of just the - // database name and the given path - return '/' + opts.db + '/' + path; -} - -// Generate a URL with the host data given by opts and the given path -function genUrl(opts, path) { - if (opts.remote) { - // If the host already has a path, then we need to have a path delimiter - // Otherwise, the path delimiter is the empty string - var pathDel = !opts.path ? '' : '/'; - - // If the host already has a path, then we need to have a path delimiter - // Otherwise, the path delimiter is the empty string - return opts.protocol + '://' + opts.host + ':' + opts.port + '/' + opts.path + pathDel + path; - } - - return '/' + path; -} -// Implements the PouchDBVersion200 API for dealing with CouchDB instances over HTTP -function HttpPouch(opts, callback) { - // Parse the URI given by opts.name into an easy-to-use object - var host = getHost(opts.name, opts); - - // Generate the database URL based on the host - var db_url = genDBUrl(host, ''); - - // The functions that will be publically available for HttpPouch - var api = this; - var ajaxOpts = opts.ajax || {}; - opts = utils.extend(true, {}, opts); - function ajax(options, callback) { - return utils.ajax(utils.extend({}, ajaxOpts, options), callback); - } - var uuids = { - list: [], - get: function (opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {count: 10}; - } - var cb = function (err, body) { - if (err || !('uuids' in body)) { - callback(err || errors.UNKNOWN_ERROR); - } else { - uuids.list = uuids.list.concat(body.uuids); - callback(null, "OK"); - } - }; - var params = '?count=' + opts.count; - ajax({ - headers: host.headers, - method: 'GET', - url: genUrl(host, '_uuids') + params - }, cb); - } - }; - - // Create a new CouchDB database based on the given opts - var createDB = function () { - ajax({headers: host.headers, method: 'PUT', url: db_url}, function (err, ret) { - // If we get an "Unauthorized" error - if (err && err.status === 401) { - // Test if the database already exists - ajax({headers: host.headers, method: 'HEAD', url: db_url}, function (err, ret) { - // If there is still an error - if (err) { - // Give the error to the callback to deal with - callback(err); - } else { - // Continue as if there had been no errors - callback(null, api); - } - }); - // If there were no errros or if the only error is "Precondition Failed" - // (note: "Precondition Failed" occurs when we try to create a database - // that already exists) - } else if (!err || err.status === 412) { - // Continue as if there had been no errors - callback(null, api); - } else { - callback(err); - } - }); - }; - if (!opts.skipSetup) { - ajax({headers: host.headers, method: 'GET', url: db_url}, function (err, ret) { - //check if the db exists - if (err) { - if (err.status === 404) { - //if it doesn't, create it - createDB(); - } else { - callback(err); - } - } else { - //go do stuff with the db - callback(null, api); - } - }); - } - - api.type = function () { - return 'http'; - }; - - api.id = utils.toPromise(function (callback) { - if (!api.taskqueue.isReady) { - api.taskqueue.addTask('id', arguments); - return; - } - ajax({ - headers: host.headers, - method: 'GET', - url: genUrl(host, '') - }, function (err, result) { - callback(null, result.uuid + host.db); - }); - }); - - api.request = utils.toPromise(function (options, callback) { - if (!api.taskqueue.isReady) { - api.taskqueue.addTask('request', arguments); - return; - } - options.headers = host.headers; - options.url = genDBUrl(host, options.url); - ajax(options, callback); - }); - - // Sends a POST request to the host calling the couchdb _compact function - // version: The version of CouchDB it is running - api.compact = utils.toPromise(function (opts, callback) { - if (!api.taskqueue.isReady) { - api.taskqueue.addTask('compact', arguments); - return; - } - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - opts = utils.extend(true, {}, opts); - ajax({ - headers: host.headers, - url: genDBUrl(host, '_compact'), - method: 'POST' - }, function () { - function ping() { - api.info(function (err, res) { - if (!res.compact_running) { - callback(); - } else { - setTimeout(ping, opts.interval || 200); - } - }); - } - // Ping the http if it's finished compaction - if (typeof callback === "function") { - ping(); - } - }); - }); - - // Calls GET on the host, which gets back a JSON string containing - // couchdb: A welcome string - // version: The version of CouchDB it is running - api._info = utils.toPromise(function (callback) { - if (!api.taskqueue.isReady) { - api.taskqueue.addTask('info', arguments); - return; - } - ajax({ - headers: host.headers, - method: 'GET', - url: genDBUrl(host, '') - }, function (err, res) { - if (err) { - callback(err); - } else { - res.host = genDBUrl(host, ''); - callback(null, res); - } - }); - }); - - // Get the document with the given id from the database given by host. - // The id could be solely the _id in the database, or it may be a - // _design/ID or _local/ID path - api.get = utils.toPromise(function (id, opts, callback) { - if (!api.taskqueue.isReady) { - api.taskqueue.addTask('get', arguments); - return; - } - // If no options were given, set the callback to the second parameter - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - opts = utils.extend(true, {}, opts); - if (opts.auto_encode === undefined) { - opts.auto_encode = true; - } - - // List of parameters to add to the GET request - var params = []; - - // If it exists, add the opts.revs value to the list of parameters. - // If revs=true then the resulting JSON will include a field - // _revisions containing an array of the revision IDs. - if (opts.revs) { - params.push('revs=true'); - } - - // If it exists, add the opts.revs_info value to the list of parameters. - // If revs_info=true then the resulting JSON will include the field - // _revs_info containing an array of objects in which each object - // representing an available revision. - if (opts.revs_info) { - params.push('revs_info=true'); - } - - if (opts.local_seq) { - params.push('local_seq=true'); - } - // If it exists, add the opts.open_revs value to the list of parameters. - // If open_revs=all then the resulting JSON will include all the leaf - // revisions. If open_revs=["rev1", "rev2",...] then the resulting JSON - // will contain an array of objects containing data of all revisions - if (opts.open_revs) { - if (opts.open_revs !== "all") { - opts.open_revs = JSON.stringify(opts.open_revs); - } - params.push('open_revs=' + opts.open_revs); - } - - // If it exists, add the opts.attachments value to the list of parameters. - // If attachments=true the resulting JSON will include the base64-encoded - // contents in the "data" property of each attachment. - if (opts.attachments) { - params.push('attachments=true'); - } - - // If it exists, add the opts.rev value to the list of parameters. - // If rev is given a revision number then get the specified revision. - if (opts.rev) { - params.push('rev=' + opts.rev); - } - - // If it exists, add the opts.conflicts value to the list of parameters. - // If conflicts=true then the resulting JSON will include the field - // _conflicts containing all the conflicting revisions. - if (opts.conflicts) { - params.push('conflicts=' + opts.conflicts); - } - - // Format the list of parameters into a valid URI query string - params = params.join('&'); - params = params === '' ? '' : '?' + params; - - if (opts.auto_encode) { - id = encodeDocId(id); - } - - // Set the options for the ajax call - var options = { - headers: host.headers, - method: 'GET', - url: genDBUrl(host, id + params) - }; - - // If the given id contains at least one '/' and the part before the '/' - // is NOT "_design" and is NOT "_local" - // OR - // If the given id contains at least two '/' and the part before the first - // '/' is "_design". - // TODO This second condition seems strange since if parts[0] === '_design' - // then we already know that parts[0] !== '_local'. - var parts = id.split('/'); - if ((parts.length > 1 && parts[0] !== '_design' && parts[0] !== '_local') || - (parts.length > 2 && parts[0] === '_design' && parts[0] !== '_local')) { - // Binary is expected back from the server - options.binary = true; - } - - // Get the document - ajax(options, function (err, doc, xhr) { - // If the document does not exist, send an error to the callback - if (err) { - return callback(err); - } - - // Send the document to the callback - callback(null, doc, xhr); - }); - }); - - // Delete the document given by doc from the database given by host. - api.remove = utils.toPromise(function (doc, opts, callback) { - if (!api.taskqueue.isReady) { - api.taskqueue.addTask('remove', arguments); - return; - } - // If no options were given, set the callback to be the second parameter - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - - // Delete the document - ajax({ - headers: host.headers, - method: 'DELETE', - url: genDBUrl(host, encodeDocId(doc._id)) + '?rev=' + doc._rev - }, callback); - }); - - // Get the attachment - api.getAttachment = utils.toPromise(function (docId, attachmentId, opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - opts = utils.extend(true, {}, opts); - if (opts.auto_encode === undefined) { - opts.auto_encode = true; - } - if (opts.auto_encode) { - docId = encodeDocId(docId); - } - opts.auto_encode = false; - api.get(docId + '/' + attachmentId, opts, callback); - }); - - // Remove the attachment given by the id and rev - api.removeAttachment = utils.toPromise(function (docId, attachmentId, rev, callback) { - if (!api.taskqueue.isReady) { - api.taskqueue.addTask('removeAttachment', arguments); - return; - } - ajax({ - headers: host.headers, - method: 'DELETE', - url: genDBUrl(host, encodeDocId(docId) + '/' + attachmentId) + '?rev=' + rev - }, callback); - }); - - // Add the attachment given by blob and its contentType property - // to the document with the given id, the revision given by rev, and - // add it to the database given by host. - api.putAttachment = utils.toPromise(function (docId, attachmentId, rev, blob, type, callback) { - if (!api.taskqueue.isReady) { - api.taskqueue.addTask('putAttachment', arguments); - return; - } - if (typeof type === 'function') { - callback = type; - type = blob; - blob = rev; - rev = null; - } - if (typeof type === 'undefined') { - type = blob; - blob = rev; - rev = null; - } - var id = encodeDocId(docId) + '/' + attachmentId; - var url = genDBUrl(host, id); - if (rev) { - url += '?rev=' + rev; - } - - var opts = { - headers: host.headers, - method: 'PUT', - url: url, - processData: false, - body: blob, - timeout: 60000 - }; - opts.headers['Content-Type'] = type; - // Add the attachment - ajax(opts, callback); - }); - - // Add the document given by doc (in JSON string format) to the database - // given by host. This fails if the doc has no _id field. - api.put = utils.toPromise(function () { - var args = Array.prototype.slice.call(arguments); - if (!api.taskqueue.isReady) { - api.taskqueue.addTask('put', args); - return; - } - var temp, temptype, doc, id, opts, callback; - doc = args.shift(); - if (typeof doc !== 'object' || Array.isArray(doc)) { - callback = args.pop(); - return callback(errors.NOT_AN_OBJECT); - } - doc = utils.extend(true, {}, doc); - while (true) { - temp = args.shift(); - temptype = typeof temp; - if (temptype === "string" && !id) { - doc._id = temp; - id = true; - } else if (temptype === "string" && id) { - doc._rev = temp; - } else if (temptype === "object") { - opts = utils.extend(true, {}, temp); - } else if (temptype === "function") { - callback = temp; - } - if (!args.length) { - break; - } - } - opts = opts || {}; - var error = utils.invalidIdError(doc._id); - if (error) { - return callback(error); - } - - // List of parameter to add to the PUT request - var params = []; - - // If it exists, add the opts.new_edits value to the list of parameters. - // If new_edits = false then the database will NOT assign this document a - // new revision number - if (opts && typeof opts.new_edits !== 'undefined') { - params.push('new_edits=' + opts.new_edits); - } - - // Format the list of parameters into a valid URI query string - params = params.join('&'); - if (params !== '') { - params = '?' + params; - } - - // Add the document - ajax({ - headers: host.headers, - method: 'PUT', - url: genDBUrl(host, encodeDocId(doc._id)) + params, - body: doc - }, callback); - }); - - // Add the document given by doc (in JSON string format) to the database - // given by host. This does not assume that doc is a new document (i.e. does not - // have a _id or a _rev field. - api.post = utils.toPromise(function (doc, opts, callback) { - if (!api.taskqueue.isReady) { - api.taskqueue.addTask('post', arguments); - return; - } - // If no options were given, set the callback to be the second parameter - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - opts = utils.extend(true, {}, opts); - if (typeof doc !== 'object') { - return callback(errors.NOT_AN_OBJECT); - } - if (! ("_id" in doc)) { - if (uuids.list.length > 0) { - doc._id = uuids.list.pop(); - api.put(doc, opts, callback); - } else { - uuids.get(function (err, resp) { - if (err) { - return callback(errors.UNKNOWN_ERROR); - } - doc._id = uuids.list.pop(); - api.put(doc, opts, callback); - }); - } - } else { - api.put(doc, opts, callback); - } - }); - - // Update/create multiple documents given by req in the database - // given by host. - api.bulkDocs = utils.toPromise(function (req, opts, callback) { - if (!api.taskqueue.isReady) { - api.taskqueue.addTask('bulkDocs', arguments); - return; - } - // If no options were given, set the callback to be the second parameter - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - if (!opts) { - opts = {}; - } - if (!Array.isArray(req.docs)) { - return callback(errors.error(errors.NOT_AN_OBJECT, "Missing JSON list of 'docs'")); - } - var bad = req.docs.filter(function (doc) { - return typeof doc !== 'object' || Array.isArray(doc); - }); - if (bad.length) { - return callback(errors.NOT_AN_OBJECT); - } - req = utils.extend(true, {}, req); - opts = utils.extend(true, {}, opts); - // If opts.new_edits exists add it to the document data to be - // send to the database. - // If new_edits=false then it prevents the database from creating - // new revision numbers for the documents. Instead it just uses - // the old ones. This is used in database replication. - if (typeof opts.new_edits !== 'undefined') { - req.new_edits = opts.new_edits; - } - - // Update/create the documents - ajax({ - headers: host.headers, - method: 'POST', - url: genDBUrl(host, '_bulk_docs'), - body: req - }, callback); - }); - - // Get a listing of the documents in the database given - // by host and ordered by increasing id. - api.allDocs = utils.toPromise(function (opts, callback) { - // If no options were given, set the callback to be the second parameter - if (!api.taskqueue.isReady) { - api.taskqueue.addTask('allDocs', arguments); - return; - } - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - opts = utils.extend(true, {}, opts); - // List of parameters to add to the GET request - var params = []; - var body; - var method = 'GET'; - - // TODO I don't see conflicts as a valid parameter for a - // _all_docs request (see http://wiki.apache.org/couchdb/HTTP_Document_API#all_docs) - if (opts.conflicts) { - params.push('conflicts=true'); - } - - // If opts.descending is truthy add it to params - if (opts.descending) { - params.push('descending=true'); - } - - // If opts.include_docs exists, add the include_docs value to the - // list of parameters. - // If include_docs=true then include the associated document with each - // result. - if (opts.include_docs) { - params.push('include_docs=true'); - } - - if (opts.key) { - params.push('key=' + encodeURIComponent(JSON.stringify(opts.key))); - } - - // If opts.startkey exists, add the startkey value to the list of - // parameters. - // If startkey is given then the returned list of documents will - // start with the document whose id is startkey. - if (opts.startkey) { - params.push('startkey=' + - encodeURIComponent(JSON.stringify(opts.startkey))); - } - - // If opts.endkey exists, add the endkey value to the list of parameters. - // If endkey is given then the returned list of docuemnts will - // end with the document whose id is endkey. - if (opts.endkey) { - params.push('endkey=' + encodeURIComponent(JSON.stringify(opts.endkey))); - } - - // If opts.limit exists, add the limit value to the parameter list. - if (opts.limit) { - params.push('limit=' + opts.limit); - } - - if (typeof opts.skip !== 'undefined') { - params.push('skip=' + opts.skip); - } - - // Format the list of parameters into a valid URI query string - params = params.join('&'); - if (params !== '') { - params = '?' + params; - } - - if (typeof opts.keys !== 'undefined') { - - var MAX_URL_LENGTH = 2000; - // according to http://stackoverflow.com/a/417184/680742, - // the de factor URL length limit is 2000 characters - - var keysAsString = 'keys=' + encodeURIComponent(JSON.stringify(opts.keys)); - if (keysAsString.length + params.length + 1 <= MAX_URL_LENGTH) { - // If the keys are short enough, do a GET. we do this to work around - // Safari not understanding 304s on POSTs (see issue #1239) - params += (params.indexOf('?') !== -1 ? '&' : '?') + keysAsString; - } else { - // If keys are too long, issue a POST request to circumvent GET query string limits - // see http://wiki.apache.org/couchdb/HTTP_view_API#Querying_Options - method = 'POST'; - body = JSON.stringify({keys: opts.keys}); - } - } - - // Get the document listing - ajax({ - headers: host.headers, - method: method, - url: genDBUrl(host, '_all_docs' + params), - body: body - }, callback); - }); - - // Get a list of changes made to documents in the database given by host. - // TODO According to the README, there should be two other methods here, - // api.changes.addListener and api.changes.removeListener. - api.changes = function (opts) { - // We internally page the results of a changes request, this means - // if there is a large set of changes to be returned we can start - // processing them quicker instead of waiting on the entire - // set of changes to return and attempting to process them at once - var CHANGES_LIMIT = 25; - - if (!api.taskqueue.isReady) { - var task = api.taskqueue.addTask('changes', arguments); - return { - cancel: function () { - if (task.task) { - return task.task.cancel(); - } else { - utils.call(opts.complete, null, {status: 'cancelled'}); - opts.complete = null; - } - task.parameters[0].aborted = true; - } - }; - } - - opts = utils.extend(true, {}, opts); - opts.timeout = opts.timeout || 0; - if (opts.since === 'latest') { - var changes = api.changes({ - descending: true, - limit: 1, - timeout: opts.timeout, - complete: function (err, info) { - if (err) { - opts.aborted = true; - utils.call(opts.complete, err); - return; - } - if (!opts.aborted) { - opts.since = info.last_seq; - changes = api.changes(opts); - } - } - }); - // Return a method to cancel this method from processing any more - return { - cancel: function () { - utils.call(opts.complete, null, {status: 'cancelled'}); - opts.complete = null; - if (changes) { - return changes.cancel(); - } - opts.aborted = true; - } - }; - } - - var params = {}; - var limit = (typeof opts.limit !== 'undefined') ? opts.limit : false; - if (limit === 0) { - limit = 1; - } - // - var leftToFetch = limit; - - if (opts.style) { - params.style = opts.style; - } - - if (opts.include_docs || opts.filter && typeof opts.filter === 'function') { - params.include_docs = true; - } - - if (opts.continuous) { - params.feed = 'longpoll'; - } - - if (opts.conflicts) { - params.conflicts = true; - } - - if (opts.descending) { - params.descending = true; - } - - if (opts.filter && typeof opts.filter === 'string') { - params.filter = opts.filter; - if (opts.filter === '_view' && opts.view && typeof opts.view === 'string') { - params.view = opts.view; - } - } - - // If opts.query_params exists, pass it through to the changes request. - // These parameters may be used by the filter on the source database. - if (opts.query_params && typeof opts.query_params === 'object') { - for (var param_name in opts.query_params) { - if (opts.query_params.hasOwnProperty(param_name)) { - params[param_name] = opts.query_params[param_name]; - } - } - } - - var xhr; - var lastFetchedSeq; - - // Get all the changes starting wtih the one immediately after the - // sequence number given by since. - var fetch = function (since, callback) { - params.since = since; - if (opts.descending) { - if (limit) { - params.limit = leftToFetch; - } - } else { - params.limit = (!limit || leftToFetch > CHANGES_LIMIT) ? - CHANGES_LIMIT : leftToFetch; - } - - var paramStr = '?' + Object.keys(params).map(function (k) { - return k + '=' + params[k]; - }).join('&'); - - // Set the options for the ajax call - var xhrOpts = { - headers: host.headers, - method: 'GET', - url: genDBUrl(host, '_changes' + paramStr), - // _changes can take a long time to generate, especially when filtered - timeout: opts.timeout - }; - lastFetchedSeq = since; - - if (opts.aborted) { - return; - } - - // Get the changes - xhr = ajax(xhrOpts, callback); - }; - - // If opts.since exists, get all the changes from the sequence - // number given by opts.since. Otherwise, get all the changes - // from the sequence number 0. - var fetchTimeout = 10; - var fetchRetryCount = 0; - - var results = {results: []}; - - var fetched = function (err, res) { - var raw_results_length = 0; - // If the result of the ajax call (res) contains changes (res.results) - if (res && res.results) { - raw_results_length = res.results.length; - results.last_seq = res.last_seq; - // For each change - var req = {}; - req.query = opts.query_params; - res.results = res.results.filter(function (c) { - leftToFetch--; - var ret = utils.filterChange(opts)(c); - if (ret) { - results.results.push(c); - utils.call(opts.onChange, c); - } - return ret; - }); - } else if (err) { - // In case of an error, stop listening for changes and call opts.complete - opts.aborted = true; - utils.call(opts.complete, err); - return; - } - - // The changes feed may have timed out with no results - // if so reuse last update sequence - if (res && res.last_seq) { - lastFetchedSeq = res.last_seq; - } - - var finished = (limit && leftToFetch <= 0) || - (res && raw_results_length < CHANGES_LIMIT) || - (opts.descending); - - if (opts.continuous || !finished) { - // Increase retry delay exponentially as long as errors persist - if (err) { - fetchRetryCount += 1; - } else { - fetchRetryCount = 0; - } - var timeoutMultiplier = 1 << fetchRetryCount; - var retryWait = fetchTimeout * timeoutMultiplier; - var maximumWait = opts.maximumWait || 30000; - - if (retryWait > maximumWait) { - utils.call(opts.complete, err || errors.UNKNOWN_ERROR); - return; - } - - // Queue a call to fetch again with the newest sequence number - setTimeout(function () { fetch(lastFetchedSeq, fetched); }, retryWait); - } else { - // We're done, call the callback - utils.call(opts.complete, null, results); - } - }; - - fetch(opts.since || 0, fetched); - - // Return a method to cancel this method from processing any more - return { - cancel: function () { - utils.call(opts.complete, null, {status: 'cancelled'}); - opts.complete = null; - opts.aborted = true; - xhr.abort(); - } - }; - }; - - // Given a set of document/revision IDs (given by req), tets the subset of - // those that do NOT correspond to revisions stored in the database. - // See http://wiki.apache.org/couchdb/HttpPostRevsDiff - api.revsDiff = utils.toPromise(function (req, opts, callback) { - if (!api.taskqueue.isReady) { - api.taskqueue.addTask('revsDiff', arguments); - return; - } - // If no options were given, set the callback to be the second parameter - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - - // Get the missing document/revision IDs - ajax({ - headers: host.headers, - method: 'POST', - url: genDBUrl(host, '_revs_diff'), - body: req - }, function (err, res) { - callback(err, res); - }); - }); - - api.close = utils.toPromise(function (callback) { - if (!api.taskqueue.isReady) { - api.taskqueue.addTask('close', arguments); - return; - } - callback(); - }); - - function replicateOnServer(target, opts, promise, targetHostUrl) { - opts = utils.extend(true, {}, opts); - var targetHost = getHost(targetHostUrl); - var params = { - source: host.db, - target: targetHost.protocol === host.protocol && - targetHost.authority === host.authority ? targetHost.db : targetHost.source - }; - - if (opts.continuous) { - params.continuous = true; - } - - if (opts.create_target) { - params.create_target = true; - } - - if (opts.doc_ids) { - params.doc_ids = opts.doc_ids; - } - - if (opts.filter && typeof opts.filter === 'string') { - params.filter = opts.filter; - } - - if (opts.query_params) { - params.query_params = opts.query_params; - } - - var result = {}; - var repOpts = { - headers: host.headers, - method: 'POST', - url: host.protocol + '://' + host.host + - (host.port === 80 ? '' : (':' + host.port)) + '/_replicate', - body: params - }; - - var xhr; - promise.cancel = function () { - this.cancelled = true; - if (xhr && !result.ok) { - xhr.abort(); - } - if (result._local_id) { - repOpts.body = { - replication_id: result._local_id - }; - } - repOpts.body.cancel = true; - ajax(repOpts, function (err, resp, xhr) { - // If the replication cancel request fails, send an error to the callback - if (err) { - return callback(err); - } - // Send the replication cancel result to the complete callback - utils.call(opts.complete, null, result, xhr); - }); - }; - - if (promise.cancelled) { - return; - } - - xhr = ajax(repOpts, function (err, resp, xhr) { - // If the replication fails, send an error to the callback - if (err) { - return callback(err); - } - - result.ok = true; - - // Provided by CouchDB from 1.2.0 onward to cancel replication - if (resp._local_id) { - result._local_id = resp._local_id; - } - - // Send the replication result to the complete callback - utils.call(opts.complete, null, resp, xhr); - }); - } - - api.replicateOnServer = function (target, opts, promise) { - if (!api.taskqueue.isReady) { - api.taskqueue.addTask('replicateOnServer', arguments); - return promise; - } - target.info(function (err, info) { - replicateOnServer(target, opts, promise, info.host); - }); - }; - api.destroy = utils.toPromise(function (callback) { - if (!api.taskqueue.isReady) { - api.taskqueue.addTask('destroy', arguments); - return; - } - utils.ajax({ - url: genDBUrl(host, ''), - method: 'DELETE' - }, function (err, resp) { - if (err) { - api.emit('error', err); - callback(err); - } else { - api.emit('destroyed'); - callback(null, resp); - } - }); - }); -} - -// Delete the HttpPouch specified by the given name. -HttpPouch.destroy = utils.toPromise(function (name, opts, callback) { - var host = getHost(name, opts); - opts = opts || {}; - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - opts = utils.extend(true, {}, opts); - opts.headers = host.headers; - opts.method = 'DELETE'; - opts.url = genDBUrl(host, ''); - utils.ajax(opts, callback); -}); - -// HttpPouch is a valid adapter. -HttpPouch.valid = function () { - return true; -}; - -module.exports = HttpPouch; - -},{"../deps/errors":8,"../utils":18}],3:[function(_dereq_,module,exports){ -(function (global){ -'use strict'; - -var utils = _dereq_('../utils'); -var merge = _dereq_('../merge'); -var errors = _dereq_('../deps/errors'); - -function idbError(callback) { - return function (event) { - callback(errors.error(errors.IDB_ERROR, event.target, event.type)); - }; -} - -function isModernIdb() { - // check for outdated implementations of IDB - // that rely on the setVersion method instead of onupgradeneeded (issue #1207) - - // cache based on appVersion, in case the browser is updated - var cacheKey = "_pouch__checkModernIdb_" + - (global.navigator && global.navigator.appVersion); - var cached = global.localStorage && global.localStorage[cacheKey]; - if (cached) { - return JSON.parse(cached); - } - - var dbName = '_pouch__checkModernIdb'; - var result = global.indexedDB.open(dbName, 1).onupgradeneeded === null; - - if (global.indexedDB.deleteDatabase) { - global.indexedDB.deleteDatabase(dbName); // db no longer needed - } - if (global.localStorage) { - global.localStorage[cacheKey] = JSON.stringify(result); // cache - } - return result; -} -function IdbPouch(opts, callback) { - - // IndexedDB requires a versioned database structure, so we use the - // version here to manage migrations. - var ADAPTER_VERSION = 2; - - // The object stores created for each database - // DOC_STORE stores the document meta data, its revision history and state - var DOC_STORE = 'document-store'; - // BY_SEQ_STORE stores a particular version of a document, keyed by its - // sequence id - var BY_SEQ_STORE = 'by-sequence'; - // Where we store attachments - var ATTACH_STORE = 'attach-store'; - // Where we store meta data - var META_STORE = 'meta-store'; - // Where we detect blob support - var DETECT_BLOB_SUPPORT_STORE = 'detect-blob-support'; - - var name = opts.name; - var req = global.indexedDB.open(name, ADAPTER_VERSION); - - if (!('openReqList' in IdbPouch)) { - IdbPouch.openReqList = {}; - } - IdbPouch.openReqList[name] = req; - - var blobSupport = null; - var instanceId = null; - var api = this; - var idb = null; - - req.onupgradeneeded = function (e) { - var db = e.target.result; - if (e.oldVersion < 1) { - // initial schema - createSchema(db); - } - if (e.oldVersion < 2) { - // version 2 adds the deletedOrLocal index - addDeletedOrLocalIndex(e); - } - }; - - function createSchema(db) { - db.createObjectStore(DOC_STORE, {keyPath : 'id'}) - .createIndex('seq', 'seq', {unique: true}); - db.createObjectStore(BY_SEQ_STORE, {autoIncrement : true}) - .createIndex('_doc_id_rev', '_doc_id_rev', {unique: true}); - db.createObjectStore(ATTACH_STORE, {keyPath: 'digest'}); - db.createObjectStore(META_STORE, {keyPath: 'id', autoIncrement: false}); - db.createObjectStore(DETECT_BLOB_SUPPORT_STORE); - } - - function addDeletedOrLocalIndex(e) { - var docStore = e.currentTarget.transaction.objectStore(DOC_STORE); - - docStore.openCursor().onsuccess = function (event) { - var cursor = event.target.result; - if (cursor) { - var metadata = cursor.value; - var deleted = utils.isDeleted(metadata); - var local = utils.isLocalId(metadata.id); - metadata.deletedOrLocal = (deleted || local) ? "1" : "0"; - docStore.put(metadata); - cursor['continue'](); - } else { - docStore.createIndex('deletedOrLocal', 'deletedOrLocal', {unique : false}); - } - }; - } - - req.onsuccess = function (e) { - - idb = e.target.result; - - idb.onversionchange = function () { - idb.close(); - }; - - var txn = idb.transaction([META_STORE, DETECT_BLOB_SUPPORT_STORE], - 'readwrite'); - - var req = txn.objectStore(META_STORE).get(META_STORE); - - req.onsuccess = function (e) { - - var idStored = false; - var checkSetupComplete = function () { - if (blobSupport === null || !idStored) { - return; - } else { - callback(null, api); - } - }; - - var meta = e.target.result || {id: META_STORE}; - if (name + '_id' in meta) { - instanceId = meta[name + '_id']; - idStored = true; - checkSetupComplete(); - } else { - instanceId = utils.uuid(); - meta[name + '_id'] = instanceId; - txn.objectStore(META_STORE).put(meta).onsuccess = function () { - idStored = true; - checkSetupComplete(); - }; - } - - // detect blob support - try { - txn.objectStore(DETECT_BLOB_SUPPORT_STORE).put(utils.createBlob(), "key"); - blobSupport = true; - } catch (err) { - blobSupport = false; - } finally { - checkSetupComplete(); - } - }; - }; - - req.onerror = idbError(callback); - - api.type = function () { - return 'idb'; - }; - - api._id = utils.toPromise(function (callback) { - callback(null, instanceId); - }); - - api._bulkDocs = function idb_bulkDocs(req, opts, callback) { - var newEdits = opts.new_edits; - var userDocs = req.docs; - // Parse the docs, give them a sequence number for the result - var docInfos = userDocs.map(function (doc, i) { - var newDoc = utils.parseDoc(doc, newEdits); - newDoc._bulk_seq = i; - return newDoc; - }); - - var docInfoErrors = docInfos.filter(function (docInfo) { - return docInfo.error; - }); - if (docInfoErrors.length) { - return callback(docInfoErrors[0]); - } - - var results = []; - var docsWritten = 0; - - function writeMetaData(e) { - var meta = e.target.result; - meta.updateSeq = (meta.updateSeq || 0) + docsWritten; - txn.objectStore(META_STORE).put(meta); - } - - function processDocs() { - if (!docInfos.length) { - txn.objectStore(META_STORE).get(META_STORE).onsuccess = writeMetaData; - return; - } - var currentDoc = docInfos.shift(); - var req = txn.objectStore(DOC_STORE).get(currentDoc.metadata.id); - req.onsuccess = function process_docRead(event) { - var oldDoc = event.target.result; - if (!oldDoc) { - insertDoc(currentDoc); - } else { - updateDoc(oldDoc, currentDoc); - } - }; - } - - function complete(event) { - var aresults = []; - results.sort(sortByBulkSeq); - results.forEach(function (result) { - delete result._bulk_seq; - if (result.error) { - aresults.push(result); - return; - } - var metadata = result.metadata; - var rev = merge.winningRev(metadata); - - aresults.push({ - ok: true, - id: metadata.id, - rev: rev - }); - - if (utils.isLocalId(metadata.id)) { - return; - } - - IdbPouch.Changes.notify(name); - IdbPouch.Changes.notifyLocalWindows(name); - }); - callback(null, aresults); - } - - function preprocessAttachment(att, finish) { - if (att.stub) { - return finish(); - } - if (typeof att.data === 'string') { - var data; - try { - data = atob(att.data); - } catch (e) { - var err = errors.error(errors.BAD_ARG, - "Attachments need to be base64 encoded"); - return callback(err); - } - att.digest = 'md5-' + utils.Crypto.MD5(data); - if (blobSupport) { - var type = att.content_type; - data = utils.fixBinary(data); - att.data = utils.createBlob([data], {type: type}); - } - return finish(); - } - var reader = new FileReader(); - reader.onloadend = function (e) { - att.digest = 'md5-' + utils.Crypto.MD5(this.result); - if (!blobSupport) { - att.data = btoa(this.result); - } - finish(); - }; - reader.readAsBinaryString(att.data); - } - - function preprocessAttachments(callback) { - if (!docInfos.length) { - return callback(); - } - - var docv = 0; - docInfos.forEach(function (docInfo) { - var attachments = docInfo.data && docInfo.data._attachments ? - Object.keys(docInfo.data._attachments) : []; - - if (!attachments.length) { - return done(); - } - - var recv = 0; - function attachmentProcessed() { - recv++; - if (recv === attachments.length) { - done(); - } - } - - for (var key in docInfo.data._attachments) { - if (docInfo.data._attachments.hasOwnProperty(key)) { - preprocessAttachment(docInfo.data._attachments[key], attachmentProcessed); - } - } - }); - - function done() { - docv++; - if (docInfos.length === docv) { - callback(); - } - } - } - - function writeDoc(docInfo, callback) { - var err = null; - var recv = 0; - docInfo.data._id = docInfo.metadata.id; - docInfo.data._rev = docInfo.metadata.rev; - - docsWritten++; - - if (utils.isDeleted(docInfo.metadata, docInfo.metadata.rev)) { - docInfo.data._deleted = true; - } - - var attachments = docInfo.data._attachments ? - Object.keys(docInfo.data._attachments) : []; - - function collectResults(attachmentErr) { - if (!err) { - if (attachmentErr) { - err = attachmentErr; - callback(err); - } else if (recv === attachments.length) { - finish(); - } - } - } - - function attachmentSaved(err) { - recv++; - collectResults(err); - } - - for (var key in docInfo.data._attachments) { - if (!docInfo.data._attachments[key].stub) { - var data = docInfo.data._attachments[key].data; - delete docInfo.data._attachments[key].data; - var digest = docInfo.data._attachments[key].digest; - saveAttachment(docInfo, digest, data, attachmentSaved); - } else { - recv++; - collectResults(); - } - } - - function finish() { - docInfo.data._doc_id_rev = docInfo.data._id + "::" + docInfo.data._rev; - var dataReq = txn.objectStore(BY_SEQ_STORE).put(docInfo.data); - dataReq.onsuccess = function (e) { - docInfo.metadata.seq = e.target.result; - // Current _rev is calculated from _rev_tree on read - delete docInfo.metadata.rev; - var deleted = utils.isDeleted(docInfo.metadata); - var local = utils.isLocalId(docInfo.metadata.id); - var metadata = utils.extend(true, {deletedOrLocal : (deleted || local) ? "1" : "0"}, docInfo.metadata); - var metaDataReq = txn.objectStore(DOC_STORE).put(metadata); - metaDataReq.onsuccess = function () { - results.push(docInfo); - utils.call(callback); - }; - }; - } - - if (!attachments.length) { - finish(); - } - } - - function updateDoc(oldDoc, docInfo) { - var merged = merge.merge(oldDoc.rev_tree, docInfo.metadata.rev_tree[0], 1000); - var wasPreviouslyDeleted = utils.isDeleted(oldDoc); - var inConflict = (wasPreviouslyDeleted && - utils.isDeleted(docInfo.metadata)) || - (!wasPreviouslyDeleted && newEdits && merged.conflicts !== 'new_leaf'); - - if (inConflict) { - results.push(makeErr(errors.REV_CONFLICT, docInfo._bulk_seq)); - return processDocs(); - } - - docInfo.metadata.rev_tree = merged.tree; - writeDoc(docInfo, processDocs); - } - - function insertDoc(docInfo) { - // Cant insert new deleted documents - if ('was_delete' in opts && utils.isDeleted(docInfo.metadata)) { - results.push(errors.MISSING_DOC); - return processDocs(); - } - writeDoc(docInfo, processDocs); - } - - // Insert sequence number into the error so we can sort later - function makeErr(err, seq) { - err._bulk_seq = seq; - return err; - } - - function saveAttachment(docInfo, digest, data, callback) { - var objectStore = txn.objectStore(ATTACH_STORE); - objectStore.get(digest).onsuccess = function (e) { - var originalRefs = e.target.result && e.target.result.refs || {}; - var ref = [docInfo.metadata.id, docInfo.metadata.rev].join('@'); - var newAtt = { - digest: digest, - body: data, - refs: originalRefs - }; - newAtt.refs[ref] = true; - objectStore.put(newAtt).onsuccess = function (e) { - utils.call(callback); - }; - }; - } - - var txn; - preprocessAttachments(function () { - txn = idb.transaction([DOC_STORE, BY_SEQ_STORE, ATTACH_STORE, META_STORE], - 'readwrite'); - txn.onerror = idbError(callback); - txn.ontimeout = idbError(callback); - txn.oncomplete = complete; - - processDocs(); - }); - }; - - function sortByBulkSeq(a, b) { - return a._bulk_seq - b._bulk_seq; - } - - // First we look up the metadata in the ids database, then we fetch the - // current revision(s) from the by sequence store - api._get = function idb_get(id, opts, callback) { - var doc; - var metadata; - var err; - var txn; - opts = utils.extend(true, {}, opts); - if (opts.ctx) { - txn = opts.ctx; - } else { - txn = idb.transaction([DOC_STORE, BY_SEQ_STORE, ATTACH_STORE], 'readonly'); - } - - function finish() { - callback(err, {doc: doc, metadata: metadata, ctx: txn}); - } - - txn.objectStore(DOC_STORE).get(id).onsuccess = function (e) { - metadata = e.target.result; - // we can determine the result here if: - // 1. there is no such document - // 2. the document is deleted and we don't ask about specific rev - // When we ask with opts.rev we expect the answer to be either - // doc (possibly with _deleted=true) or missing error - if (!metadata) { - err = errors.MISSING_DOC; - return finish(); - } - if (utils.isDeleted(metadata) && !opts.rev) { - err = errors.error(errors.MISSING_DOC, "deleted"); - return finish(); - } - - var rev = merge.winningRev(metadata); - var key = metadata.id + '::' + (opts.rev ? opts.rev : rev); - var index = txn.objectStore(BY_SEQ_STORE).index('_doc_id_rev'); - - index.get(key).onsuccess = function (e) { - doc = e.target.result; - if (doc && doc._doc_id_rev) { - delete(doc._doc_id_rev); - } - if (!doc) { - err = errors.MISSING_DOC; - return finish(); - } - finish(); - }; - }; - }; - - api._getAttachment = function (attachment, opts, callback) { - var result; - var txn; - opts = utils.extend(true, {}, opts); - if (opts.ctx) { - txn = opts.ctx; - } else { - txn = idb.transaction([DOC_STORE, BY_SEQ_STORE, ATTACH_STORE], 'readonly'); - } - var digest = attachment.digest; - var type = attachment.content_type; - - txn.objectStore(ATTACH_STORE).get(digest).onsuccess = function (e) { - var data = e.target.result.body; - if (opts.encode) { - if (blobSupport) { - var reader = new FileReader(); - reader.onloadend = function (e) { - result = btoa(this.result); - callback(null, result); - }; - reader.readAsBinaryString(data); - } else { - result = data; - callback(null, result); - } - } else { - if (blobSupport) { - result = data; - } else { - data = utils.fixBinary(atob(data)); - result = utils.createBlob([data], {type: type}); - } - callback(null, result); - } - }; - }; - - function allDocsKeysQuery(totalRows, opts, callback) { - var keys = opts.keys; - var descending = 'descending' in opts ? opts.descending : false; - - if (!keys.length) { // empty list is okay - callback(null, { - offset : opts.skip, - rows : [], - total_rows : totalRows - }); - } else { - // do a separate "key" query for each key in the keys array - var resultsToCollate = []; - keys.forEach(function (key) { - var subOpts = utils.extend(true, {}, opts); - subOpts.keys_request = true; // internal param, says this is a "keys" request - subOpts.key = key; - delete subOpts.keys; - delete subOpts.skip; - delete subOpts.limit; - - allDocsNormalQuery(totalRows, subOpts, function (err, res) { - resultsToCollate.push({err : err, res : res, key : key}); - if (resultsToCollate.length === keys.length) { - // all done, time to collate - var keysToResults = {}; - for (var i = 0; i < resultsToCollate.length; i++) { - var result = resultsToCollate[i]; - if (result.err) { - callback(err); - return; - } else { - keysToResults[result.key] = result; - } - } - var results = []; - keys.forEach(function (key) { - var result = keysToResults[key]; - if (result.res.rows.length) { - results.push(result.res.rows[0]); // only one result ever - } else { - results.push({"key": key, "error": "not_found"}); - } - }); - if (descending) { - results = results.reverse(); - } - callback(null, { - total_rows: totalRows, - offset: opts.skip, - rows: ('limit' in opts) ? results.slice(opts.skip, opts.limit + opts.skip) : - (opts.skip > 0) ? results.slice(opts.skip) : results - }); - } - }); - }); - } - } - - function allDocsNormalQuery(totalRows, opts, callback) { - var start = 'startkey' in opts ? opts.startkey : false; - var end = 'endkey' in opts ? opts.endkey : false; - var key = 'key' in opts ? opts.key : false; - - var descending = 'descending' in opts && opts.descending ? 'prev' : null; - - var skipped = 0; - - var manualDescEnd = false; - if (descending && start && end) { - // unfortunately IDB has a quirk where IDBKeyRange.bound is invalid if the - // start is less than the end, even in descending mode. Best bet - // is just to handle it manually in that case. - manualDescEnd = end; - end = false; - } - - var keyRange; - try { - keyRange = start && end ? global.IDBKeyRange.bound(start, end) - : start ? (descending ? global.IDBKeyRange.upperBound(start) : global.IDBKeyRange.lowerBound(start)) - : end ? (descending ? global.IDBKeyRange.lowerBound(end) : global.IDBKeyRange.upperBound(end)) - : key ? global.IDBKeyRange.only(key) : null; - } catch (e) { - if (e.name === "DataError" && e.code === 0) { - // data error, start is less than end - return callback(null, {total_rows : totalRows, offset : opts.skip, rows : []}); // no docs possible - } else { - return callback(errors.error(errors.IDB_ERROR, e.name, e.message)); - } - } - - var transaction = idb.transaction([DOC_STORE, BY_SEQ_STORE], 'readonly'); - transaction.oncomplete = function () { - callback(null, { - total_rows: totalRows, - offset: opts.skip, - rows: results - }); - }; - - var oStore = transaction.objectStore(DOC_STORE); - var oCursor = descending ? oStore.openCursor(keyRange, descending) - : oStore.openCursor(keyRange); - var results = []; - oCursor.onsuccess = function (e) { - if (!e.target.result) { - return; - } - var cursor = e.target.result; - var metadata = cursor.value; - - function allDocsInner(metadata, data) { - if (utils.isLocalId(metadata.id)) { - return cursor['continue'](); - } - var doc = { - id: metadata.id, - key: metadata.id, - value: { - rev: merge.winningRev(metadata) - } - }; - if (opts.include_docs) { - doc.doc = data; - doc.doc._rev = merge.winningRev(metadata); - if (doc.doc._doc_id_rev) { - delete(doc.doc._doc_id_rev); - } - if (opts.conflicts) { - doc.doc._conflicts = merge.collectConflicts(metadata); - } - for (var att in doc.doc._attachments) { - if (doc.doc._attachments.hasOwnProperty(att)) { - doc.doc._attachments[att].stub = true; - } - } - } - if (opts.keys_request) { - // deleted docs are okay with keys_requests - if (utils.isDeleted(metadata)) { - doc.value.deleted = true; - doc.doc = null; - } - results.push(doc); - } else if (!utils.isDeleted(metadata)) { - if (!results.length && opts.skip > 0 && skipped < opts.skip) { - skipped++; - } else if (manualDescEnd && doc.key <= manualDescEnd) { - if (doc.key === manualDescEnd) { - results.push(doc); - } - return; // done reading - } else if ('limit' in opts && results.length === opts.limit) { - return; // done reading - } else { - results.push(doc); - } - } - cursor['continue'](); - } - - if (!opts.include_docs) { - allDocsInner(metadata); - } else { - var index = transaction.objectStore(BY_SEQ_STORE).index('_doc_id_rev'); - var mainRev = merge.winningRev(metadata); - var key = metadata.id + "::" + mainRev; - index.get(key).onsuccess = function (event) { - allDocsInner(cursor.value, event.target.result); - }; - } - }; - } - - api._allDocs = function idb_allDocs(opts, callback) { - - // first count the total_rows using the undeleted/non-local count - var txn = idb.transaction([DOC_STORE], 'readonly'); - - var totalRows; - function countUndeletedNonlocalDocs(e) { - totalRows = e.target.result; - } - - var index = txn.objectStore(DOC_STORE).index('deletedOrLocal'); - index.count(global.IDBKeyRange.only("0")).onsuccess = countUndeletedNonlocalDocs; - - txn.onerror = idbError(callback); - - txn.oncomplete = function () { - if ('keys' in opts) { - allDocsKeysQuery(totalRows, opts, callback); - } else { - allDocsNormalQuery(totalRows, opts, callback); - } - }; - }; - - api._info = function idb_info(callback) { - var count = 0; - var update_seq = 0; - var txn = idb.transaction([DOC_STORE, META_STORE], 'readonly'); - - function fetchUpdateSeq(e) { - update_seq = e.target.result && e.target.result.updateSeq || 0; - } - - function countDocs(e) { - var cursor = e.target.result; - if (!cursor) { - txn.objectStore(META_STORE).get(META_STORE).onsuccess = fetchUpdateSeq; - return; - } - if (cursor.value.deleted !== true) { - count++; - } - cursor['continue'](); - } - - txn.oncomplete = function () { - callback(null, { - db_name: name, - doc_count: count, - update_seq: update_seq - }); - }; - - txn.objectStore(DOC_STORE).openCursor().onsuccess = countDocs; - }; - - api._changes = function idb_changes(opts) { - opts = utils.extend(true, {}, opts); - - if (opts.continuous) { - var id = name + ':' + utils.uuid(); - opts.cancelled = false; - IdbPouch.Changes.addListener(name, id, api, opts); - IdbPouch.Changes.notify(name); - return { - cancel: function () { - opts.complete(null, {status: 'cancelled'}); - opts.complete = null; - opts.cancelled = true; - IdbPouch.Changes.removeListener(name, id); - } - }; - } - - var descending = opts.descending ? 'prev' : null; - var last_seq = 0; - - // Ignore the `since` parameter when `descending` is true - opts.since = opts.since && !descending ? opts.since : 0; - - var results = [], resultIndices = {}, dedupResults = []; - var txn; - - function fetchChanges() { - txn = idb.transaction([DOC_STORE, BY_SEQ_STORE]); - txn.oncomplete = onTxnComplete; - - var req; - - if (descending) { - req = txn.objectStore(BY_SEQ_STORE) - .openCursor(global.IDBKeyRange.lowerBound(opts.since, true), descending); - } else { - req = txn.objectStore(BY_SEQ_STORE) - .openCursor(global.IDBKeyRange.lowerBound(opts.since, true)); - } - - req.onsuccess = onsuccess; - req.onerror = onerror; - } - - fetchChanges(); - - function onsuccess(event) { - if (!event.target.result) { - // Filter out null results casued by deduping - for (var i = 0, l = results.length; i < l; i++) { - var result = results[i]; - if (result) { - dedupResults.push(result); - } - } - return false; - } - - var cursor = event.target.result; - - // Try to pre-emptively dedup to save us a bunch of idb calls - var changeId = cursor.value._id; - var changeIdIndex = resultIndices[changeId]; - if (changeIdIndex !== undefined) { - results[changeIdIndex].seq = cursor.key; - // update so it has the later sequence number - results.push(results[changeIdIndex]); - results[changeIdIndex] = null; - resultIndices[changeId] = results.length - 1; - return cursor['continue'](); - } - - var index = txn.objectStore(DOC_STORE); - index.get(cursor.value._id).onsuccess = function (event) { - var metadata = event.target.result; - if (utils.isLocalId(metadata.id)) { - return cursor['continue'](); - } - - if (last_seq < metadata.seq) { - last_seq = metadata.seq; - } - - var mainRev = merge.winningRev(metadata); - var key = metadata.id + "::" + mainRev; - var index = txn.objectStore(BY_SEQ_STORE).index('_doc_id_rev'); - index.get(key).onsuccess = function (docevent) { - var doc = docevent.target.result; - delete doc['_doc_id_rev']; - - doc._rev = mainRev; - var change = opts.processChange(doc, metadata, opts); - change.seq = cursor.key; - - // Dedupe the changes feed - var changeId = change.id, changeIdIndex = resultIndices[changeId]; - if (changeIdIndex !== undefined) { - results[changeIdIndex] = null; - } - results.push(change); - resultIndices[changeId] = results.length - 1; - cursor['continue'](); - }; - }; - } - - function onTxnComplete() { - utils.processChanges(opts, dedupResults, last_seq); - } - }; - - api._close = function (callback) { - if (idb === null) { - return callback(errors.NOT_OPEN); - } - - // https://developer.mozilla.org/en-US/docs/IndexedDB/IDBDatabase#close - // "Returns immediately and closes the connection in a separate thread..." - idb.close(); - callback(); - }; - - api._getRevisionTree = function (docId, callback) { - var txn = idb.transaction([DOC_STORE], 'readonly'); - var req = txn.objectStore(DOC_STORE).get(docId); - req.onsuccess = function (event) { - var doc = event.target.result; - if (!doc) { - callback(errors.MISSING_DOC); - } else { - callback(null, doc.rev_tree); - } - }; - }; - - // This function removes revisions of document docId - // which are listed in revs and sets this document - // revision to to rev_tree - api._doCompaction = function (docId, rev_tree, revs, callback) { - var txn = idb.transaction([DOC_STORE, BY_SEQ_STORE], 'readwrite'); - - var index = txn.objectStore(DOC_STORE); - index.get(docId).onsuccess = function (event) { - var metadata = event.target.result; - metadata.rev_tree = rev_tree; - - var count = revs.length; - revs.forEach(function (rev) { - var index = txn.objectStore(BY_SEQ_STORE).index('_doc_id_rev'); - var key = docId + "::" + rev; - index.getKey(key).onsuccess = function (e) { - var seq = e.target.result; - if (!seq) { - return; - } - txn.objectStore(BY_SEQ_STORE)['delete'](seq); - - count--; - if (!count) { - if (metadata) { - var deleted = utils.isDeleted(metadata); - var local = utils.isLocalId(metadata.id); - metadata = utils.extend(true, {deletedOrLocal : (deleted || local) ? "1" : "0"}, metadata); - } - txn.objectStore(DOC_STORE).put(metadata); - } - }; - }); - }; - txn.oncomplete = function () { - utils.call(callback); - }; - }; - -} - -IdbPouch.valid = function () { - return global.indexedDB && isModernIdb(); -}; - -IdbPouch.destroy = utils.toPromise(function (name, opts, callback) { - if (!('openReqList' in IdbPouch)) { - IdbPouch.openReqList = {}; - } - IdbPouch.Changes.clearListeners(name); - - //Close open request for "name" database to fix ie delay. - if (IdbPouch.openReqList[name] && IdbPouch.openReqList[name].result) { - IdbPouch.openReqList[name].result.close(); - } - var req = global.indexedDB.deleteDatabase(name); - - req.onsuccess = function () { - //Remove open request from the list. - if (IdbPouch.openReqList[name]) { - IdbPouch.openReqList[name] = null; - } - callback(); - }; - - req.onerror = idbError(callback); -}); - -IdbPouch.Changes = new utils.Changes(); - -module.exports = IdbPouch; - -}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../deps/errors":8,"../merge":14,"../utils":18}],4:[function(_dereq_,module,exports){ -(function (global){ -'use strict'; - -var utils = _dereq_('../utils'); -var merge = _dereq_('../merge'); -var errors = _dereq_('../deps/errors'); -function quote(str) { - return "'" + str + "'"; -} - -function openDB() { - if (typeof global !== 'undefined') { - if (global.navigator && global.navigator.sqlitePlugin && - global.navigator.sqlitePlugin.openDatabase) { - return navigator.sqlitePlugin.openDatabase - .apply(navigator.sqlitePlugin, arguments); - } else if (global.sqlitePlugin && global.sqlitePlugin.openDatabase) { - return global.sqlitePlugin.openDatabase - .apply(global.sqlitePlugin, arguments); - } else { - return global.openDatabase.apply(global, arguments); - } - } -} - -var POUCH_VERSION = 1; -var POUCH_SIZE = 5 * 1024 * 1024; -var ADAPTER_VERSION = 2; // used to manage migrations - -// The object stores created for each database -// DOC_STORE stores the document meta data, its revision history and state -var DOC_STORE = quote('document-store'); -// BY_SEQ_STORE stores a particular version of a document, keyed by its -// sequence id -var BY_SEQ_STORE = quote('by-sequence'); -// Where we store attachments -var ATTACH_STORE = quote('attach-store'); -var META_STORE = quote('metadata-store'); - -// these indexes cover the ground for most allDocs queries -var BY_SEQ_STORE_DELETED_INDEX_SQL = 'CREATE INDEX IF NOT EXISTS \'by-seq-deleted-idx\' ON ' + - BY_SEQ_STORE + ' (seq, deleted)'; -var DOC_STORE_LOCAL_INDEX_SQL = 'CREATE INDEX IF NOT EXISTS \'doc-store-local-idx\' ON ' + - DOC_STORE + ' (local, id)'; -var DOC_STORE_WINNINGSEQ_INDEX_SQL = 'CREATE INDEX IF NOT EXISTS \'doc-winningseq-idx\' ON ' + - DOC_STORE + ' (winningseq)'; - - -var idRequests = []; -var cachedDatabases = {}; - -function unknownError(callback) { - return function (event) { - // event may actually be a SQLError object, so report is as such - var errorNameMatch = event && event.constructor.toString() - .match(/function ([^\(]+)/); - var errorName = (errorNameMatch && errorNameMatch[1]) || event.type; - var errorReason = event.target || event.message; - callback(errors.error(errors.WSQ_ERROR, errorReason, errorName)); - }; -} - -function parseHexString(str) { - var result = ''; - for (var i = 0, len = str.length; i < len; i += 2) { - result += String.fromCharCode(parseInt(str.substring(i, i + 2), 16)); - } - return result; -} - -// Safari is weird, it encodes everything with bonus \u0000 characters after -// every character rather than user agent sniff, we test every odd -// character for \u0000 -function isMangledUnicode(str) { - for (var i = 1, len = str.length; i < len; i += 2) { - if (str.charAt(i) !== '\u0000') { - return false; - } - } - return true; -} - -// unmangle the aforementioned Safari atrocity -function unmangleUnicode(str) { - var result = ''; - for (var i = 0, len = str.length; i < len; i += 2) { - result += str.charAt(i); - } - return result; -} - -// used to deal with utf8 encoding that occurs in most sqlite implementations -// partially taken from -// http://ecmanaut.blogspot.ca/2006/07/encoding-decoding-utf8-in-javascript.html -function decodeUtf8(str) { - var result; - try { - result = decodeURIComponent(window.escape(str)); - } catch (err) { - // URI error in safari, string is already escaped but still possibly mangled - result = str; - } - return isMangledUnicode(result) ? unmangleUnicode(result) : result; -} -function WebSqlPouch(opts, callback) { - var api = this; - var instanceId = null; - var name = opts.name; - - var db = cachedDatabases[name]; - if (!db) { - cachedDatabases[name] = db = openDB(name, POUCH_VERSION, name, POUCH_SIZE); - } - if (!db) { - return callback(errors.UNKNOWN_ERROR); - } - - function dbCreated() { - callback(null, api); - } - - // In this migration, we added the 'deleted' and 'local' columns to the by-seq and doc store tables. - // To preserve existing user data, we re-process all the existing JSON - // and add these values. - // Called migration2 because it corresponds to adapter version (db_version) #2 - function runMigration2(tx) { - - tx.executeSql(DOC_STORE_WINNINGSEQ_INDEX_SQL); // index used for the join in the allDocs query - - tx.executeSql('ALTER TABLE ' + BY_SEQ_STORE + ' ADD COLUMN deleted TINYINT(1) DEFAULT 0', [], function () { - tx.executeSql(BY_SEQ_STORE_DELETED_INDEX_SQL); - tx.executeSql('ALTER TABLE ' + DOC_STORE + ' ADD COLUMN local TINYINT(1) DEFAULT 0', [], function () { - tx.executeSql(DOC_STORE_LOCAL_INDEX_SQL); - - var sql = 'SELECT ' + DOC_STORE + '.winningseq AS seq, ' + DOC_STORE + '.json AS metadata FROM ' + - BY_SEQ_STORE + ' JOIN ' + DOC_STORE + ' ON ' + BY_SEQ_STORE + '.seq = ' + - DOC_STORE + '.winningseq'; - - tx.executeSql(sql, [], function (tx, result) { - - var deleted = []; - var local = []; - - for (var i = 0; i < result.rows.length; i++) { - var item = result.rows.item(i); - var seq = item.seq; - var metadata = JSON.parse(item.metadata); - if (utils.isDeleted(metadata)) { - deleted.push(seq); - } - if (utils.isLocalId(metadata.id)) { - local.push(metadata.id); - } - } - - tx.executeSql('UPDATE ' + DOC_STORE + 'SET local = 1 WHERE id IN (' + local.map(function () { - return '?'; - }).join(',') + ')', local); - tx.executeSql('UPDATE ' + BY_SEQ_STORE + ' SET deleted = 1 WHERE seq IN (' + deleted.map(function () { - return '?'; - }).join(',') + ')', deleted); - }); - }); - }); - } - - function onGetInstanceId() { - while (idRequests.length > 0) { - var idCallback = idRequests.pop(); - idCallback(null, instanceId); - } - } - - function onGetVersion(tx, dbVersion) { - if (dbVersion === 0) { - // initial schema - - var meta = 'CREATE TABLE IF NOT EXISTS ' + META_STORE + - ' (update_seq, dbid, db_version INTEGER)'; - var attach = 'CREATE TABLE IF NOT EXISTS ' + ATTACH_STORE + - ' (digest, json, body BLOB)'; - var doc = 'CREATE TABLE IF NOT EXISTS ' + DOC_STORE + - ' (id unique, seq, json, winningseq, local TINYINT(1))'; - var seq = 'CREATE TABLE IF NOT EXISTS ' + BY_SEQ_STORE + - ' (seq INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, doc_id_rev UNIQUE, json, deleted TINYINT(1))'; - - // creates - tx.executeSql(attach); - tx.executeSql(doc, [], function () { - tx.executeSql(DOC_STORE_WINNINGSEQ_INDEX_SQL); - tx.executeSql(DOC_STORE_LOCAL_INDEX_SQL); - }); - tx.executeSql(seq, [], function () { - tx.executeSql(BY_SEQ_STORE_DELETED_INDEX_SQL); - }); - tx.executeSql(meta, [], function () { - // mark the update_seq, db version, and new dbid - var initSeq = 'INSERT INTO ' + META_STORE + ' (update_seq, db_version, dbid) VALUES (?, ?, ?)'; - instanceId = utils.uuid(); - tx.executeSql(initSeq, [0, ADAPTER_VERSION, instanceId]); - onGetInstanceId(); - }); - } else { // version > 0 - - if (dbVersion === 1) { - runMigration2(tx); - // mark the db version within this transaction - tx.executeSql('UPDATE ' + META_STORE + ' SET db_version = ' + ADAPTER_VERSION); - } // in the future, add more migrations here - - // notify db.id() callers - tx.executeSql('SELECT dbid FROM ' + META_STORE, [], function (tx, result) { - instanceId = result.rows.item(0).dbid; - onGetInstanceId(); - }); - } - } - - function setup() { - - db.transaction(function (tx) { - // first get the version - tx.executeSql('SELECT sql FROM sqlite_master WHERE tbl_name = ' + META_STORE, [], function (tx, result) { - if (!result.rows.length) { - // database hasn't even been created yet (version 0) - onGetVersion(tx, 0); - } else if (!/db_version/.test(result.rows.item(0).sql)) { - // table was created, but without the new db_version column, so add it. - tx.executeSql('ALTER TABLE ' + META_STORE + ' ADD COLUMN db_version INTEGER', [], function () { - onGetVersion(tx, 1); // before version 2, this column didn't even exist - }); - } else { // column exists, we can safely get it - tx.executeSql('SELECT db_version FROM ' + META_STORE, [], function (tx, result) { - var dbVersion = result.rows.item(0).db_version; - onGetVersion(tx, dbVersion); - }); - } - }); - }, unknownError(callback), dbCreated); - } - - if (utils.isCordova() && typeof global !== 'undefined') { - //to wait until custom api is made in pouch.adapters before doing setup - global.addEventListener(name + '_pouch', function cordova_init() { - global.removeEventListener(name + '_pouch', cordova_init, false); - setup(); - }, false); - } else { - setup(); - } - - - api.type = function () { - return 'websql'; - }; - - api._id = utils.toPromise(function (callback) { - callback(null, instanceId); - }); - - api._info = function (callback) { - db.transaction(function (tx) { - var sql = 'SELECT COUNT(id) AS count FROM ' + DOC_STORE; - tx.executeSql(sql, [], function (tx, result) { - var doc_count = result.rows.item(0).count; - var updateseq = 'SELECT update_seq FROM ' + META_STORE; - tx.executeSql(updateseq, [], function (tx, result) { - var update_seq = result.rows.item(0).update_seq; - callback(null, { - db_name: name, - doc_count: doc_count, - update_seq: update_seq - }); - }); - }); - }); - }; - - api._bulkDocs = function (req, opts, callback) { - - var newEdits = opts.new_edits; - var userDocs = req.docs; - var docsWritten = 0; - - // Parse the docs, give them a sequence number for the result - var docInfos = userDocs.map(function (doc, i) { - var newDoc = utils.parseDoc(doc, newEdits); - newDoc._bulk_seq = i; - return newDoc; - }); - - var docInfoErrors = docInfos.filter(function (docInfo) { - return docInfo.error; - }); - if (docInfoErrors.length) { - return callback(docInfoErrors[0]); - } - - var tx; - var results = []; - var fetchedDocs = {}; - - function sortByBulkSeq(a, b) { - return a._bulk_seq - b._bulk_seq; - } - - function complete(event) { - var aresults = []; - results.sort(sortByBulkSeq); - results.forEach(function (result) { - delete result._bulk_seq; - if (result.error) { - aresults.push(result); - return; - } - var metadata = result.metadata; - var rev = merge.winningRev(metadata); - - aresults.push({ - ok: true, - id: metadata.id, - rev: rev - }); - - if (utils.isLocalId(metadata.id)) { - return; - } - - docsWritten++; - - WebSqlPouch.Changes.notify(name); - WebSqlPouch.Changes.notifyLocalWindows(name); - }); - - var updateseq = 'SELECT update_seq FROM ' + META_STORE; - tx.executeSql(updateseq, [], function (tx, result) { - var update_seq = result.rows.item(0).update_seq + docsWritten; - var sql = 'UPDATE ' + META_STORE + ' SET update_seq=?'; - tx.executeSql(sql, [update_seq], function () { - callback(null, aresults); - }); - }); - } - - function preprocessAttachment(att, finish) { - if (att.stub) { - return finish(); - } - if (typeof att.data === 'string') { - try { - att.data = atob(att.data); - } catch (e) { - var err = errors.error(errors.BAD_ARG, - "Attachments need to be base64 encoded"); - return callback(err); - } - var data = utils.fixBinary(att.data); - att.data = utils.createBlob([data], {type: att.content_type}); - } - var reader = new FileReader(); - reader.onloadend = function (e) { - att.data = this.result; - att.digest = 'md5-' + utils.Crypto.MD5(this.result); - finish(); - }; - reader.readAsBinaryString(att.data); - } - - function preprocessAttachments(callback) { - if (!docInfos.length) { - return callback(); - } - - var docv = 0; - - docInfos.forEach(function (docInfo) { - var attachments = docInfo.data && docInfo.data._attachments ? - Object.keys(docInfo.data._attachments) : []; - var recv = 0; - - if (!attachments.length) { - return done(); - } - - function processedAttachment() { - recv++; - if (recv === attachments.length) { - done(); - } - } - - for (var key in docInfo.data._attachments) { - if (docInfo.data._attachments.hasOwnProperty(key)) { - preprocessAttachment(docInfo.data._attachments[key], processedAttachment); - } - } - }); - - function done() { - docv++; - if (docInfos.length === docv) { - callback(); - } - } - } - - function writeDoc(docInfo, callback, isUpdate) { - - function finish() { - var data = docInfo.data; - var sql = 'INSERT INTO ' + BY_SEQ_STORE + ' (doc_id_rev, json, deleted) VALUES (?, ?, ?);'; - var sqlArgs = [ - data._id + "::" + data._rev, - JSON.stringify(data), - utils.isDeleted(docInfo.metadata, docInfo.metadata.rev) ? 1 : 0 - ]; - tx.executeSql(sql, sqlArgs, dataWritten); - } - - function collectResults(attachmentErr) { - if (!err) { - if (attachmentErr) { - err = attachmentErr; - callback(err); - } else if (recv === attachments.length) { - finish(); - } - } - } - - var err = null; - var recv = 0; - - docInfo.data._id = docInfo.metadata.id; - docInfo.data._rev = docInfo.metadata.rev; - - if (utils.isDeleted(docInfo.metadata, docInfo.metadata.rev)) { - docInfo.data._deleted = true; - } - - var attachments = docInfo.data._attachments ? - Object.keys(docInfo.data._attachments) : []; - - function attachmentSaved(err) { - recv++; - collectResults(err); - } - - for (var key in docInfo.data._attachments) { - if (!docInfo.data._attachments[key].stub) { - var data = docInfo.data._attachments[key].data; - delete docInfo.data._attachments[key].data; - var digest = docInfo.data._attachments[key].digest; - saveAttachment(docInfo, digest, data, attachmentSaved); - } else { - recv++; - collectResults(); - } - } - - if (!attachments.length) { - finish(); - } - - function dataWritten(tx, result) { - var seq = docInfo.metadata.seq = result.insertId; - delete docInfo.metadata.rev; - - var mainRev = merge.winningRev(docInfo.metadata); - - var sql = isUpdate ? - 'UPDATE ' + DOC_STORE + ' SET seq=?, json=?, winningseq=(SELECT seq FROM ' + - BY_SEQ_STORE + ' WHERE doc_id_rev=?) WHERE id=?' : - 'INSERT INTO ' + DOC_STORE + ' (id, seq, winningseq, json, local) VALUES (?, ?, ?, ?, ?);'; - var metadataStr = JSON.stringify(docInfo.metadata); - var key = docInfo.metadata.id + "::" + mainRev; - var local = utils.isLocalId(docInfo.metadata.id) ? 1 : 0; - var params = isUpdate ? - [seq, metadataStr, key, docInfo.metadata.id] : - [docInfo.metadata.id, seq, seq, metadataStr, local]; - tx.executeSql(sql, params, function (tx, result) { - results.push(docInfo); - callback(); - }); - } - } - - function updateDoc(oldDoc, docInfo) { - var merged = merge.merge(oldDoc.rev_tree, docInfo.metadata.rev_tree[0], 1000); - var inConflict = (utils.isDeleted(oldDoc) && - utils.isDeleted(docInfo.metadata)) || - (!utils.isDeleted(oldDoc) && - newEdits && merged.conflicts !== 'new_leaf'); - - if (inConflict) { - results.push(makeErr(errors.REV_CONFLICT, docInfo._bulk_seq)); - return processDocs(); - } - - docInfo.metadata.rev_tree = merged.tree; - writeDoc(docInfo, processDocs, true); - } - - function insertDoc(docInfo) { - // Cant insert new deleted documents - if ('was_delete' in opts && utils.isDeleted(docInfo.metadata)) { - results.push(errors.MISSING_DOC); - return processDocs(); - } - writeDoc(docInfo, processDocs, false); - } - - function processDocs() { - if (!docInfos.length) { - return complete(); - } - var currentDoc = docInfos.shift(); - var id = currentDoc.metadata.id; - if (id in fetchedDocs) { - updateDoc(fetchedDocs[id], currentDoc); - } else { - // if we have newEdits=false then we can update the same - // document twice in a single bulk docs call - fetchedDocs[id] = currentDoc.metadata; - insertDoc(currentDoc); - } - } - - // Insert sequence number into the error so we can sort later - function makeErr(err, seq) { - err._bulk_seq = seq; - return err; - } - - function saveAttachment(docInfo, digest, data, callback) { - var ref = [docInfo.metadata.id, docInfo.metadata.rev].join('@'); - var newAtt = {digest: digest}; - var sql = 'SELECT digest, json FROM ' + ATTACH_STORE + ' WHERE digest=?'; - tx.executeSql(sql, [digest], function (tx, result) { - if (!result.rows.length) { - newAtt.refs = {}; - newAtt.refs[ref] = true; - sql = 'INSERT INTO ' + ATTACH_STORE + '(digest, json, body) VALUES (?, ?, ?)'; - tx.executeSql(sql, [digest, JSON.stringify(newAtt), data], function () { - callback(); - }); - } else { - newAtt.refs = JSON.parse(result.rows.item(0).json).refs; - sql = 'UPDATE ' + ATTACH_STORE + ' SET json=?, body=? WHERE digest=?'; - tx.executeSql(sql, [JSON.stringify(newAtt), data, digest], function () { - callback(); - }); - } - }); - } - - function metadataFetched(tx, results) { - for (var j = 0; j < results.rows.length; j++) { - var row = results.rows.item(j); - fetchedDocs[row.id] = JSON.parse(row.json); - } - processDocs(); - } - - preprocessAttachments(function () { - db.transaction(function (txn) { - tx = txn; - var sql = 'SELECT * FROM ' + DOC_STORE + ' WHERE id IN ' + - '(' + docInfos.map(function () {return '?'; }).join(',') + ')'; - var queryArgs = docInfos.map(function (d) { return d.metadata.id; }); - tx.executeSql(sql, queryArgs, metadataFetched); - }, unknownError(callback)); - }); - }; - - api._get = function (id, opts, callback) { - opts = utils.extend(true, {}, opts); - var doc; - var metadata; - var err; - if (!opts.ctx) { - db.transaction(function (txn) { - opts.ctx = txn; - api._get(id, opts, callback); - }); - return; - } - var tx = opts.ctx; - - function finish() { - callback(err, {doc: doc, metadata: metadata, ctx: tx}); - } - - var sql = 'SELECT * FROM ' + DOC_STORE + ' WHERE id=?'; - tx.executeSql(sql, [id], function (a, results) { - if (!results.rows.length) { - err = errors.MISSING_DOC; - return finish(); - } - metadata = JSON.parse(results.rows.item(0).json); - if (utils.isDeleted(metadata) && !opts.rev) { - err = errors.error(errors.MISSING_DOC, "deleted"); - return finish(); - } - - var rev = merge.winningRev(metadata); - var key = opts.rev ? opts.rev : rev; - key = metadata.id + '::' + key; - var sql = 'SELECT * FROM ' + BY_SEQ_STORE + ' WHERE doc_id_rev=?'; - tx.executeSql(sql, [key], function (tx, results) { - if (!results.rows.length) { - err = errors.MISSING_DOC; - return finish(); - } - doc = JSON.parse(results.rows.item(0).json); - - finish(); - }); - }); - }; - - api._allDocs = function (opts, callback) { - var results = []; - var resultsMap = {}; - var totalRows; - - var from = BY_SEQ_STORE + ' JOIN ' + DOC_STORE + ' ON ' + BY_SEQ_STORE + '.seq = ' + - DOC_STORE + '.winningseq'; - - var start = 'startkey' in opts ? opts.startkey : false; - var end = 'endkey' in opts ? opts.endkey : false; - var key = 'key' in opts ? opts.key : false; - var descending = 'descending' in opts ? opts.descending : false; - var keys = 'keys' in opts ? opts.keys : false; - var limit = 'limit' in opts ? opts.limit : false; - var offset = 'skip' in opts ? opts.skip : false; - - var sqlArgs = []; - var criteria = [DOC_STORE + '.local = 0']; - - if (key !== false) { - criteria.push(DOC_STORE + '.id = ?'); - sqlArgs.push(key); - } else if (keys !== false) { - criteria.push(DOC_STORE + '.id in (' + keys.map(function () { - return '?'; - }).join(',') + ')'); - sqlArgs = sqlArgs.concat(keys); - } else if (start !== false || end !== false) { - if (start !== false) { - criteria.push(DOC_STORE + '.id ' + (descending ? '<=' : '>=') + ' ?'); - sqlArgs.push(start); - } - if (end !== false) { - criteria.push(DOC_STORE + '.id ' + (descending ? '>=' : '<=') + ' ?'); - sqlArgs.push(end); - } - if (key !== false) { - criteria.push(DOC_STORE + '.id = ?'); - sqlArgs.push(key); - } - } - - if (keys === false) { - // report deleted if keys are specified - criteria.push(BY_SEQ_STORE + '.deleted = 0'); - } - - db.transaction(function (tx) { - - // first count up the total rows - var sql = 'SELECT COUNT(' + DOC_STORE + '.id) AS \'num\' FROM ' + - from + ' WHERE ' + BY_SEQ_STORE + '.deleted = 0 AND ' + - // local docs are e.g. '_local_foo' - DOC_STORE + '.local = 0'; - - tx.executeSql(sql, [], function (tx, result) { - totalRows = result.rows.item(0).num; - - // then actually fetch the documents - - var sql = 'SELECT ' + DOC_STORE + '.id, ' + BY_SEQ_STORE + '.seq, ' + - BY_SEQ_STORE + '.json AS data, ' + DOC_STORE + '.json AS metadata FROM ' + from; - - if (criteria.length) { - sql += ' WHERE ' + criteria.join(' AND '); - } - sql += ' ORDER BY ' + DOC_STORE + '.id ' + (descending ? 'DESC' : 'ASC'); - if (limit !== false) { - sql += ' LIMIT ' + limit; - } - if (offset !== false && offset > 0) { - if (limit === false) { - // sqlite requires limit with offset, -1 acts as infinity here - sql += ' LIMIT -1'; - } - sql += ' OFFSET ' + offset; - } - - tx.executeSql(sql, sqlArgs, function (tx, result) { - for (var i = 0, l = result.rows.length; i < l; i++) { - var doc = result.rows.item(i); - var metadata = JSON.parse(doc.metadata); - var data = JSON.parse(doc.data); - doc = { - id: metadata.id, - key: metadata.id, - value: {rev: merge.winningRev(metadata)} - }; - if (opts.include_docs) { - doc.doc = data; - doc.doc._rev = merge.winningRev(metadata); - if (opts.conflicts) { - doc.doc._conflicts = merge.collectConflicts(metadata); - } - for (var att in doc.doc._attachments) { - if (doc.doc._attachments.hasOwnProperty(att)) { - doc.doc._attachments[att].stub = true; - } - } - } - if ('keys' in opts) { - if (opts.keys.indexOf(metadata.id) > -1) { - if (utils.isDeleted(metadata)) { - doc.value.deleted = true; - doc.doc = null; - } - resultsMap[doc.id] = doc; - } - } else { - results.push(doc); - } - } - }); - }); - }, unknownError(callback), function () { - if ('keys' in opts) { - opts.keys.forEach(function (key) { - if (key in resultsMap) { - results.push(resultsMap[key]); - } else { - results.push({"key": key, "error": "not_found"}); - } - }); - if (opts.descending) { - results.reverse(); - } - } - callback(null, { - total_rows: totalRows, - offset: opts.skip, - rows: results - }); - }); - }; - - api._changes = function idb_changes(opts) { - opts = utils.extend(true, {}, opts); - - - //console.log(name + ': Start Changes Feed: continuous=' + opts.continuous); - - - if (opts.continuous) { - var id = name + ':' + utils.uuid(); - opts.cancelled = false; - WebSqlPouch.Changes.addListener(name, id, api, opts); - WebSqlPouch.Changes.notify(name); - return { - cancel: function () { - opts.complete(null, {status: 'cancelled'}); - opts.complete = null; - opts.cancelled = true; - WebSqlPouch.Changes.removeListener(name, id); - } - }; - } - - var descending = opts.descending; - - // Ignore the `since` parameter when `descending` is true - opts.since = opts.since && !descending ? opts.since : 0; - - var results = []; - - function fetchChanges() { - var sql = 'SELECT ' + DOC_STORE + '.id, ' + BY_SEQ_STORE + '.seq, ' + - BY_SEQ_STORE + '.json AS data, ' + DOC_STORE + '.json AS metadata FROM ' + - BY_SEQ_STORE + ' JOIN ' + DOC_STORE + ' ON ' + BY_SEQ_STORE + '.seq = ' + - DOC_STORE + '.winningseq WHERE ' + DOC_STORE + '.seq > ' + opts.since + - ' ORDER BY ' + DOC_STORE + '.seq ' + (descending ? 'DESC' : 'ASC'); - - db.transaction(function (tx) { - tx.executeSql(sql, [], function (tx, result) { - var last_seq = 0; - for (var i = 0, l = result.rows.length; i < l; i++) { - var res = result.rows.item(i); - var metadata = JSON.parse(res.metadata); - if (!utils.isLocalId(metadata.id)) { - if (last_seq < res.seq) { - last_seq = res.seq; - } - var doc = JSON.parse(res.data); - var change = opts.processChange(doc, metadata, opts); - change.seq = res.seq; - - results.push(change); - } - } - utils.processChanges(opts, results, last_seq); - }); - }); - } - - fetchChanges(); - }; - - api._close = function (callback) { - //WebSQL databases do not need to be closed - callback(); - }; - - api._getAttachment = function (attachment, opts, callback) { - var res; - var tx = opts.ctx; - var digest = attachment.digest; - var type = attachment.content_type; - var sql = 'SELECT hex(body) as body FROM ' + ATTACH_STORE + ' WHERE digest=?'; - tx.executeSql(sql, [digest], function (tx, result) { - // TODO: sqlite normally stores data as utf8, so even the hex() function "encodes" the binary - // data in utf8 before returning it, and yet hex() is the only way to get the full data. so we do this. - var data = decodeUtf8(parseHexString(result.rows.item(0).body)); - if (opts.encode) { - res = btoa(data); - } else { - data = utils.fixBinary(data); - res = utils.createBlob([data], {type: type}); - } - callback(null, res); - }); - }; - - api._getRevisionTree = function (docId, callback) { - db.transaction(function (tx) { - var sql = 'SELECT json AS metadata FROM ' + DOC_STORE + ' WHERE id = ?'; - tx.executeSql(sql, [docId], function (tx, result) { - if (!result.rows.length) { - callback(errors.MISSING_DOC); - } else { - var data = JSON.parse(result.rows.item(0).metadata); - callback(null, data.rev_tree); - } - }); - }); - }; - - api._doCompaction = function (docId, rev_tree, revs, callback) { - db.transaction(function (tx) { - var sql = 'SELECT json AS metadata FROM ' + DOC_STORE + ' WHERE id = ?'; - tx.executeSql(sql, [docId], function (tx, result) { - if (!result.rows.length) { - return utils.call(callback); - } - var metadata = JSON.parse(result.rows.item(0).metadata); - metadata.rev_tree = rev_tree; - - var sql = 'DELETE FROM ' + BY_SEQ_STORE + ' WHERE doc_id_rev IN (' + - revs.map(function (rev) {return quote(docId + '::' + rev); }).join(',') + ')'; - - tx.executeSql(sql, [], function (tx, result) { - var sql = 'UPDATE ' + DOC_STORE + ' SET json = ? WHERE id = ?'; - - tx.executeSql(sql, [JSON.stringify(metadata), docId], function (tx, result) { - callback(); - }); - }); - }); - }); - }; -} - -WebSqlPouch.valid = function () { - if (typeof global !== 'undefined') { - if (global.navigator && global.navigator.sqlitePlugin && global.navigator.sqlitePlugin.openDatabase) { - return true; - } else if (global.sqlitePlugin && global.sqlitePlugin.openDatabase) { - return true; - } else if (global.openDatabase) { - return true; - } - } - return false; -}; - -WebSqlPouch.destroy = utils.toPromise(function (name, opts, callback) { - var self = this; - var db = openDB(name, POUCH_VERSION, name, POUCH_SIZE); - db.transaction(function (tx) { - tx.executeSql('DROP TABLE IF EXISTS ' + DOC_STORE, []); - tx.executeSql('DROP TABLE IF EXISTS ' + BY_SEQ_STORE, []); - tx.executeSql('DROP TABLE IF EXISTS ' + ATTACH_STORE, []); - tx.executeSql('DROP TABLE IF EXISTS ' + META_STORE, []); - }, unknownError(callback), function () { - self.emit('destroyed'); - callback(); - }); -}); - -WebSqlPouch.Changes = new utils.Changes(); - -module.exports = WebSqlPouch; - -}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../deps/errors":8,"../merge":14,"../utils":18}],5:[function(_dereq_,module,exports){ -(function (global){ -/*globals cordova */ -"use strict"; - -var Adapter = _dereq_('./adapter'); -var utils = _dereq_('./utils'); -var Promise = typeof global.Promise === 'function' ? global.Promise : _dereq_('bluebird'); -var TaskQueue = _dereq_('./taskqueue'); - -function defaultCallback(err) { - if (err && global.debug) { - console.error(err); - } -} -utils.inherits(PouchDBVersion200, Adapter); -function PouchDBVersion200(name, opts, callback) { - - if (!(this instanceof PouchDBVersion200)) { - return new PouchDBVersion200(name, opts, callback); - } - var self = this; - if (typeof opts === 'function' || typeof opts === 'undefined') { - callback = opts; - opts = {}; - } - - if (typeof name === 'object') { - opts = name; - name = undefined; - } - if (typeof callback === 'undefined') { - callback = defaultCallback; - } - opts = opts || {}; - var oldCB = callback; - self.auto_compaction = opts.auto_compaction; - self.prefix = PouchDBVersion200.prefix; - Adapter.call(self); - self.taskqueue = new TaskQueue(); - var promise = new Promise(function (fulfill, reject) { - callback = function (err, resp) { - if (err) { - return reject(err); - } - delete resp.then; - fulfill(resp); - }; - - opts = utils.extend(true, {}, opts); - var originalName = opts.name || name; - var backend, error; - (function () { - try { - - if (typeof originalName !== 'string') { - error = new Error('Missing/invalid DB name'); - error.code = 400; - throw error; - } - - backend = PouchDBVersion200.parseAdapter(originalName); - - opts.originalName = originalName; - opts.name = backend.name; - opts.adapter = opts.adapter || backend.adapter; - - if (!PouchDBVersion200.adapters[opts.adapter]) { - error = new Error('Adapter is missing'); - error.code = 404; - throw error; - } - - if (!PouchDBVersion200.adapters[opts.adapter].valid()) { - error = new Error('Invalid Adapter'); - error.code = 404; - throw error; - } - } catch (err) { - self.taskqueue.fail(err); - self.changes = utils.toPromise(function (opts) { - if (opts.complete) { - opts.complete(err); - } - }); - } - }()); - if (error) { - return reject(error); // constructor error, see above - } - self.adapter = opts.adapter; - // needs access to PouchDBVersion200; - self.replicate = PouchDBVersion200.replicate.bind(self, self); - self.replicate.from = function (url, opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - return PouchDBVersion200.replicate(url, self, opts, callback); - }; - - self.replicate.to = function (dbName, opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - return self.replicate(dbName, opts, callback); - }; - - self.replicate.sync = function (dbName, opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - return PouchDBVersion200.sync(self, dbName, opts, callback); - }; - self.destroy = utils.toPromise(function (callback) { - var self = this; - if (!self.taskqueue.isReady) { - self.taskqueue.addTask('destroy', arguments); - return; - } - self.id(function (err, id) { - if (err) { - return callback(err); - } - PouchDBVersion200.destroy(id, callback); - }); - }); - PouchDBVersion200.adapters[opts.adapter].call(self, opts, function (err, db) { - if (err) { - if (callback) { - self.taskqueue.fail(err); - callback(err); - } - return; - } - function destructionListner(event) { - if (event === 'destroyed') { - self.emit('destroyed'); - PouchDBVersion200.removeListener(opts.name, destructionListner); - } - } - PouchDBVersion200.on(opts.name, destructionListner); - self.emit('created', self); - PouchDBVersion200.emit('created', opts.originalName); - self.taskqueue.ready(self); - callback(null, self); - - }); - if (opts.skipSetup) { - self.taskqueue.ready(self); - } - - if (utils.isCordova()) { - //to inform websql adapter that we can use api - cordova.fireWindowEvent(opts.name + "_pouch", {}); - } - }); - promise.then(function (resp) { - oldCB(null, resp); - }, oldCB); - self.then = promise.then.bind(promise); - //prevent deoptimizing - (function () { - try { - self.catch = promise.catch.bind(promise); - } catch (e) {} - }()); -} - -module.exports = PouchDBVersion200; - -}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./adapter":1,"./taskqueue":17,"./utils":18,"bluebird":24}],6:[function(_dereq_,module,exports){ -(function (process){ -"use strict"; - -var request = _dereq_('request'); -var extend = _dereq_('./extend.js'); -var createBlob = _dereq_('./blob.js'); -var errors = _dereq_('./errors'); -var uuid = _dereq_('../deps/uuid'); - -function ajax(options, callback) { - - if (typeof options === "function") { - callback = options; - options = {}; - } - options = extend(true, {}, options); - function call(fun) { - /* jshint validthis: true */ - var args = Array.prototype.slice.call(arguments, 1); - if (typeof fun === typeof Function) { - fun.apply(this, args); - } - } - - var defaultOptions = { - method : "GET", - headers: {}, - json: true, - processData: true, - timeout: 10000, - cache: false - }; - - options = extend(true, defaultOptions, options); - - // cache-buster, specifically designed to work around IE's aggressive caching - // see http://www.dashbay.com/2011/05/internet-explorer-caches-ajax/ - if (options.method === 'GET' && !options.cache) { - var hasArgs = options.url.indexOf('?') !== -1; - options.url += (hasArgs ? '&' : '?') + '_nonce=' + uuid(16); - } - - function onSuccess(obj, resp, cb) { - if (!options.binary && !options.json && options.processData && - typeof obj !== 'string') { - obj = JSON.stringify(obj); - } else if (!options.binary && options.json && typeof obj === 'string') { - try { - obj = JSON.parse(obj); - } catch (e) { - // Probably a malformed JSON from server - call(cb, e); - return; - } - } - if (Array.isArray(obj)) { - obj = obj.map(function (v) { - var obj; - if (v.ok) { - return v; - } else if (v.error && v.error === 'conflict') { - obj = errors.REV_CONFLICT; - obj.id = v.id; - return obj; - } else if (v.error && v.error === 'forbidden') { - obj = errors.FORBIDDEN; - obj.id = v.id; - obj.reason = v.reason; - return obj; - } else if (v.missing) { - obj = errors.MISSING_DOC; - obj.missing = v.missing; - return obj; - } else { - return v; - } - }); - } - call(cb, null, obj, resp); - } - - function onError(err, cb) { - var errParsed, errObj, errType, key; - try { - errParsed = JSON.parse(err.responseText); - //would prefer not to have a try/catch clause - for (key in errors) { - if (errors.hasOwnProperty(key) && errors[key].name === errParsed.error) { - errType = errors[key]; - break; - } - } - if (!errType) { - errType = errors.UNKNOWN_ERROR; - if (err.status) { - errType.status = err.status; - } - if (err.statusText) { - err.name = err.statusText; - } - } - errObj = errors.error(errType, errParsed.reason); - } catch (e) { - for (var key in errors) { - if (errors.hasOwnProperty(key) && errors[key].status === err.status) { - errType = errors[key]; - break; - } - } - if (!errType) { - errType = errors.UNKNOWN_ERROR; - if (err.status) { - errType.status = err.status; - } - if (err.statusText) { - err.name = err.statusText; - } - } - errObj = errors.error(errType); - } - call(cb, errObj); - } - - if (process.browser) { - var timer, timedout = false; - var xhr; - if (options.xhr) { - xhr = new options.xhr(); - } else { - xhr = new XMLHttpRequest(); - } - xhr.open(options.method, options.url); - xhr.withCredentials = true; - - if (options.json) { - options.headers.Accept = 'application/json'; - options.headers['Content-Type'] = options.headers['Content-Type'] || - 'application/json'; - if (options.body && options.processData && typeof options.body !== "string") { - options.body = JSON.stringify(options.body); - } - } - - if (options.binary) { - xhr.responseType = 'arraybuffer'; - } - - var createCookie = function (name, value, days) { - var expires = ""; - if (days) { - var date = new Date(); - date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); - expires = "; expires=" + date.toGMTString(); - } - document.cookie = name + "=" + value + expires + "; path=/"; - }; - - for (var key in options.headers) { - if (key === 'Cookie') { - var cookie = options.headers[key].split('='); - createCookie(cookie[0], cookie[1], 10); - } else { - xhr.setRequestHeader(key, options.headers[key]); - } - } - - if (!("body" in options)) { - options.body = null; - } - - var abortReq = function () { - timedout = true; - xhr.abort(); - call(onError, xhr, callback); - }; - - xhr.onreadystatechange = function () { - if (xhr.readyState !== 4 || timedout) { - return; - } - clearTimeout(timer); - if (xhr.status >= 200 && xhr.status < 300) { - var data; - if (options.binary) { - data = createBlob([xhr.response || ''], { - type: xhr.getResponseHeader('Content-Type') - }); - } else { - data = xhr.responseText; - } - call(onSuccess, data, xhr, callback); - } else { - call(onError, xhr, callback); - } - }; - - if (options.timeout > 0) { - timer = setTimeout(abortReq, options.timeout); - xhr.onprogress = function () { - clearTimeout(timer); - timer = setTimeout(abortReq, options.timeout); - }; - if (xhr.upload) { // does not exist in ie9 - xhr.upload.onprogress = xhr.onprogress; - } - } - xhr.send(options.body); - return {abort: abortReq}; - - } else { - - if (options.json) { - if (!options.binary) { - options.headers.Accept = 'application/json'; - } - options.headers['Content-Type'] = options.headers['Content-Type'] || - 'application/json'; - } - - if (options.binary) { - options.encoding = null; - options.json = false; - } - - if (!options.processData) { - options.json = false; - } - - return request(options, function (err, response, body) { - if (err) { - err.status = response ? response.statusCode : 400; - return call(onError, err, callback); - } - var error; - var content_type = response.headers['content-type']; - var data = (body || ''); - - // CouchDB doesn't always return the right content-type for JSON data, so - // we check for ^{ and }$ (ignoring leading/trailing whitespace) - if (!options.binary && (options.json || !options.processData) && - typeof data !== 'object' && - (/json/.test(content_type) || - (/^[\s]*\{/.test(data) && /\}[\s]*$/.test(data)))) { - data = JSON.parse(data); - } - - if (response.statusCode >= 200 && response.statusCode < 300) { - call(onSuccess, data, response, callback); - } - else { - if (options.binary) { - data = JSON.parse(data.toString()); - } - if (data.reason === 'missing') { - error = errors.MISSING_DOC; - } else if (data.reason === 'no_db_file') { - error = errors.error(errors.DB_MISSING, data.reason); - } else if (data.error === 'conflict') { - error = errors.REV_CONFLICT; - } else { - error = errors.error(errors.UNKNOWN_ERROR, data.reason, data.error); - } - error.status = response.statusCode; - call(callback, error); - } - }); - } -} - -module.exports = ajax; - -}).call(this,_dereq_("/Users/daleharvey/src/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js")) -},{"../deps/uuid":12,"./blob.js":7,"./errors":8,"./extend.js":10,"/Users/daleharvey/src/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":22,"request":20}],7:[function(_dereq_,module,exports){ -(function (global){ -"use strict"; - -//Abstracts constructing a Blob object, so it also works in older -//browsers that don't support the native Blob constructor. (i.e. -//old QtWebKit versions, at least). -function createBlob(parts, properties) { - parts = parts || []; - properties = properties || {}; - try { - return new Blob(parts, properties); - } catch (e) { - if (e.name !== "TypeError") { - throw e; - } - var BlobBuilder = global.BlobBuilder || global.MSBlobBuilder || global.MozBlobBuilder || global.WebKitBlobBuilder; - var builder = new BlobBuilder(); - for (var i = 0; i < parts.length; i += 1) { - builder.append(parts[i]); - } - return builder.getBlob(properties.type); - } -} - -module.exports = createBlob; - - -}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],8:[function(_dereq_,module,exports){ -"use strict"; - -function PouchError(opts) { - this.status = opts.status; - this.name = opts.error; - this.message = opts.reason; - this.error = true; -} - -PouchError.prototype__proto__ = Error.prototype; - -PouchError.prototype.toString = function () { - return JSON.stringify({ - status: this.status, - name: this.name, - message: this.message - }); -}; - -exports.UNAUTHORIZED = new PouchError({ - status: 401, - error: 'unauthorized', - reason: "Name or password is incorrect." -}); -exports.MISSING_BULK_DOCS = new PouchError({ - status: 400, - error: 'bad_request', - reason: "Missing JSON list of 'docs'" -}); -exports.MISSING_DOC = new PouchError({ - status: 404, - error: 'not_found', - reason: 'missing' -}); -exports.REV_CONFLICT = new PouchError({ - status: 409, - error: 'conflict', - reason: 'Document update conflict' -}); -exports.INVALID_ID = new PouchError({ - status: 400, - error: 'invalid_id', - reason: '_id field must contain a string' -}); -exports.MISSING_ID = new PouchError({ - status: 412, - error: 'missing_id', - reason: '_id is required for puts' -}); -exports.RESERVED_ID = new PouchError({ - status: 400, - error: 'bad_request', - reason: 'Only reserved document ids may start with underscore.' -}); -exports.NOT_OPEN = new PouchError({ - status: 412, - error: 'precondition_failed', - reason: 'Database not open so cannot close' -}); -exports.UNKNOWN_ERROR = new PouchError({ - status: 500, - error: 'unknown_error', - reason: 'Database encountered an unknown error' -}); -exports.BAD_ARG = new PouchError({ - status: 500, - error: 'badarg', - reason: 'Some query argument is invalid' -}); -exports.INVALID_REQUEST = new PouchError({ - status: 400, - error: 'invalid_request', - reason: 'Request was invalid' -}); -exports.QUERY_PARSE_ERROR = new PouchError({ - status: 400, - error: 'query_parse_error', - reason: 'Some query parameter is invalid' -}); -exports.DOC_VALIDATION = new PouchError({ - status: 500, - error: 'doc_validation', - reason: 'Bad special document member' -}); -exports.BAD_REQUEST = new PouchError({ - status: 400, - error: 'bad_request', - reason: 'Something wrong with the request' -}); -exports.NOT_AN_OBJECT = new PouchError({ - status: 400, - error: 'bad_request', - reason: 'Document must be a JSON object' -}); -exports.DB_MISSING = new PouchError({ - status: 404, - error: 'not_found', - reason: 'Database not found' -}); -exports.IDB_ERROR = new PouchError({ - status: 500, - error: 'indexed_db_went_bad', - reason: 'unknown' -}); -exports.WSQ_ERROR = new PouchError({ - status: 500, - error: 'web_sql_went_bad', - reason: 'unknown' -}); -exports.LDB_ERROR = new PouchError({ - status: 500, - error: 'levelDB_went_went_bad', - reason: 'unknown' -}); -exports.FORBIDDEN = new PouchError({ - status: 403, - error: 'forbidden', - reason: 'Forbidden by design doc validate_doc_update function' -}); -exports.error = function (error, reason, name) { - function CustomPouchError(msg) { - this.message = reason; - if (name) { - this.name = name; - } - } - CustomPouchError.prototype = error; - return new CustomPouchError(reason); -}; - -},{}],9:[function(_dereq_,module,exports){ -// some small shims for es5 just for the features we commonly use -// some of this is copied from https://github.com/kriskowal/es5-shim/blob/master/es5-shim.js -'use strict'; - -if (!Object.keys) { - Object.keys = function keys(object) { - - if ((typeof object !== 'object' && typeof object !== 'function') || object === null) { - throw new TypeError('Object.keys called on a non-object'); - } - - var mykeys = []; - for (var name in object) { - if (Object.prototype.hasOwnProperty.call(object, name)) { - mykeys.push(name); - } - } - return mykeys; - }; -} - -if (!Array.isArray) { - Array.isArray = function isArray(obj) { - return Object.prototype.toString.call(obj) === '[object Array]'; - }; -} - -if (!('forEach' in Array.prototype)) { - Array.prototype.forEach = function (action, that /*opt*/) { - for (var i = 0, n = this.length; i < n; i++) { - if (i in this) { - action.call(that, this[i], i, this); - } - } - }; -} - -if (!('map' in Array.prototype)) { - Array.prototype.map = function (mapper, that /*opt*/) { - var other = new Array(this.length); - for (var i = 0, n = this.length; i < n; i++) { - if (i in this) { - other[i] = mapper.call(that, this[i], i, this); - } - } - return other; - }; -} - -},{}],10:[function(_dereq_,module,exports){ -"use strict"; - -// Extends method -// (taken from http://code.jquery.com/jquery-1.9.0.js) -// Populate the class2type map -var class2type = {}; - -var types = ["Boolean", "Number", "String", "Function", "Array", "Date", "RegExp", "Object", "Error"]; -for (var i = 0; i < types.length; i++) { - var typename = types[i]; - class2type["[object " + typename + "]"] = typename.toLowerCase(); -} - -var core_toString = class2type.toString; -var core_hasOwn = class2type.hasOwnProperty; - -function type(obj) { - if (obj === null) { - return String(obj); - } - return typeof obj === "object" || typeof obj === "function" ? - class2type[core_toString.call(obj)] || "object" : - typeof obj; -} - -function isWindow(obj) { - return obj !== null && obj === obj.window; -} - -function isPlainObject(obj) { - // Must be an Object. - // Because of IE, we also have to check the presence of the constructor property. - // Make sure that DOM nodes and window objects don't pass through, as well - if (!obj || type(obj) !== "object" || obj.nodeType || isWindow(obj)) { - return false; - } - - try { - // Not own constructor property must be Object - if (obj.constructor && - !core_hasOwn.call(obj, "constructor") && - !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) { - return false; - } - } catch ( e ) { - // IE8,9 Will throw exceptions on certain host objects #9897 - return false; - } - - // Own properties are enumerated firstly, so to speed up, - // if last one is own, then all properties are own. - var key; - for (key in obj) {} - - return key === undefined || core_hasOwn.call(obj, key); -} - - -function isFunction(obj) { - return type(obj) === "function"; -} - -var isArray = Array.isArray || function (obj) { - return type(obj) === "array"; -}; - -function extend() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[0] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if (typeof target === "boolean") { - deep = target; - target = arguments[1] || {}; - // skip the boolean and the target - i = 2; - } - - // Handle case when target is a string or something (possible in deep copy) - if (typeof target !== "object" && !isFunction(target)) { - target = {}; - } - - // extend jQuery itself if only one argument is passed - if (length === i) { - /* jshint validthis: true */ - target = this; - --i; - } - - for (; i < length; i++) { - // Only deal with non-null/undefined values - if ((options = arguments[i]) != null) { - // Extend the base object - for (name in options) { - //if (options.hasOwnProperty(name)) { - if (!(name in Object.prototype)) { - - src = target[name]; - copy = options[name]; - - // Prevent never-ending loop - if (target === copy) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if (deep && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) { - if (copyIsArray) { - copyIsArray = false; - clone = src && isArray(src) ? src : []; - - } else { - clone = src && isPlainObject(src) ? src : {}; - } - - // Never move original objects, clone them - target[name] = extend(deep, clone, copy); - - // Don't bring in undefined values - } else if (copy !== undefined) { - if (!(isArray(options) && isFunction(copy))) { - target[name] = copy; - } - } - } - } - } - } - - // Return the modified object - return target; -} - - -module.exports = extend; - - -},{}],11:[function(_dereq_,module,exports){ -(function (process){ -"use strict"; - -/** -* -* MD5 (Message-Digest Algorithm) -* -* For original source see http://www.webtoolkit.info/ -* Download: 15.02.2009 from http://www.webtoolkit.info/javascript-md5.html -* -* Licensed under CC-BY 2.0 License -* (http://creativecommons.org/licenses/by/2.0/uk/) -* -**/ -var crypto = _dereq_('crypto'); - -exports.MD5 = function (string) { - if (!process.browser) { - return crypto.createHash('md5').update(string).digest('hex'); - } - function rotateLeft(lValue, iShiftBits) { - return (lValue<<iShiftBits) | (lValue>>>(32 - iShiftBits)); - } - - function addUnsigned(lX, lY) { - var lX4, lY4, lX8, lY8, lResult; - lX8 = (lX & 0x80000000); - lY8 = (lY & 0x80000000); - lX4 = (lX & 0x40000000); - lY4 = (lY & 0x40000000); - lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF); - if (lX4 & lY4) { - return (lResult ^ 0x80000000 ^ lX8 ^ lY8); - } - if (lX4 | lY4) { - if (lResult & 0x40000000) { - return (lResult ^ 0xC0000000 ^ lX8 ^ lY8); - } else { - return (lResult ^ 0x40000000 ^ lX8 ^ lY8); - } - } else { - return (lResult ^ lX8 ^ lY8); - } - } - - function f(x, y, z) { return (x & y) | ((~x) & z); } - function g(x, y, z) { return (x & z) | (y & (~z)); } - function h(x, y, z) { return (x ^ y ^ z); } - function i(x, y, z) { return (y ^ (x | (~z))); } - - function ff(a, b, c, d, x, s, ac) { - a = addUnsigned(a, addUnsigned(addUnsigned(f(b, c, d), x), ac)); - return addUnsigned(rotateLeft(a, s), b); - } - - function gg(a, b, c, d, x, s, ac) { - a = addUnsigned(a, addUnsigned(addUnsigned(g(b, c, d), x), ac)); - return addUnsigned(rotateLeft(a, s), b); - } - - function hh(a, b, c, d, x, s, ac) { - a = addUnsigned(a, addUnsigned(addUnsigned(h(b, c, d), x), ac)); - return addUnsigned(rotateLeft(a, s), b); - } - - function ii(a, b, c, d, x, s, ac) { - a = addUnsigned(a, addUnsigned(addUnsigned(i(b, c, d), x), ac)); - return addUnsigned(rotateLeft(a, s), b); - } - - function convertToWordArray(string) { - var lWordCount; - var lMessageLength = string.length; - var lNumberOfWords_temp1 = lMessageLength + 8; - var lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64; - var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16; - var lWordArray = new Array(lNumberOfWords - 1); - var lBytePosition = 0; - var lByteCount = 0; - while (lByteCount < lMessageLength) { - lWordCount = (lByteCount - (lByteCount % 4)) / 4; - lBytePosition = (lByteCount % 4) * 8; - lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount)<<lBytePosition)); - lByteCount++; - } - lWordCount = (lByteCount - (lByteCount % 4)) / 4; - lBytePosition = (lByteCount % 4) * 8; - lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80<<lBytePosition); - lWordArray[lNumberOfWords - 2] = lMessageLength<<3; - lWordArray[lNumberOfWords - 1] = lMessageLength>>>29; - return lWordArray; - } - - function wordToHex(lValue) { - var wordToHexValue = "", wordToHexValue_temp = "", lByte, lCount; - for (lCount = 0;lCount <= 3;lCount++) { - lByte = (lValue>>>(lCount * 8)) & 255; - wordToHexValue_temp = "0" + lByte.toString(16); - wordToHexValue = wordToHexValue + wordToHexValue_temp.substr(wordToHexValue_temp.length - 2, 2); - } - return wordToHexValue; - } - - //** function Utf8Encode(string) removed. Aready defined in pidcrypt_utils.js - - var x = []; - var k, AA, BB, CC, DD, a, b, c, d; - var S11 = 7, S12 = 12, S13 = 17, S14 = 22; - var S21 = 5, S22 = 9, S23 = 14, S24 = 20; - var S31 = 4, S32 = 11, S33 = 16, S34 = 23; - var S41 = 6, S42 = 10, S43 = 15, S44 = 21; - - // string = Utf8Encode(string); #function call removed - - x = convertToWordArray(string); - - a = 0x67452301; - b = 0xEFCDAB89; - c = 0x98BADCFE; - d = 0x10325476; - - for (k = 0;k < x.length;k += 16) { - AA = a; - BB = b; - CC = c; - DD = d; - a = ff(a, b, c, d, x[k + 0], S11, 0xD76AA478); - d = ff(d, a, b, c, x[k + 1], S12, 0xE8C7B756); - c = ff(c, d, a, b, x[k + 2], S13, 0x242070DB); - b = ff(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE); - a = ff(a, b, c, d, x[k + 4], S11, 0xF57C0FAF); - d = ff(d, a, b, c, x[k + 5], S12, 0x4787C62A); - c = ff(c, d, a, b, x[k + 6], S13, 0xA8304613); - b = ff(b, c, d, a, x[k + 7], S14, 0xFD469501); - a = ff(a, b, c, d, x[k + 8], S11, 0x698098D8); - d = ff(d, a, b, c, x[k + 9], S12, 0x8B44F7AF); - c = ff(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1); - b = ff(b, c, d, a, x[k + 11], S14, 0x895CD7BE); - a = ff(a, b, c, d, x[k + 12], S11, 0x6B901122); - d = ff(d, a, b, c, x[k + 13], S12, 0xFD987193); - c = ff(c, d, a, b, x[k + 14], S13, 0xA679438E); - b = ff(b, c, d, a, x[k + 15], S14, 0x49B40821); - a = gg(a, b, c, d, x[k + 1], S21, 0xF61E2562); - d = gg(d, a, b, c, x[k + 6], S22, 0xC040B340); - c = gg(c, d, a, b, x[k + 11], S23, 0x265E5A51); - b = gg(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA); - a = gg(a, b, c, d, x[k + 5], S21, 0xD62F105D); - d = gg(d, a, b, c, x[k + 10], S22, 0x2441453); - c = gg(c, d, a, b, x[k + 15], S23, 0xD8A1E681); - b = gg(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8); - a = gg(a, b, c, d, x[k + 9], S21, 0x21E1CDE6); - d = gg(d, a, b, c, x[k + 14], S22, 0xC33707D6); - c = gg(c, d, a, b, x[k + 3], S23, 0xF4D50D87); - b = gg(b, c, d, a, x[k + 8], S24, 0x455A14ED); - a = gg(a, b, c, d, x[k + 13], S21, 0xA9E3E905); - d = gg(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8); - c = gg(c, d, a, b, x[k + 7], S23, 0x676F02D9); - b = gg(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A); - a = hh(a, b, c, d, x[k + 5], S31, 0xFFFA3942); - d = hh(d, a, b, c, x[k + 8], S32, 0x8771F681); - c = hh(c, d, a, b, x[k + 11], S33, 0x6D9D6122); - b = hh(b, c, d, a, x[k + 14], S34, 0xFDE5380C); - a = hh(a, b, c, d, x[k + 1], S31, 0xA4BEEA44); - d = hh(d, a, b, c, x[k + 4], S32, 0x4BDECFA9); - c = hh(c, d, a, b, x[k + 7], S33, 0xF6BB4B60); - b = hh(b, c, d, a, x[k + 10], S34, 0xBEBFBC70); - a = hh(a, b, c, d, x[k + 13], S31, 0x289B7EC6); - d = hh(d, a, b, c, x[k + 0], S32, 0xEAA127FA); - c = hh(c, d, a, b, x[k + 3], S33, 0xD4EF3085); - b = hh(b, c, d, a, x[k + 6], S34, 0x4881D05); - a = hh(a, b, c, d, x[k + 9], S31, 0xD9D4D039); - d = hh(d, a, b, c, x[k + 12], S32, 0xE6DB99E5); - c = hh(c, d, a, b, x[k + 15], S33, 0x1FA27CF8); - b = hh(b, c, d, a, x[k + 2], S34, 0xC4AC5665); - a = ii(a, b, c, d, x[k + 0], S41, 0xF4292244); - d = ii(d, a, b, c, x[k + 7], S42, 0x432AFF97); - c = ii(c, d, a, b, x[k + 14], S43, 0xAB9423A7); - b = ii(b, c, d, a, x[k + 5], S44, 0xFC93A039); - a = ii(a, b, c, d, x[k + 12], S41, 0x655B59C3); - d = ii(d, a, b, c, x[k + 3], S42, 0x8F0CCC92); - c = ii(c, d, a, b, x[k + 10], S43, 0xFFEFF47D); - b = ii(b, c, d, a, x[k + 1], S44, 0x85845DD1); - a = ii(a, b, c, d, x[k + 8], S41, 0x6FA87E4F); - d = ii(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0); - c = ii(c, d, a, b, x[k + 6], S43, 0xA3014314); - b = ii(b, c, d, a, x[k + 13], S44, 0x4E0811A1); - a = ii(a, b, c, d, x[k + 4], S41, 0xF7537E82); - d = ii(d, a, b, c, x[k + 11], S42, 0xBD3AF235); - c = ii(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB); - b = ii(b, c, d, a, x[k + 9], S44, 0xEB86D391); - a = addUnsigned(a, AA); - b = addUnsigned(b, BB); - c = addUnsigned(c, CC); - d = addUnsigned(d, DD); - } - var temp = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d); - return temp.toLowerCase(); -}; -}).call(this,_dereq_("/Users/daleharvey/src/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js")) -},{"/Users/daleharvey/src/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":22,"crypto":20}],12:[function(_dereq_,module,exports){ -"use strict"; - -// BEGIN Math.uuid.js - -/*! -Math.uuid.js (v1.4) -http://www.broofa.com -mailto:robert@broofa.com - -Copyright (c) 2010 Robert Kieffer -Dual licensed under the MIT and GPL licenses. -*/ - -/* - * Generate a random uuid. - * - * USAGE: Math.uuid(length, radix) - * length - the desired number of characters - * radix - the number of allowable values for each character. - * - * EXAMPLES: - * // No arguments - returns RFC4122, version 4 ID - * >>> Math.uuid() - * "92329D39-6F5C-4520-ABFC-AAB64544E172" - * - * // One argument - returns ID of the specified length - * >>> Math.uuid(15) // 15 character ID (default base=62) - * "VcydxgltxrVZSTV" - * - * // Two arguments - returns ID of the specified length, and radix. (Radix must be <= 62) - * >>> Math.uuid(8, 2) // 8 character ID (base=2) - * "01001010" - * >>> Math.uuid(8, 10) // 8 character ID (base=10) - * "47473046" - * >>> Math.uuid(8, 16) // 8 character ID (base=16) - * "098F4D35" - */ - - -function uuid(len, radix) { - var chars = uuid.CHARS; - var uuidInner = []; - var i; - - radix = radix || chars.length; - - if (len) { - // Compact form - for (i = 0; i < len; i++) { - uuidInner[i] = chars[0 | Math.random() * radix]; - } - } else { - // rfc4122, version 4 form - var r; - - // rfc4122 requires these characters - uuidInner[8] = uuidInner[13] = uuidInner[18] = uuidInner[23] = '-'; - uuidInner[14] = '4'; - - // Fill in random data. At i==19 set the high bits of clock sequence as - // per rfc4122, sec. 4.1.5 - for (i = 0; i < 36; i++) { - if (!uuidInner[i]) { - r = 0 | Math.random() * 16; - uuidInner[i] = chars[(i === 19) ? (r & 0x3) | 0x8 : r]; - } - } - } - - return uuidInner.join(''); -} - -uuid.CHARS = ( - '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' + - 'abcdefghijklmnopqrstuvwxyz' -).split(''); - -module.exports = uuid; - - -},{}],13:[function(_dereq_,module,exports){ -(function (process){ -"use strict"; - -_dereq_('./deps/es5_shims'); - -var PouchDBVersion200 = _dereq_('./setup'); - -module.exports = PouchDBVersion200; - -PouchDBVersion200.ajax = _dereq_('./deps/ajax'); -PouchDBVersion200.extend = _dereq_('./deps/extend'); -PouchDBVersion200.utils = _dereq_('./utils'); -PouchDBVersion200.Errors = _dereq_('./deps/errors'); -var replicate = _dereq_('./replicate'); -PouchDBVersion200.replicate = replicate.replicate; -PouchDBVersion200.sync = replicate.sync; -PouchDBVersion200.version = _dereq_('./version'); -var httpAdapter = _dereq_('./adapters/http'); -PouchDBVersion200.adapter('http', httpAdapter); -PouchDBVersion200.adapter('https', httpAdapter); - -PouchDBVersion200.adapter('idb', _dereq_('./adapters/idb')); -PouchDBVersion200.adapter('websql', _dereq_('./adapters/websql')); -PouchDBVersion200.plugin(_dereq_('pouchdb-mapreduce')); - -if (!process.browser) { - var ldbAdapter = _dereq_('./adapters/leveldb'); - PouchDBVersion200.adapter('ldb', ldbAdapter); - PouchDBVersion200.adapter('leveldb', ldbAdapter); -} - -}).call(this,_dereq_("/Users/daleharvey/src/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js")) -},{"./adapters/http":2,"./adapters/idb":3,"./adapters/leveldb":20,"./adapters/websql":4,"./deps/ajax":6,"./deps/errors":8,"./deps/es5_shims":9,"./deps/extend":10,"./replicate":15,"./setup":16,"./utils":18,"./version":19,"/Users/daleharvey/src/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":22,"pouchdb-mapreduce":35}],14:[function(_dereq_,module,exports){ -'use strict'; - -var extend = _dereq_('./deps/extend'); - - -// for a better overview of what this is doing, read: -// https://github.com/apache/couchdb/blob/master/src/couchdb/couch_key_tree.erl -// -// But for a quick intro, CouchDB uses a revision tree to store a documents -// history, A -> B -> C, when a document has conflicts, that is a branch in the -// tree, A -> (B1 | B2 -> C), We store these as a nested array in the format -// -// KeyTree = [Path ... ] -// Path = {pos: position_from_root, ids: Tree} -// Tree = [Key, Opts, [Tree, ...]], in particular single node: [Key, []] - -// Turn a path as a flat array into a tree with a single branch -function pathToTree(path) { - var doc = path.shift(); - var root = [doc.id, doc.opts, []]; - var leaf = root; - var nleaf; - - while (path.length) { - doc = path.shift(); - nleaf = [doc.id, doc.opts, []]; - leaf[2].push(nleaf); - leaf = nleaf; - } - return root; -} - -// Merge two trees together -// The roots of tree1 and tree2 must be the same revision -function mergeTree(in_tree1, in_tree2) { - var queue = [{tree1: in_tree1, tree2: in_tree2}]; - var conflicts = false; - while (queue.length > 0) { - var item = queue.pop(); - var tree1 = item.tree1; - var tree2 = item.tree2; - - if (tree1[1].status || tree2[1].status) { - tree1[1].status = (tree1[1].status === 'available' || - tree2[1].status === 'available') ? 'available' : 'missing'; - } - - for (var i = 0; i < tree2[2].length; i++) { - if (!tree1[2][0]) { - conflicts = 'new_leaf'; - tree1[2][0] = tree2[2][i]; - continue; - } - - var merged = false; - for (var j = 0; j < tree1[2].length; j++) { - if (tree1[2][j][0] === tree2[2][i][0]) { - queue.push({tree1: tree1[2][j], tree2: tree2[2][i]}); - merged = true; - } - } - if (!merged) { - conflicts = 'new_branch'; - tree1[2].push(tree2[2][i]); - tree1[2].sort(); - } - } - } - return {conflicts: conflicts, tree: in_tree1}; -} - -function doMerge(tree, path, dontExpand) { - var restree = []; - var conflicts = false; - var merged = false; - var res; - - if (!tree.length) { - return {tree: [path], conflicts: 'new_leaf'}; - } - - tree.forEach(function (branch) { - if (branch.pos === path.pos && branch.ids[0] === path.ids[0]) { - // Paths start at the same position and have the same root, so they need - // merged - res = mergeTree(branch.ids, path.ids); - restree.push({pos: branch.pos, ids: res.tree}); - conflicts = conflicts || res.conflicts; - merged = true; - } else if (dontExpand !== true) { - // The paths start at a different position, take the earliest path and - // traverse up until it as at the same point from root as the path we want to - // merge. If the keys match we return the longer path with the other merged - // After stemming we dont want to expand the trees - - var t1 = branch.pos < path.pos ? branch : path; - var t2 = branch.pos < path.pos ? path : branch; - var diff = t2.pos - t1.pos; - - var candidateParents = []; - - var trees = []; - trees.push({ids: t1.ids, diff: diff, parent: null, parentIdx: null}); - while (trees.length > 0) { - var item = trees.pop(); - if (item.diff === 0) { - if (item.ids[0] === t2.ids[0]) { - candidateParents.push(item); - } - continue; - } - if (!item.ids) { - continue; - } - /*jshint loopfunc:true */ - item.ids[2].forEach(function (el, idx) { - trees.push({ids: el, diff: item.diff - 1, parent: item.ids, parentIdx: idx}); - }); - } - - var el = candidateParents[0]; - - if (!el) { - restree.push(branch); - } else { - res = mergeTree(el.ids, t2.ids); - el.parent[2][el.parentIdx] = res.tree; - restree.push({pos: t1.pos, ids: t1.ids}); - conflicts = conflicts || res.conflicts; - merged = true; - } - } else { - restree.push(branch); - } - }); - - // We didnt find - if (!merged) { - restree.push(path); - } - - restree.sort(function (a, b) { - return a.pos - b.pos; - }); - - return { - tree: restree, - conflicts: conflicts || 'internal_node' - }; -} - -// To ensure we dont grow the revision tree infinitely, we stem old revisions -function stem(tree, depth) { - // First we break out the tree into a complete list of root to leaf paths, - // we cut off the start of the path and generate a new set of flat trees - var stemmedPaths = PouchMerge.rootToLeaf(tree).map(function (path) { - var stemmed = path.ids.slice(-depth); - return { - pos: path.pos + (path.ids.length - stemmed.length), - ids: pathToTree(stemmed) - }; - }); - // Then we remerge all those flat trees together, ensuring that we dont - // connect trees that would go beyond the depth limit - return stemmedPaths.reduce(function (prev, current, i, arr) { - return doMerge(prev, current, true).tree; - }, [stemmedPaths.shift()]); -} - -var PouchMerge = {}; - -PouchMerge.merge = function (tree, path, depth) { - // Ugh, nicer way to not modify arguments in place? - tree = extend(true, [], tree); - path = extend(true, {}, path); - var newTree = doMerge(tree, path); - return { - tree: stem(newTree.tree, depth), - conflicts: newTree.conflicts - }; -}; - -// We fetch all leafs of the revision tree, and sort them based on tree length -// and whether they were deleted, undeleted documents with the longest revision -// tree (most edits) win -// The final sort algorithm is slightly documented in a sidebar here: -// http://guide.couchdb.org/draft/conflicts.html -PouchMerge.winningRev = function (metadata) { - var leafs = []; - PouchMerge.traverseRevTree(metadata.rev_tree, - function (isLeaf, pos, id, something, opts) { - if (isLeaf) { - leafs.push({pos: pos, id: id, deleted: !!opts.deleted}); - } - }); - leafs.sort(function (a, b) { - if (a.deleted !== b.deleted) { - return a.deleted > b.deleted ? 1 : -1; - } - if (a.pos !== b.pos) { - return b.pos - a.pos; - } - return a.id < b.id ? 1 : -1; - }); - - return leafs[0].pos + '-' + leafs[0].id; -}; - -// Pretty much all below can be combined into a higher order function to -// traverse revisions -// The return value from the callback will be passed as context to all -// children of that node -PouchMerge.traverseRevTree = function (revs, callback) { - var toVisit = []; - - revs.forEach(function (tree) { - toVisit.push({pos: tree.pos, ids: tree.ids}); - }); - while (toVisit.length > 0) { - var node = toVisit.pop(); - var pos = node.pos; - var tree = node.ids; - var newCtx = callback(tree[2].length === 0, pos, tree[0], node.ctx, tree[1]); - /*jshint loopfunc: true */ - tree[2].forEach(function (branch) { - toVisit.push({pos: pos + 1, ids: branch, ctx: newCtx}); - }); - } -}; - -PouchMerge.collectLeaves = function (revs) { - var leaves = []; - PouchMerge.traverseRevTree(revs, function (isLeaf, pos, id, acc, opts) { - if (isLeaf) { - leaves.unshift({rev: pos + "-" + id, pos: pos, opts: opts}); - } - }); - leaves.sort(function (a, b) { - return b.pos - a.pos; - }); - leaves.map(function (leaf) { delete leaf.pos; }); - return leaves; -}; - -// returns revs of all conflicts that is leaves such that -// 1. are not deleted and -// 2. are different than winning revision -PouchMerge.collectConflicts = function (metadata) { - var win = PouchMerge.winningRev(metadata); - var leaves = PouchMerge.collectLeaves(metadata.rev_tree); - var conflicts = []; - leaves.forEach(function (leaf) { - if (leaf.rev !== win && !leaf.opts.deleted) { - conflicts.push(leaf.rev); - } - }); - return conflicts; -}; - -PouchMerge.rootToLeaf = function (tree) { - var paths = []; - PouchMerge.traverseRevTree(tree, function (isLeaf, pos, id, history, opts) { - history = history ? history.slice(0) : []; - history.push({id: id, opts: opts}); - if (isLeaf) { - var rootPos = pos + 1 - history.length; - paths.unshift({pos: rootPos, ids: history}); - } - return history; - }); - return paths; -}; - - -module.exports = PouchMerge; - -},{"./deps/extend":10}],15:[function(_dereq_,module,exports){ -'use strict'; - -var PouchUtils = _dereq_('./utils'); -var Pouch = _dereq_('./index'); - -// We create a basic promise so the caller can cancel the replication possibly -// before we have actually started listening to changes etc -function Promise() { - var that = this; - this.cancelled = false; - this.cancel = function () { - that.cancelled = true; - }; -} - - -// A batch of changes to be processed as a unit -function Batch() { - this.seq = 0; - this.state = 'start'; - this.changes = []; - this.docs = []; -} - - -// TODO: check CouchDB's replication id generation -// Generate a unique id particular to this replication -function genReplicationId(src, target, opts, callback) { - var filterFun = opts.filter ? opts.filter.toString() : ''; - src.id(function (err, src_id) { - target.id(function (err, target_id) { - var queryData = src_id + target_id + filterFun + - JSON.stringify(opts.query_params); - callback('_local/' + PouchUtils.Crypto.MD5(queryData)); - }); - }); -} - - -// A checkpoint lets us restart replications from when they were last cancelled -function fetchCheckpoint(src, target, id, callback) { - target.get(id, function (err, targetDoc) { - if (err && err.status === 404) { - callback(null, 0); - } else if (err) { - callback(err); - } else { - src.get(id, function (err, sourceDoc) { - if (err && err.status === 404 || - (!err && (targetDoc.last_seq !== sourceDoc.last_seq))) { - callback(null, 0); - } else if (err) { - callback(err); - } else { - callback(null, sourceDoc.last_seq); - } - }); - } - }); -} - - -function writeCheckpoint(src, target, id, checkpoint, callback) { - function updateCheckpoint(db, callback) { - db.get(id, function (err, doc) { - if (err && err.status === 404) { - doc = {_id: id}; - } else if (err) { - return callback(err); - } - doc.last_seq = checkpoint; - db.put(doc, callback); - }); - } - updateCheckpoint(target, function (err, doc) { - updateCheckpoint(src, function (err, doc) { - callback(); - }); - }); -} - - -function replicate(repId, src, target, opts, promise) { - var batches = []; // queue of batches of changes to be processed - var pendingBatch = new Batch(); - var changesCompleted = false; - var completeCalled = false; - var last_seq = 0; - var continuous = opts.continuous || false; - var batch_size = opts.batch_size || 1; - var doc_ids = opts.doc_ids; - var result = { - ok: true, - start_time: new Date(), - docs_read: 0, - docs_written: 0, - errors: [] - }; - - - function writeDocs() { - if (batches[0].docs.length === 0) { - // This should never happen: - // batch processing continues past onRevsDiff only if there are diffs - // and replication is aborted if a get fails. - // TODO: throw or log the error - return finishBatch(); - } - - var docs = batches[0].docs; - target.bulkDocs({docs: docs}, {new_edits: false}, function (err, res) { - if (err) { - return abortReplication('target.bulkDocs completed with error', err); - } - - result.docs_written += docs.length; - finishBatch(); - }); - } - - - function onGet(err, docs) { - if (promise.cancelled) { - return replicationCancelled(); - } - - if (err) { - return abortReplication('src.get completed with error', err); - } - - Object.keys(docs).forEach(function (revpos) { - var doc = docs[revpos].ok; - - if (doc) { - result.docs_read++; - batches[0].pendingRevs++; - batches[0].docs.push(doc); - } - }); - - fetchRev(); - } - - - function fetchRev() { - var diffs = batches[0].diffs; - - if (Object.keys(diffs).length === 0) { - writeDocs(); - return; - } - - var id = Object.keys(diffs)[0]; - var revs = diffs[id].missing; - delete diffs[id]; - - src.get(id, {revs: true, open_revs: revs, attachments: true}, onGet); - } - - - function abortReplication(reason, err) { - if (completeCalled) { - return; - } - result.ok = false; - result.status = 'aborted'; - result.errors.push(err); - result.end_time = new Date(); - result.last_seq = last_seq; - promise.cancel(); - batches = []; - pendingBatch = new Batch(); - var error = { - status: 500, - error: 'Replication aborted', - reason: reason, - details: err - }; - completeCalled = true; - PouchUtils.call(opts.complete, error, result); - } - - - function finishBatch() { - writeCheckpoint(src, target, repId, batches[0].seq, function (err, res) { - if (err) { - return abortReplication('writeCheckpoint completed with error', err); - } - last_seq = batches[0].seq; - result.last_seq = last_seq; - PouchUtils.call(opts.onChange, null, result); - batches.shift(); - startNextBatch(); - }); - } - - function onRevsDiff(err, diffs) { - if (promise.cancelled) { - return replicationCancelled(); - } - - if (err) { - return abortReplication('target.revsDiff completed with error', err); - } - - if (Object.keys(diffs).length === 0) { - finishBatch(); - return; - } - - batches[0].diffs = diffs; - batches[0].pendingRevs = 0; - fetchRev(); - } - - - function fetchRevsDiff() { - var diff = {}; - batches[0].changes.forEach(function (change) { - diff[change.id] = change.changes.map(function (x) { return x.rev; }); - }); - - target.revsDiff(diff, onRevsDiff); - } - - - function startNextBatch() { - if (promise.cancelled) { - return replicationCancelled(); - } - - if (batches.length === 0) { - processPendingBatch(); - return; - } - - if (batches[0].state === 'start') { - batches[0].state = 'processing'; - fetchRevsDiff(); - } - } - - - function processPendingBatch() { - if (pendingBatch.changes.length === 0) { - if (changesCompleted && batches.length === 0) { - replicationComplete(); - } - return; - } - - if (changesCompleted || pendingBatch.changes.length >= batch_size) { - batches.push(pendingBatch); - pendingBatch = new Batch(); - startNextBatch(); - } - } - - - function replicationCancelled() { - result.status = 'cancelled'; - replicationComplete(); - } - - - function replicationComplete() { - if (completeCalled) { - return; - } - result.status = result.status || 'complete'; - result.end_time = new Date(); - result.last_seq = last_seq; - completeCalled = true; - return PouchUtils.call(opts.complete, null, result); - } - - - function onChange(change) { - if (promise.cancelled) { - return replicationCancelled(); - } - - if (completeCalled) { - // This should never happen - // The complete callback has already been called - // How to raise an exception in PouchDBVersion200? - return; - } - - pendingBatch.seq = change.seq; - pendingBatch.changes.push(change); - - processPendingBatch(); - } - - - function complete(err, result) { - changesCompleted = true; - if (promise.cancelled) { - return replicationCancelled(); - } - - if (err) { - return abortReplication('src.changes completed with error', err); - } - - processPendingBatch(); - } - - - function getChanges() { - fetchCheckpoint(src, target, repId, function (err, checkpoint) { - if (err) { - return abortReplication('fetchCheckpoint completed with error', err); - } - - last_seq = checkpoint; - - // Was the replication cancelled by the caller before it had a chance - // to start. Shouldnt we be calling complete? - if (promise.cancelled) { - return replicationCancelled(); - } - - // Call changes on the source database, with callbacks to onChange for - // each change and complete when done. - var repOpts = { - continuous: continuous, - since: last_seq, - style: 'all_docs', - onChange: onChange, - complete: complete, - doc_ids: doc_ids - }; - - if (opts.filter) { - repOpts.filter = opts.filter; - } - - if (opts.query_params) { - repOpts.query_params = opts.query_params; - } - - var changes = src.changes(repOpts); - - if (opts.continuous) { - var cancel = promise.cancel; - promise.cancel = function () { - cancel(); - changes.cancel(); - }; - } - }); - } - - // If opts.since is given, set the checkpoint to opts.since - if (typeof opts.since === 'undefined') { - getChanges(); - } else { - writeCheckpoint(src, target, repId, opts.since, function (err, res) { - if (err) { - return abortReplication('writeCheckpoint completed with error', err); - } - last_seq = opts.since; - getChanges(); - }); - } -} - -function toPouch(db, callback) { - if (typeof db === 'string') { - return new Pouch(db, callback); - } - callback(null, db); -} - -function replicateWrapper(src, target, opts, callback) { - if (opts instanceof Function) { - callback = opts; - opts = {}; - } - if (opts === undefined) { - opts = {}; - } - if (!opts.complete) { - opts.complete = callback; - } - var replicateRet = new Promise(); - toPouch(src, function (err, src) { - if (err) { - return callback(err); - } - toPouch(target, function (err, target) { - if (err) { - return callback(err); - } - if (opts.server) { - if (typeof src.replicateOnServer !== 'function') { - return callback({ - error: 'Server replication not supported for ' + src.type() + - 'adapter' - }); - } - if (src.type() !== target.type()) { - return callback({ - error: 'Server replication for different adapter types (' + - src.type() + ' and ' + target.type() + ') is not supported' - }); - } - src.replicateOnServer(target, opts, replicateRet); - } else { - genReplicationId(src, target, opts, function (repId) { - replicate(repId, src, target, opts, replicateRet); - }); - } - }); - }); - return replicateRet; -} - -function sync(db1, db2, opts, callback) { - var push_promise; - var pull_promise; - - function complete(callback) { - return function (err, res) { - if (err) { - // cancel both replications if either experiences problems - cancel(); - } - callback(err, res); - }; - } - - function onChange(src, callback) { - callback = callback || function () {}; - return function (change) { - return { - source: src, - change: callback(change) - }; - }; - } - - function makeOpts(src, opts) { - opts = PouchUtils.extend(true, {}, opts); - opts.complete = complete(opts.complete); - opts.onChange = onChange(src, opts.onChange); - return opts; - } - - function push() { - push_promise = replicateWrapper(db1, db2, makeOpts(db1, opts), callback); - return push_promise; - } - - function pull() { - pull_promise = replicateWrapper(db2, db1, makeOpts(db2, opts), callback); - return pull_promise; - } - - function cancel() { - if (push_promise) { - push_promise.cancel(); - } - if (pull_promise) { - pull_promise.cancel(); - } - } - - return { - push: push(), - pull: pull(), - cancel: cancel - }; -} - -exports.replicate = replicateWrapper; -exports.sync = sync; - -},{"./index":13,"./utils":18}],16:[function(_dereq_,module,exports){ -"use strict"; - -var PouchDBVersion200 = _dereq_("./constructor"); -var utils = _dereq_('./utils'); -var EventEmitter = _dereq_('events').EventEmitter; -PouchDBVersion200.adapters = {}; - -PouchDBVersion200.prefix = '_pouch_'; - -var eventEmitter = new EventEmitter(); - -var eventEmitterMethods = [ - 'on', - 'addListener', - 'emit', - 'listeners', - 'once', - 'removeAllListeners', - 'removeListener', - 'setMaxListeners' -]; - -eventEmitterMethods.forEach(function (method) { - PouchDBVersion200[method] = eventEmitter[method].bind(eventEmitter); -}); -PouchDBVersion200.setMaxListeners(0); -PouchDBVersion200.parseAdapter = function (name) { - var match = name.match(/([a-z\-]*):\/\/(.*)/); - var adapter; - if (match) { - // the http adapter expects the fully qualified name - name = /http(s?)/.test(match[1]) ? match[1] + '://' + match[2] : match[2]; - adapter = match[1]; - if (!PouchDBVersion200.adapters[adapter].valid()) { - throw 'Invalid adapter'; - } - return {name: name, adapter: match[1]}; - } - - var preferredAdapters = ['idb', 'leveldb', 'websql']; - for (var i = 0; i < preferredAdapters.length; ++i) { - if (preferredAdapters[i] in PouchDBVersion200.adapters) { - adapter = PouchDBVersion200.adapters[preferredAdapters[i]]; - var use_prefix = 'use_prefix' in adapter ? adapter.use_prefix : true; - - return { - name: use_prefix ? PouchDBVersion200.prefix + name : name, - adapter: preferredAdapters[i] - }; - } - } - - throw 'No valid adapter found'; -}; - -PouchDBVersion200.destroy = utils.toPromise(function (name, opts, callback) { - if (typeof opts === 'function' || typeof opts === 'undefined') { - callback = opts; - opts = {}; - } - - if (typeof name === 'object') { - opts = name; - name = undefined; - } - - var backend = PouchDBVersion200.parseAdapter(opts.name || name); - var dbName = backend.name; - - // call destroy method of the particular adaptor - PouchDBVersion200.adapters[backend.adapter].destroy(dbName, opts, function (err, resp) { - if (err) { - callback(err); - } else { - PouchDBVersion200.emit('destroyed', dbName); - //so we don't have to sift through all dbnames - PouchDBVersion200.emit(dbName, 'destroyed'); - callback(null, resp); - } - }); -}); -PouchDBVersion200.allDbs = utils.toPromise(function (callback) { - var err = new Error('allDbs method removed'); - err.stats = '400'; - callback(err); -}); -PouchDBVersion200.adapter = function (id, obj) { - if (obj.valid()) { - PouchDBVersion200.adapters[id] = obj; - } -}; - -PouchDBVersion200.plugin = function (obj) { - Object.keys(obj).forEach(function (id) { - PouchDBVersion200.prototype[id] = obj[id]; - }); -}; - -module.exports = PouchDBVersion200; - -},{"./constructor":5,"./utils":18,"events":21}],17:[function(_dereq_,module,exports){ -'use strict'; - -module.exports = TaskQueue; - -function TaskQueue() { - this.isReady = false; - this.failed = false; - this.queue = []; -} - -TaskQueue.prototype.execute = function () { - var d, func; - if (this.failed) { - while ((d = this.queue.shift())) { - func = d.parameters[d.parameters.length - 1]; - if (typeof func === 'function') { - func(this.failed); - } else if (d.name === 'changes' && typeof func.complete === 'function') { - func.complete(this.failed); - } - } - } else if (this.isReady) { - while ((d = this.queue.shift())) { - d.task = this.db[d.name].apply(this.db, d.parameters); - } - } -}; -TaskQueue.prototype.fail = function (err) { - this.failed = err; - this.execute(); -}; - -TaskQueue.prototype.ready = function (db) { - if (this.failed) { - return false; - } else if (arguments.length === 0) { - return this.isReady; - } - this.isReady = db ? true: false; - this.db = db; - this.execute(); -}; - -TaskQueue.prototype.addTask = function (name, parameters) { - var task = { name: name, parameters: parameters }; - this.queue.push(task); - if (this.failed) { - this.execute(); - } - return task; -}; -},{}],18:[function(_dereq_,module,exports){ -(function (process,global){ -/*jshint strict: false */ -/*global chrome */ - -var merge = _dereq_('./merge'); -exports.extend = _dereq_('./deps/extend'); -exports.ajax = _dereq_('./deps/ajax'); -exports.createBlob = _dereq_('./deps/blob'); -var uuid = _dereq_('./deps/uuid'); -exports.Crypto = _dereq_('./deps/md5.js'); -var buffer = _dereq_('./deps/buffer'); -var errors = _dereq_('./deps/errors'); -var Promise = typeof global.Promise === 'function' ? global.Promise : _dereq_('bluebird'); - -// List of top level reserved words for doc -var reservedWords = [ - '_id', - '_rev', - '_attachments', - '_deleted', - '_revisions', - '_revs_info', - '_conflicts', - '_deleted_conflicts', - '_local_seq', - '_rev_tree' -]; -exports.inherits = _dereq_('inherits'); -exports.uuids = function (count, options) { - - if (typeof(options) !== 'object') { - options = {}; - } - - var length = options.length; - var radix = options.radix; - var uuids = []; - - while (uuids.push(uuid(length, radix)) < count) { } - - return uuids; -}; - -// Give back one UUID -exports.uuid = function (options) { - return exports.uuids(1, options)[0]; -}; -// Determine id an ID is valid -// - invalid IDs begin with an underescore that does not begin '_design' or '_local' -// - any other string value is a valid id -// Returns the specific error object for each case -exports.invalidIdError = function (id) { - if (!id) { - return errors.MISSING_ID; - } else if (typeof id !== 'string') { - return errors.INVALID_ID; - } else if (/^_/.test(id) && !(/^_(design|local)/).test(id)) { - return errors.RESERVED_ID; - } -}; - -function isChromeApp() { - return (typeof chrome !== "undefined" && - typeof chrome.storage !== "undefined" && - typeof chrome.storage.local !== "undefined"); -} - -// Pretty dumb name for a function, just wraps callback calls so we dont -// to if (callback) callback() everywhere -exports.call = function (fun) { - if (typeof fun === typeof Function) { - var args = Array.prototype.slice.call(arguments, 1); - fun.apply(this, args); - } -}; - -exports.isLocalId = function (id) { - return (/^_local/).test(id); -}; - -// check if a specific revision of a doc has been deleted -// - metadata: the metadata object from the doc store -// - rev: (optional) the revision to check. defaults to winning revision -exports.isDeleted = function (metadata, rev) { - if (!rev) { - rev = merge.winningRev(metadata); - } - if (rev.indexOf('-') >= 0) { - rev = rev.split('-')[1]; - } - var deleted = false; - merge.traverseRevTree(metadata.rev_tree, function (isLeaf, pos, id, acc, opts) { - if (id === rev) { - deleted = !!opts.deleted; - } - }); - - return deleted; -}; - -exports.filterChange = function (opts) { - return function (change) { - var req = {}; - var hasFilter = opts.filter && typeof opts.filter === 'function'; - - req.query = opts.query_params; - if (opts.filter && hasFilter && !opts.filter.call(this, change.doc, req)) { - return false; - } - if (opts.doc_ids && opts.doc_ids.indexOf(change.id) === -1) { - return false; - } - if (!opts.include_docs) { - delete change.doc; - } else { - for (var att in change.doc._attachments) { - if (change.doc._attachments.hasOwnProperty(att)) { - change.doc._attachments[att].stub = true; - } - } - } - return true; - }; -}; - -exports.processChanges = function (opts, changes, last_seq) { - // TODO: we should try to filter and limit as soon as possible - changes = changes.filter(exports.filterChange(opts)); - if (opts.limit) { - if (opts.limit < changes.length) { - changes.length = opts.limit; - } - } - changes.forEach(function (change) { - exports.call(opts.onChange, change); - }); - if (!opts.continuous) { - exports.call(opts.complete, null, {results: changes, last_seq: last_seq}); - } -}; - -// Preprocess documents, parse their revisions, assign an id and a -// revision for new writes that are missing them, etc -exports.parseDoc = function (doc, newEdits) { - var error = null; - var nRevNum; - var newRevId; - var revInfo; - var opts = {status: 'available'}; - if (doc._deleted) { - opts.deleted = true; - } - - if (newEdits) { - if (!doc._id) { - doc._id = exports.uuid(); - } - newRevId = exports.uuid({length: 32, radix: 16}).toLowerCase(); - if (doc._rev) { - revInfo = /^(\d+)-(.+)$/.exec(doc._rev); - if (!revInfo) { - throw "invalid value for property '_rev'"; - } - doc._rev_tree = [{ - pos: parseInt(revInfo[1], 10), - ids: [revInfo[2], {status: 'missing'}, [[newRevId, opts, []]]] - }]; - nRevNum = parseInt(revInfo[1], 10) + 1; - } else { - doc._rev_tree = [{ - pos: 1, - ids : [newRevId, opts, []] - }]; - nRevNum = 1; - } - } else { - if (doc._revisions) { - doc._rev_tree = [{ - pos: doc._revisions.start - doc._revisions.ids.length + 1, - ids: doc._revisions.ids.reduce(function (acc, x) { - if (acc === null) { - return [x, opts, []]; - } else { - return [x, {status: 'missing'}, [acc]]; - } - }, null) - }]; - nRevNum = doc._revisions.start; - newRevId = doc._revisions.ids[0]; - } - if (!doc._rev_tree) { - revInfo = /^(\d+)-(.+)$/.exec(doc._rev); - if (!revInfo) { - return errors.BAD_ARG; - } - nRevNum = parseInt(revInfo[1], 10); - newRevId = revInfo[2]; - doc._rev_tree = [{ - pos: parseInt(revInfo[1], 10), - ids: [revInfo[2], opts, []] - }]; - } - } - - error = exports.invalidIdError(doc._id); - - for (var key in doc) { - if (doc.hasOwnProperty(key) && key[0] === '_' && reservedWords.indexOf(key) === -1) { - error = exports.extend({}, errors.DOC_VALIDATION); - error.reason += ': ' + key; - } - } - - doc._id = decodeURIComponent(doc._id); - doc._rev = [nRevNum, newRevId].join('-'); - - if (error) { - return error; - } - - return Object.keys(doc).reduce(function (acc, key) { - if (/^_/.test(key) && key !== '_attachments') { - acc.metadata[key.slice(1)] = doc[key]; - } else { - acc.data[key] = doc[key]; - } - return acc; - }, {metadata : {}, data : {}}); -}; - -exports.isCordova = function () { - return (typeof cordova !== "undefined" || - typeof PhoneGap !== "undefined" || - typeof phonegap !== "undefined"); -}; - -exports.Changes = function () { - - var api = {}; - var listeners = {}; - - if (isChromeApp()) { - chrome.storage.onChanged.addListener(function (e) { - // make sure it's event addressed to us - if (e.db_name != null) { - api.notify(e.db_name.newValue);//object only has oldValue, newValue members - } - }); - } else if (typeof window !== 'undefined') { - global.addEventListener("storage", function (e) { - api.notify(e.key); - }); - } - - api.addListener = function (db_name, id, db, opts) { - if (!listeners[db_name]) { - listeners[db_name] = {}; - } - listeners[db_name][id] = { - db: db, - opts: opts - }; - }; - - api.removeListener = function (db_name, id) { - if (listeners[db_name]) { - delete listeners[db_name][id]; - } - }; - - api.clearListeners = function (db_name) { - delete listeners[db_name]; - }; - - api.notifyLocalWindows = function (db_name) { - //do a useless change on a storage thing - //in order to get other windows's listeners to activate - if (isChromeApp()) { - chrome.storage.local.set({db_name: db_name}); - } else if (global.localStorage) { - localStorage[db_name] = (localStorage[db_name] === "a") ? "b" : "a"; - } - }; - - api.notify = function (db_name) { - if (!listeners[db_name]) { return; } - - Object.keys(listeners[db_name]).forEach(function (i) { - var opts = listeners[db_name][i].opts; - listeners[db_name][i].db.changes({ - include_docs: opts.include_docs, - conflicts: opts.conflicts, - continuous: false, - descending: false, - filter: opts.filter, - view: opts.view, - since: opts.since, - query_params: opts.query_params, - onChange: function (c) { - if (c.seq > opts.since && !opts.cancelled) { - opts.since = c.seq; - exports.call(opts.onChange, c); - } - } - }); - }); - }; - - return api; -}; - -if (!process.browser || !('atob' in global)) { - exports.atob = function (str) { - var base64 = new buffer(str, 'base64'); - // Node.js will just skip the characters it can't encode instead of - // throwing and exception - if (base64.toString('base64') !== str) { - throw ("Cannot base64 encode full string"); - } - return base64.toString('binary'); - }; -} else { - exports.atob = function (str) { - return atob(str); - }; -} - -if (!process.browser || !('btoa' in global)) { - exports.btoa = function (str) { - return new buffer(str, 'binary').toString('base64'); - }; -} else { - exports.btoa = function (str) { - return btoa(str); - }; -} - -// From http://stackoverflow.com/questions/14967647/encode-decode-image-with-base64-breaks-image (2013-04-21) -exports.fixBinary = function (bin) { - if (!process.browser) { - // don't need to do this in Node - return bin; - } - - var length = bin.length; - var buf = new ArrayBuffer(length); - var arr = new Uint8Array(buf); - for (var i = 0; i < length; i++) { - arr[i] = bin.charCodeAt(i); - } - return buf; -}; - -exports.toPromise = function (func) { - //create the function we will be returning - return function () { - var self = this; - var args = Array.prototype.slice.call(arguments); - var tempCB = (typeof args[args.length - 1] === 'function') ? args.pop() : false; - // if the last argument is a function, assume its a callback - var usedCB; - if (tempCB) { - // if it was a callback, create a new callback which calls the callback function - // but we do so async so we don't trap any errors - usedCB = function (err, resp) { - process.nextTick(function () { - tempCB(err, resp); - }); - }; - } - var promise = new Promise(function (fulfill, reject) { - function callback(err, mesg) { - if (err) { - reject(err); - } else { - fulfill(mesg); - } - } - // create a callback for this invocation - args.push(callback); - func.apply(self, args); - // apply the function in the orig context - }); - // if there is a callback, call it back - if (usedCB) { - promise.then(function (result) { - usedCB(null, result); - }, usedCB); - } - return promise; - }; -}; - -}).call(this,_dereq_("/Users/daleharvey/src/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./deps/ajax":6,"./deps/blob":7,"./deps/buffer":20,"./deps/errors":8,"./deps/extend":10,"./deps/md5.js":11,"./deps/uuid":12,"./merge":14,"/Users/daleharvey/src/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":22,"bluebird":24,"inherits":23}],19:[function(_dereq_,module,exports){ -module.exports = _dereq_('../package.json').version; -},{"../package.json":37}],20:[function(_dereq_,module,exports){ - -},{}],21:[function(_dereq_,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -function EventEmitter() { - this._events = this._events || {}; - this._maxListeners = this._maxListeners || undefined; -} -module.exports = EventEmitter; - -// Backwards-compat with node 0.10.x -EventEmitter.EventEmitter = EventEmitter; - -EventEmitter.prototype._events = undefined; -EventEmitter.prototype._maxListeners = undefined; - -// By default EventEmitters will print a warning if more than 10 listeners are -// added to it. This is a useful default which helps finding memory leaks. -EventEmitter.defaultMaxListeners = 10; - -// Obviously not all Emitters should be limited to 10. This function allows -// that to be increased. Set to zero for unlimited. -EventEmitter.prototype.setMaxListeners = function(n) { - if (!isNumber(n) || n < 0 || isNaN(n)) - throw TypeError('n must be a positive number'); - this._maxListeners = n; - return this; -}; - -EventEmitter.prototype.emit = function(type) { - var er, handler, len, args, i, listeners; - - if (!this._events) - this._events = {}; - - // If there is no 'error' event listener then throw. - if (type === 'error') { - if (!this._events.error || - (isObject(this._events.error) && !this._events.error.length)) { - er = arguments[1]; - if (er instanceof Error) { - throw er; // Unhandled 'error' event - } else { - throw TypeError('Uncaught, unspecified "error" event.'); - } - return false; - } - } - - handler = this._events[type]; - - if (isUndefined(handler)) - return false; - - if (isFunction(handler)) { - switch (arguments.length) { - // fast cases - case 1: - handler.call(this); - break; - case 2: - handler.call(this, arguments[1]); - break; - case 3: - handler.call(this, arguments[1], arguments[2]); - break; - // slower - default: - len = arguments.length; - args = new Array(len - 1); - for (i = 1; i < len; i++) - args[i - 1] = arguments[i]; - handler.apply(this, args); - } - } else if (isObject(handler)) { - len = arguments.length; - args = new Array(len - 1); - for (i = 1; i < len; i++) - args[i - 1] = arguments[i]; - - listeners = handler.slice(); - len = listeners.length; - for (i = 0; i < len; i++) - listeners[i].apply(this, args); - } - - return true; -}; - -EventEmitter.prototype.addListener = function(type, listener) { - var m; - - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - if (!this._events) - this._events = {}; - - // To avoid recursion in the case that type === "newListener"! Before - // adding it to the listeners, first emit "newListener". - if (this._events.newListener) - this.emit('newListener', type, - isFunction(listener.listener) ? - listener.listener : listener); - - if (!this._events[type]) - // Optimize the case of one listener. Don't need the extra array object. - this._events[type] = listener; - else if (isObject(this._events[type])) - // If we've already got an array, just append. - this._events[type].push(listener); - else - // Adding the second element, need to change to array. - this._events[type] = [this._events[type], listener]; - - // Check for listener leak - if (isObject(this._events[type]) && !this._events[type].warned) { - var m; - if (!isUndefined(this._maxListeners)) { - m = this._maxListeners; - } else { - m = EventEmitter.defaultMaxListeners; - } - - if (m && m > 0 && this._events[type].length > m) { - this._events[type].warned = true; - console.error('(node) warning: possible EventEmitter memory ' + - 'leak detected. %d listeners added. ' + - 'Use emitter.setMaxListeners() to increase limit.', - this._events[type].length); - console.trace(); - } - } - - return this; -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.once = function(type, listener) { - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - var fired = false; - - function g() { - this.removeListener(type, g); - - if (!fired) { - fired = true; - listener.apply(this, arguments); - } - } - - g.listener = listener; - this.on(type, g); - - return this; -}; - -// emits a 'removeListener' event iff the listener was removed -EventEmitter.prototype.removeListener = function(type, listener) { - var list, position, length, i; - - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - if (!this._events || !this._events[type]) - return this; - - list = this._events[type]; - length = list.length; - position = -1; - - if (list === listener || - (isFunction(list.listener) && list.listener === listener)) { - delete this._events[type]; - if (this._events.removeListener) - this.emit('removeListener', type, listener); - - } else if (isObject(list)) { - for (i = length; i-- > 0;) { - if (list[i] === listener || - (list[i].listener && list[i].listener === listener)) { - position = i; - break; - } - } - - if (position < 0) - return this; - - if (list.length === 1) { - list.length = 0; - delete this._events[type]; - } else { - list.splice(position, 1); - } - - if (this._events.removeListener) - this.emit('removeListener', type, listener); - } - - return this; -}; - -EventEmitter.prototype.removeAllListeners = function(type) { - var key, listeners; - - if (!this._events) - return this; - - // not listening for removeListener, no need to emit - if (!this._events.removeListener) { - if (arguments.length === 0) - this._events = {}; - else if (this._events[type]) - delete this._events[type]; - return this; - } - - // emit removeListener for all listeners on all events - if (arguments.length === 0) { - for (key in this._events) { - if (key === 'removeListener') continue; - this.removeAllListeners(key); - } - this.removeAllListeners('removeListener'); - this._events = {}; - return this; - } - - listeners = this._events[type]; - - if (isFunction(listeners)) { - this.removeListener(type, listeners); - } else { - // LIFO order - while (listeners.length) - this.removeListener(type, listeners[listeners.length - 1]); - } - delete this._events[type]; - - return this; -}; - -EventEmitter.prototype.listeners = function(type) { - var ret; - if (!this._events || !this._events[type]) - ret = []; - else if (isFunction(this._events[type])) - ret = [this._events[type]]; - else - ret = this._events[type].slice(); - return ret; -}; - -EventEmitter.listenerCount = function(emitter, type) { - var ret; - if (!emitter._events || !emitter._events[type]) - ret = 0; - else if (isFunction(emitter._events[type])) - ret = 1; - else - ret = emitter._events[type].length; - return ret; -}; - -function isFunction(arg) { - return typeof arg === 'function'; -} - -function isNumber(arg) { - return typeof arg === 'number'; -} - -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} - -function isUndefined(arg) { - return arg === void 0; -} - -},{}],22:[function(_dereq_,module,exports){ -// shim for using process in browser - -var process = module.exports = {}; - -process.nextTick = (function () { - var canSetImmediate = typeof window !== 'undefined' - && window.setImmediate; - var canPost = typeof window !== 'undefined' - && window.postMessage && window.addEventListener - ; - - if (canSetImmediate) { - return function (f) { return window.setImmediate(f) }; - } - - if (canPost) { - var queue = []; - window.addEventListener('message', function (ev) { - var source = ev.source; - if ((source === window || source === null) && ev.data === 'process-tick') { - ev.stopPropagation(); - if (queue.length > 0) { - var fn = queue.shift(); - fn(); - } - } - }, true); - - return function nextTick(fn) { - queue.push(fn); - window.postMessage('process-tick', '*'); - }; - } - - return function nextTick(fn) { - setTimeout(fn, 0); - }; -})(); - -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; - -process.binding = function (name) { - throw new Error('process.binding is not supported'); -} - -// TODO(shtylman) -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; - -},{}],23:[function(_dereq_,module,exports){ -if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); - }; -} else { - // old school shim for old browsers - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - var TempCtor = function () {} - TempCtor.prototype = superCtor.prototype - ctor.prototype = new TempCtor() - ctor.prototype.constructor = ctor - } -} - -},{}],24:[function(_dereq_,module,exports){ -'use strict'; - -var immediate = _dereq_('immediate'); -var isDefineProp = false; -// prevents deoptimization -(function(){ - try { - Object.defineProperty({}, 'test', {value:true}); - isDefineProp = true; - }catch(e){} -}()); -function defineNonEnum(obj, name, value){ - if(isDefineProp){ - Object.defineProperty(obj, name, { - value: value, - configurable: true, - writable: true - }); - }else{ - obj[name] = value; - } -} -function Promise(resolver) { - - if (!(this instanceof Promise)) { - return new Promise(resolver); - } - - defineNonEnum(this, 'successQueue', []); - defineNonEnum(this, 'failureQueue', []); - defineNonEnum(this, 'resolved', false); - - - if(typeof resolver === 'function'){ - this.resolvePassed(resolver); - } -} -defineNonEnum(Promise.prototype, 'resolvePassed', function(resolver){ - try{ - resolver(this.fulfillUnwrap.bind(this),this.reject.bind(this)); - }catch(e){ - this.reject(e); - } -}); -defineNonEnum(Promise.prototype, 'reject', function(reason){ - this.resolve(false,reason); -}); -defineNonEnum(Promise.prototype, 'fulfill', function(value){ - this.resolve(true,value); -}); -defineNonEnum(Promise.prototype, 'fulfillUnwrap', function(value){ - unwrap(this.fulfill.bind(this), this.reject.bind(this), value); -}); -Promise.prototype.then = function(onFulfilled, onRejected) { - if(this.resolved){ - return this.resolved(onFulfilled, onRejected); - } else { - return this.pending(onFulfilled, onRejected); - } -}; -(function(){ - try { - Promise.prototype.catch = function(onRejected) { - return this.then(null, onRejected); - }; - } catch(e){} -}()); -defineNonEnum(Promise.prototype, 'pending', function(onFulfilled, onRejected){ - var self = this; - return new Promise(function(success,failure){ - if(typeof onFulfilled === 'function'){ - self.successQueue.push({ - resolve: success, - reject: failure, - callback:onFulfilled - }); - }else{ - self.successQueue.push({ - next: success, - callback:false - }); - } - - if(typeof onRejected === 'function'){ - self.failureQueue.push({ - resolve: success, - reject: failure, - callback:onRejected - }); - }else{ - self.failureQueue.push({ - next: failure, - callback:false - }); - } - }); -}); -defineNonEnum(Promise.prototype, 'resolve', function (success, value){ - - if(this.resolved){ - return; - } - - this.resolved = createResolved(this, value, success?0:1); - - var queue = success ? this.successQueue : this.failureQueue; - var len = queue.length; - var i = -1; - while(++i < len) { - - if (queue[i].callback) { - immediate(execute,queue[i].callback, value, queue[i].resolve, queue[i].reject); - }else { - queue[i].next(value); - } - } -}); - -function unwrap(fulfill, reject, value){ - if(value && typeof value.then==='function'){ - value.then(fulfill,reject); - }else{ - fulfill(value); - } -} - -function createResolved(scope, value, whichArg) { - function resolved() { - var callback = arguments[whichArg]; - if (typeof callback !== 'function') { - return scope; - }else{ - return new Promise(function(resolve,reject){ - immediate(execute,callback,value,resolve,reject); - }); - } - } - return resolved; -} - -function execute(callback, value, resolve, reject) { - try { - unwrap(resolve,reject,callback(value)); - } catch (error) { - reject(error); - } -} - - - -module.exports = Promise; - -},{"immediate":27}],25:[function(_dereq_,module,exports){ -"use strict"; -exports.test = function () { - return false; -}; -},{}],26:[function(_dereq_,module,exports){ -(function (global){ -module.exports = typeof global === "object" && global ? global : this; -}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],27:[function(_dereq_,module,exports){ -"use strict"; -var types = [ - _dereq_("./nextTick"), - _dereq_("./mutation"), - _dereq_("./realSetImmediate"), - _dereq_("./postMessage"), - _dereq_("./messageChannel"), - _dereq_("./stateChange"), - _dereq_("./timeout") -]; -var handlerQueue = []; -function drainQueue() { - var i = 0, - task, - innerQueue = handlerQueue; - handlerQueue = []; - /*jslint boss: true */ - while (task = innerQueue[i++]) { - task(); - } -} -var nextTick; -var i = -1; -var len = types.length; -while(++i<len){ - if(types[i].test()){ - nextTick = types[i].install(drainQueue); - break; - } -} -var retFunc = function (task) { - var len, args; - var nTask = task; - if (arguments.length > 1 && typeof task === "function") { - args = Array.prototype.slice.call(arguments, 1); - nTask = function(){ - task.apply(undefined,args); - } - } - if ((len = handlerQueue.push(nTask)) === 1) { - nextTick(drainQueue); - } - return len; -}; -retFunc.clear = function (n) { - if (n <= handlerQueue.length) { - handlerQueue[n - 1] = function () {}; - } - return this; -}; -module.exports = retFunc; - -},{"./messageChannel":28,"./mutation":29,"./nextTick":25,"./postMessage":30,"./realSetImmediate":31,"./stateChange":32,"./timeout":33}],28:[function(_dereq_,module,exports){ -"use strict"; -var globe = _dereq_("./global"); -exports.test = function () { - return !!globe.MessageChannel; -}; - -exports.install = function (func) { - var channel = new globe.MessageChannel(); - channel.port1.onmessage = func; - return function () { - channel.port2.postMessage(0); - }; -}; -},{"./global":26}],29:[function(_dereq_,module,exports){ -"use strict"; -//based off rsvp -//https://github.com/tildeio/rsvp.js/blob/master/lib/rsvp/async.js -var globe = _dereq_("./global"); - -var MutationObserver = globe.MutationObserver || globe.WebKitMutationObserver; - -exports.test = function () { - return MutationObserver; -}; - -exports.install = function (handle) { - var observer = new MutationObserver(handle); - var element = globe.document.createElement("div"); - observer.observe(element, { attributes: true }); - - // Chrome Memory Leak: https://bugs.webkit.org/show_bug.cgi?id=93661 - globe.addEventListener("unload", function () { - observer.disconnect(); - observer = null; - }, false); - return function () { - element.setAttribute("drainQueue", "drainQueue"); - }; -}; -},{"./global":26}],30:[function(_dereq_,module,exports){ -"use strict"; -var globe = _dereq_("./global"); -exports.test = function () { - // The test against `importScripts` prevents this implementation from being installed inside a web worker, - // where `global.postMessage` means something completely different and can"t be used for this purpose. - - if (!globe.postMessage || globe.importScripts) { - return false; - } - - var postMessageIsAsynchronous = true; - var oldOnMessage = globe.onmessage; - globe.onmessage = function () { - postMessageIsAsynchronous = false; - }; - globe.postMessage("", "*"); - globe.onmessage = oldOnMessage; - - return postMessageIsAsynchronous; -}; - -exports.install = function (func) { - var codeWord = "com.calvinmetcalf.setImmediate" + Math.random(); - function globalMessage(event) { - if (event.source === globe && event.data === codeWord) { - func(); - } - } - if (globe.addEventListener) { - globe.addEventListener("message", globalMessage, false); - } else { - globe.attachEvent("onmessage", globalMessage); - } - return function () { - globe.postMessage(codeWord, "*"); - }; -}; -},{"./global":26}],31:[function(_dereq_,module,exports){ -"use strict"; -var globe = _dereq_("./global"); -exports.test = function () { - return globe.setImmediate; -}; - -exports.install = function (handle) { - return globe.setTimeout.bind(globe, handle, 0); -}; - -},{"./global":26}],32:[function(_dereq_,module,exports){ -"use strict"; -var globe = _dereq_("./global"); -exports.test = function () { - return "document" in globe && "onreadystatechange" in globe.document.createElement("script"); -}; - -exports.install = function (handle) { - return function () { - - // Create a <script> 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 = globe.document.createElement("script"); - scriptEl.onreadystatechange = function () { - handle(); - - scriptEl.onreadystatechange = null; - scriptEl.parentNode.removeChild(scriptEl); - scriptEl = null; - }; - globe.document.documentElement.appendChild(scriptEl); - - return handle; - }; -}; -},{"./global":26}],33:[function(_dereq_,module,exports){ -"use strict"; -exports.test = function () { - return true; -}; - -exports.install = function (t) { - return function () { - setTimeout(t, 0); - }; -}; -},{}],34:[function(_dereq_,module,exports){ -'use strict'; - -module.exports = function (func, emit, sum, log, isArray, toJSON) { - /*jshint evil: true */ - return eval("'use strict'; (" + func + ");"); -}; - -},{}],35:[function(_dereq_,module,exports){ -(function (process,global){ -'use strict'; - -var pouchCollate = _dereq_('pouchdb-collate'); -var Promise = typeof global.Promise === 'function' ? global.Promise : _dereq_('lie'); -var collate = pouchCollate.collate; -var evalFunc = _dereq_('./evalfunc'); -var log = (typeof console !== 'undefined') ? - Function.prototype.bind.call(console.log, console) : function () {}; -var processKey = function (key) { - // Stringify keys since we want them as map keys (see #35) - return JSON.stringify(pouchCollate.normalizeKey(key)); -}; -// This is the first implementation of a basic plugin, we register the -// plugin object with pouch and it is mixin'd to each database created -// (regardless of adapter), adapters can override plugins by providing -// their own implementation. functions on the plugin object that start -// with _ are reserved function that are called by pouchdb for special -// notifications. - -// If we wanted to store incremental views we can do it here by listening -// to the changes feed (keeping track of our last update_seq between page loads) -// and storing the result of the map function (possibly using the upcoming -// extracted adapter functions) - - -function createKeysLookup(keys) { - // creates a lookup map for the given keys, so that doing - // query() with keys doesn't become an O(n * m) operation - // lookup values are typically integer indexes, but may - // map to a list of integers, since keys can be duplicated - var lookup = {}; - - for (var i = 0, len = keys.length; i < len; i++) { - var key = processKey(keys[i]); - var val = lookup[key]; - if (typeof val === 'undefined') { - lookup[key] = i; - } else if (typeof val === 'number') { - lookup[key] = [val, i]; - } else { // array - val.push(i); - } - } - - return lookup; -} - -function sortByIdAndValue(a, b) { - // sort by id, then value - var idCompare = collate(a.id, b.id); - return idCompare !== 0 ? idCompare : collate(a.value, b.value); -} -function addAtIndex(idx, result, prelimResults) { - var val = prelimResults[idx]; - if (typeof val === 'undefined') { - prelimResults[idx] = result; - } else if (!Array.isArray(val)) { - // same key for multiple docs, need to preserve document order, so create array - prelimResults[idx] = [val, result]; - } else { // existing array - val.push(result); - } -} - -function sum(values) { - return values.reduce(function (a, b) { - return a + b; - }, 0); -} - -var builtInReduce = { - "_sum": function (keys, values) { - return sum(values); - }, - - "_count": function (keys, values, rereduce) { - return values.length; - }, - - "_stats": function (keys, values) { - return { - 'sum': sum(values), - 'min': Math.min.apply(null, values), - 'max': Math.max.apply(null, values), - 'count': values.length, - 'sumsqr': (function () { - var _sumsqr = 0; - var error; - for (var idx in values) { - if (typeof values[idx] === 'number') { - _sumsqr += values[idx] * values[idx]; - } else { - error = new Error('builtin _stats function requires map values to be numbers'); - error.name = 'invalid_value'; - error.status = 500; - return error; - } - } - return _sumsqr; - })() - }; - } -}; - -function addHttpParam(paramName, opts, params, asJson) { - // add an http param from opts to params, optionally json-encoded - var val = opts[paramName]; - if (typeof val !== 'undefined') { - if (asJson) { - val = encodeURIComponent(JSON.stringify(val)); - } - params.push(paramName + '=' + val); - } -} - -function mapUsingKeys(inputResults, keys, keysLookup) { - // create a new results array from the given array, - // ensuring that the following conditions are respected: - // 1. docs are ordered by key, then doc id - // 2. docs can appear >1 time in the list, if their key is specified >1 time - // 3. keys can be unknown, in which case there's just a hole in the returned array - - var prelimResults = new Array(keys.length); - - inputResults.forEach(function (result) { - var idx = keysLookup[processKey(result.key)]; - if (typeof idx === 'number') { - addAtIndex(idx, result, prelimResults); - } else { // array of indices - idx.forEach(function (subIdx) { - addAtIndex(subIdx, result, prelimResults); - }); - } - }); - - // flatten the array, remove nulls, sort by doc ids - var outputResults = []; - prelimResults.forEach(function (result) { - if (Array.isArray(result)) { - outputResults = outputResults.concat(result.sort(sortByIdAndValue)); - } else { // single result - outputResults.push(result); - } - }); - - return outputResults; -} - -function viewQuery(db, fun, options) { - var origMap; - if (!options.skip) { - options.skip = 0; - } - - if (!fun.reduce) { - options.reduce = false; - } - - var results = []; - var current; - var num_started = 0; - var completed = false; - var keysLookup; - - function emit(key, val) { - var viewRow = { - id: current.doc._id, - key: key, - value: val - }; - - if (typeof options.startkey !== 'undefined' && collate(key, options.startkey) < 0) { - return; - } - if (typeof options.endkey !== 'undefined' && collate(key, options.endkey) > 0) { - return; - } - if (typeof options.key !== 'undefined' && collate(key, options.key) !== 0) { - return; - } - if (typeof options.keys !== 'undefined') { - keysLookup = keysLookup || createKeysLookup(options.keys); - if (typeof keysLookup[processKey(key)] === 'undefined') { - return; - } - } - - num_started++; - if (options.include_docs) { - //in this special case, join on _id (issue #106) - if (val && typeof val === 'object' && val._id) { - db.get(val._id, - function (_, joined_doc) { - if (joined_doc) { - viewRow.doc = joined_doc; - } - results.push(viewRow); - checkComplete(); - }); - return; - } else { - viewRow.doc = current.doc; - } - } - results.push(viewRow); - } - if (typeof fun.map === "function" && fun.map.length === 2) { - //save a reference to it - origMap = fun.map; - fun.map = function (doc) { - //call it with the emit as the second argument - return origMap(doc, emit); - }; - } else { - // ugly way to make sure references to 'emit' in map/reduce bind to the - // above emit - fun.map = evalFunc(fun.map.toString(), emit, sum, log, Array.isArray, JSON.parse); - } - if (fun.reduce) { - if (builtInReduce[fun.reduce]) { - fun.reduce = builtInReduce[fun.reduce]; - } else { - fun.reduce = evalFunc(fun.reduce.toString(), emit, sum, log, Array.isArray, JSON.parse); - } - } - - //only proceed once all documents are mapped and joined - function checkComplete() { - var error; - if (completed && results.length === num_started) { - - if (typeof options.keys !== 'undefined' && results.length) { - // user supplied a keys param, sort by keys - results = mapUsingKeys(results, options.keys, keysLookup); - } else { // normal sorting - results.sort(function (a, b) { - // sort by key, then id - var keyCollate = collate(a.key, b.key); - return keyCollate !== 0 ? keyCollate : collate(a.id, b.id); - }); - } - if (options.descending) { - results.reverse(); - } - if (options.reduce === false) { - return options.complete(null, { - total_rows: results.length, - offset: options.skip, - rows: ('limit' in options) ? results.slice(options.skip, options.limit + options.skip) : - (options.skip > 0) ? results.slice(options.skip) : results - }); - } - - var groups = []; - results.forEach(function (e) { - var last = groups[groups.length - 1]; - if (last && collate(last.key[0][0], e.key) === 0) { - last.key.push([e.key, e.id]); - last.value.push(e.value); - return; - } - groups.push({key: [ - [e.key, e.id] - ], value: [e.value]}); - }); - groups.forEach(function (e) { - e.value = fun.reduce.call(null, e.key, e.value); - if (e.value.sumsqr && e.value.sumsqr instanceof Error) { - error = e.value; - return; - } - e.key = e.key[0][0]; - }); - if (error) { - options.complete(error); - return; - } - options.complete(null, { - total_rows: groups.length, - offset: options.skip, - rows: ('limit' in options) ? groups.slice(options.skip, options.limit + options.skip) : - (options.skip > 0) ? groups.slice(options.skip) : groups - }); - } - } - - db.changes({ - conflicts: true, - include_docs: true, - onChange: function (doc) { - if (!('deleted' in doc) && doc.id[0] !== "_") { - current = {doc: doc.doc}; - fun.map.call(null, doc.doc); - } - }, - complete: function () { - completed = true; - checkComplete(); - } - }); -} - -function httpQuery(db, fun, opts) { - var callback = opts.complete; - - // List of parameters to add to the PUT request - var params = []; - var body; - var method = 'GET'; - - // If opts.reduce exists and is defined, then add it to the list - // of parameters. - // If reduce=false then the results are that of only the map function - // not the final result of map and reduce. - addHttpParam('reduce', opts, params); - addHttpParam('include_docs', opts, params); - addHttpParam('limit', opts, params); - addHttpParam('descending', opts, params); - addHttpParam('group', opts, params); - addHttpParam('group_level', opts, params); - addHttpParam('skip', opts, params); - addHttpParam('startkey', opts, params, true); - addHttpParam('endkey', opts, params, true); - addHttpParam('key', opts, params, true); - - // If keys are supplied, issue a POST request to circumvent GET query string limits - // see http://wiki.apache.org/couchdb/HTTP_view_API#Querying_Options - if (typeof opts.keys !== 'undefined') { - method = 'POST'; - if (typeof fun === 'string') { - body = JSON.stringify({keys: opts.keys}); - } else { // fun is {map : mapfun}, so append to this - fun.keys = opts.keys; - } - } - - // Format the list of parameters into a valid URI query string - params = params.join('&'); - params = params === '' ? '' : '?' + params; - - // We are referencing a query defined in the design doc - if (typeof fun === 'string') { - var parts = fun.split('/'); - db.request({ - method: method, - url: '_design/' + parts[0] + '/_view/' + parts[1] + params, - body: body - }, callback); - return; - } - - // We are using a temporary view, terrible for performance but good for testing - var queryObject = JSON.parse(JSON.stringify(fun, function (key, val) { - if (typeof val === 'function') { - return val + ''; // implicitly `toString` it - } - return val; - })); - - db.request({ - method: 'POST', - url: '_temp_view' + params, - body: queryObject - }, callback); -} - -exports.query = function (fun, opts, callback) { - var db = this; - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - opts = opts || {}; - if (callback) { - opts.complete = callback; - } - var tempCB = opts.complete; - var realCB; - if (opts.complete) { - realCB = function (err, resp) { - process.nextTick(function () { - tempCB(err, resp); - }); - }; - } - var promise = new Promise(function (resolve, reject) { - opts.complete = function (err, data) { - if (err) { - reject(err); - } else { - resolve(data); - } - }; - - if (db.type() === 'http') { - if (typeof fun === 'function') { - return httpQuery(db, {map: fun}, opts); - } - return httpQuery(db, fun, opts); - } - - if (typeof fun === 'object') { - return viewQuery(db, fun, opts); - } - - if (typeof fun === 'function') { - return viewQuery(db, {map: fun}, opts); - } - - var parts = fun.split('/'); - db.get('_design/' + parts[0], function (err, doc) { - if (err) { - opts.complete(err); - return; - } - - if (!doc.views[parts[1]]) { - opts.complete({ name: 'not_found', message: 'missing_named_view' }); - return; - } - viewQuery(db, { - map: doc.views[parts[1]].map, - reduce: doc.views[parts[1]].reduce - }, opts); - }); - }); - if (realCB) { - promise.then(function (resp) { - realCB(null, resp); - }, realCB); - } - return promise; -}; - -}).call(this,_dereq_("/Users/daleharvey/src/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./evalfunc":34,"/Users/daleharvey/src/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":22,"lie":24,"pouchdb-collate":36}],36:[function(_dereq_,module,exports){ -'use strict'; - -exports.collate = function (a, b) { - a = exports.normalizeKey(a); - b = exports.normalizeKey(b); - var ai = collationIndex(a); - var bi = collationIndex(b); - if ((ai - bi) !== 0) { - return ai - bi; - } - if (a === null) { - return 0; - } - if (typeof a === 'number') { - return a - b; - } - if (typeof a === 'boolean') { - return a === b ? 0 : (a < b ? -1 : 1); - } - if (typeof a === 'string') { - return stringCollate(a, b); - } - if (Array.isArray(a)) { - return arrayCollate(a, b); - } - if (typeof a === 'object') { - return objectCollate(a, b); - } -} - -// couch considers null/NaN/Infinity/-Infinity === undefined, -// for the purposes of mapreduce indexes. also, dates get stringified. -exports.normalizeKey = function (key) { - if (typeof key === 'undefined') { - return null; - } else if (typeof key === 'number') { - if (key === Infinity || key === -Infinity || isNaN(key)) { - return null; - } - } else if (key instanceof Date) { - return key.toJSON(); - } - return key; -} - -function arrayCollate(a, b) { - var len = Math.min(a.length, b.length); - for (var i = 0; i < len; i++) { - var sort = exports.collate(a[i], b[i]); - if (sort !== 0) { - return sort; - } - } - return (a.length === b.length) ? 0 : - (a.length > b.length) ? 1 : -1; -} -function stringCollate(a, b) { - // See: https://github.com/daleharvey/pouchdb/issues/40 - // This is incompatible with the CouchDB implementation, but its the - // best we can do for now - return (a === b) ? 0 : ((a > b) ? 1 : -1); -} -function objectCollate(a, b) { - var ak = Object.keys(a), bk = Object.keys(b); - var len = Math.min(ak.length, bk.length); - for (var i = 0; i < len; i++) { - // First sort the keys - var sort = exports.collate(ak[i], bk[i]); - if (sort !== 0) { - return sort; - } - // if the keys are equal sort the values - sort = exports.collate(a[ak[i]], b[bk[i]]); - if (sort !== 0) { - return sort; - } - - } - return (ak.length === bk.length) ? 0 : - (ak.length > bk.length) ? 1 : -1; -} -// The collation is defined by erlangs ordered terms -// the atoms null, true, false come first, then numbers, strings, -// arrays, then objects -// null/undefined/NaN/Infinity/-Infinity are all considered null -function collationIndex(x) { - var id = ['boolean', 'number', 'string', 'object']; - if (id.indexOf(typeof x) !== -1) { - if (x === null) { - return 1; - } - return id.indexOf(typeof x) + 2; - } - if (Array.isArray(x)) { - return 4.5; - } -} - -},{}],37:[function(_dereq_,module,exports){ -module.exports={ - "name": "pouchdb", - "version": "2.0.0", - "description": "PouchDBVersion200 is a pocket-sized database.", - "release": "nightly", - "main": "./lib/index.js", - "homepage": "https://github.com/daleharvey/pouchdb", - "repository": "https://github.com/daleharvey/pouchdb", - "keywords": [ - "db", - "couchdb", - "pouchdb" - ], - "tags": [ - "db", - "couchdb", - "pouchdb" - ], - "dependencies": { - "request": "~2.28.0", - "pouchdb-mapreduce": "1.0.0", - "bluebird": "~1.0.0", - "level-sublevel": "~5.2.0", - "levelup": "~0.18.2", - "leveldown": "~0.10.2", - "inherits": "~2.0.1" - }, - "devDependencies": { - "commander": "~2.1.0", - "watchify": "~0.4.1", - "uglify-js": "~2.4.6", - "jshint": "~2.3.0", - "http-proxy": "~0.10.3", - "corsproxy": "~0.2.13", - "http-server": "~0.5.5", - "browserify": "~3.24.13", - "lie": "~2.5.2", - "wd": "~0.2.8", - "tin": "~0.4.0", - "qunit-mocha-ui": "0.0.5", - "mocha": "~1.17.1", - "chai": "~1.9.0", - "istanbul": "~0.2.4", - "ncp": "~0.5.0" - }, - "scripts": { - "jshint": "jshint -c .jshintrc bin/ lib/ tests/*.js", - "build-js": "browserify lib/index.js -s PouchDBVersion200 -o dist/pouchdb-nightly.js", - "uglify": "uglifyjs dist/pouchdb-nightly.js -mc > dist/pouchdb-nightly.min.js", - "build": "mkdir -p dist && npm run build-js && npm run uglify", - "test-node": "./bin/run-mocha.sh", - "test-browser": "mkdir -p dist && npm run build-js && ./bin/test-browser.js", - "dev": "./bin/dev-server.js", - "test": "npm run jshint && ./bin/run-test.sh", - "publish": "./bin/publish.sh", - "publish-site": "./bin/publish-site.sh" - }, - "browser": { - "./adapters/leveldb": false, - "./deps/buffer": false, - "request": false, - "levelup": false, - "leveldown": false, - "crypto": false, - "bluebird": "lie", - "level-sublevel": false - } -} - -},{}]},{},[13]) -(13) -}); \ No newline at end of file
diff --git a/tests/integration/deps/pouchdb-2.2.0-postfixed.js b/tests/integration/deps/pouchdb-2.2.0-postfixed.js deleted file mode 100644 index b963c6c..0000000 --- a/tests/integration/deps/pouchdb-2.2.0-postfixed.js +++ /dev/null
@@ -1,8733 +0,0 @@ -!function(e){if("object"==typeof exports)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.PouchDBVersion220=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);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ -module.exports = "2.2.0"; - -},{}],2:[function(_dereq_,module,exports){ -"use strict"; - -var utils = _dereq_('./utils'); -var merge = _dereq_('./merge'); -var errors = _dereq_('./deps/errors'); -var EventEmitter = _dereq_('events').EventEmitter; -var upsert = _dereq_('./deps/upsert'); -var Changes = _dereq_('./changes'); -var Promise = utils.Promise; - -/* - * A generic pouch adapter - */ - -// returns first element of arr satisfying callback predicate -function arrayFirst(arr, callback) { - for (var i = 0; i < arr.length; i++) { - if (callback(arr[i], i) === true) { - return arr[i]; - } - } - return false; -} - -// Wrapper for functions that call the bulkdocs api with a single doc, -// if the first result is an error, return an error -function yankError(callback) { - return function (err, results) { - if (err || results[0].error) { - callback(err || results[0]); - } else { - callback(null, results[0]); - } - }; -} - -// for every node in a revision tree computes its distance from the closest -// leaf -function computeHeight(revs) { - var height = {}; - var edges = []; - merge.traverseRevTree(revs, function (isLeaf, pos, id, prnt) { - var rev = pos + "-" + id; - if (isLeaf) { - height[rev] = 0; - } - if (prnt !== undefined) { - edges.push({from: prnt, to: rev}); - } - return rev; - }); - - edges.reverse(); - edges.forEach(function (edge) { - if (height[edge.from] === undefined) { - height[edge.from] = 1 + height[edge.to]; - } else { - height[edge.from] = Math.min(height[edge.from], 1 + height[edge.to]); - } - }); - return height; -} - -function allDocsKeysQuery(api, opts, callback) { - var keys = ('limit' in opts) ? - opts.keys.slice(opts.skip, opts.limit + opts.skip) : - (opts.skip > 0) ? opts.keys.slice(opts.skip) : opts.keys; - if (opts.descending) { - keys.reverse(); - } - if (!keys.length) { - return api._allDocs({limit: 0}, callback); - } - var finalResults = { - offset: opts.skip - }; - return Promise.all(keys.map(function (key, i) { - var subOpts = utils.extend(true, {key: key, deleted: 'ok'}, opts); - ['limit', 'skip', 'keys'].forEach(function (optKey) { - delete subOpts[optKey]; - }); - return new Promise(function (resolve, reject) { - api._allDocs(subOpts, function (err, res) { - if (err) { - return reject(err); - } - finalResults.total_rows = res.total_rows; - resolve(res.rows[0] || {key: key, error: 'not_found'}); - }); - }); - })).then(function (results) { - finalResults.rows = results; - return finalResults; - }); -} - -utils.inherits(AbstractPouchDBVersion220, EventEmitter); -module.exports = AbstractPouchDBVersion220; - -function AbstractPouchDBVersion220() { - var self = this; - EventEmitter.call(this); - self.autoCompact = function (callback) { - if (!self.auto_compaction) { - return callback; - } - return function (err, res) { - if (err) { - callback(err); - } else { - var count = res.length; - var decCount = function () { - count--; - if (!count) { - callback(null, res); - } - }; - res.forEach(function (doc) { - if (doc.ok) { - // TODO: we need better error handling - self.compactDocument(doc.id, 1, decCount); - } else { - decCount(); - } - }); - } - }; - }; - - var listeners = 0, changes; - var eventNames = ['change', 'delete', 'create', 'update']; - this.on('newListener', function (eventName) { - if (~eventNames.indexOf(eventName)) { - if (listeners) { - listeners++; - return; - } else { - listeners++; - } - } else { - return; - } - var lastChange = 0; - changes = this.changes({ - conflicts: true, - include_docs: true, - continuous: true, - since: 'latest', - onChange: function (change) { - if (change.seq <= lastChange) { - return; - } - lastChange = change.seq; - self.emit('change', change); - if (change.doc._deleted) { - self.emit('delete', change); - } else if (change.doc._rev.split('-')[0] === '1') { - self.emit('create', change); - } else { - self.emit('update', change); - } - } - }); - }); - this.on('removeListener', function (eventName) { - if (~eventNames.indexOf(eventName)) { - listeners--; - if (listeners) { - return; - } - } else { - return; - } - changes.cancel(); - }); -} - -AbstractPouchDBVersion220.prototype.post = - utils.adapterFun('post', function (doc, opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - if (typeof doc !== 'object' || Array.isArray(doc)) { - return callback(errors.NOT_AN_OBJECT); - } - this.bulkDocs({docs: [doc]}, opts, - this.autoCompact(yankError(callback))); -}); - -AbstractPouchDBVersion220.prototype.put = - utils.adapterFun('put', utils.getArguments(function (args) { - var temp, temptype, opts, callback; - var doc = args.shift(); - var id = '_id' in doc; - if (typeof doc !== 'object' || Array.isArray(doc)) { - callback = args.pop(); - return callback(errors.NOT_AN_OBJECT); - } - doc = utils.clone(doc); - while (true) { - temp = args.shift(); - temptype = typeof temp; - if (temptype === "string" && !id) { - doc._id = temp; - id = true; - } else if (temptype === "string" && id && !('_rev' in doc)) { - doc._rev = temp; - } else if (temptype === "object") { - opts = temp; - } else if (temptype === "function") { - callback = temp; - } - if (!args.length) { - break; - } - } - opts = opts || {}; - var error = utils.invalidIdError(doc._id); - if (error) { - return callback(error); - } - this.bulkDocs({docs: [doc]}, opts, - this.autoCompact(yankError(callback))); -})); - -AbstractPouchDBVersion220.prototype.putAttachment = - utils.adapterFun('putAttachment', function (docId, attachmentId, rev, - blob, type, callback) { - var api = this; - if (typeof type === 'function') { - callback = type; - type = blob; - blob = rev; - rev = null; - } - if (typeof type === 'undefined') { - type = blob; - blob = rev; - rev = null; - } - - function createAttachment(doc) { - doc._attachments = doc._attachments || {}; - doc._attachments[attachmentId] = { - content_type: type, - data: blob - }; - return api.put(doc); - } - - return api.get(docId).then(function (doc) { - if (doc._rev !== rev) { - throw errors.REV_CONFLICT; - } - - return createAttachment(doc); - }, function (err) { - // create new doc - if (err.error === errors.MISSING_DOC.error) { - return createAttachment({_id: docId}); - } else { - throw err; - } - }); -}); - -AbstractPouchDBVersion220.prototype.removeAttachment = - utils.adapterFun('removeAttachment', function (docId, attachmentId, rev, - callback) { - var self = this; - self.get(docId, function (err, obj) { - if (err) { - callback(err); - return; - } - if (obj._rev !== rev) { - callback(errors.REV_CONFLICT); - return; - } - if (!obj._attachments) { - return callback(); - } - delete obj._attachments[attachmentId]; - if (Object.keys(obj._attachments).length === 0) { - delete obj._attachments; - } - self.put(obj, callback); - }); -}); - -AbstractPouchDBVersion220.prototype.remove = - utils.adapterFun('remove', function (doc, opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } else if (typeof opts === 'string') { - doc = { - _id: doc, - _rev: opts - }; - } else if (opts === undefined) { - opts = {}; - } - opts = utils.clone(opts); - opts.was_delete = true; - var newDoc = {_id: doc._id, _rev: doc._rev}; - newDoc._deleted = true; - this.bulkDocs({docs: [newDoc]}, opts, yankError(callback)); -}); - -AbstractPouchDBVersion220.prototype.revsDiff = - utils.adapterFun('revsDiff', function (req, opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - opts = utils.clone(opts); - var ids = Object.keys(req); - var count = 0; - var missing = {}; - - function addToMissing(id, revId) { - if (!missing[id]) { - missing[id] = {missing: []}; - } - missing[id].missing.push(revId); - } - - function processDoc(id, rev_tree) { - // Is this fast enough? Maybe we should switch to a set simulated by a map - var missingForId = req[id].slice(0); - merge.traverseRevTree(rev_tree, function (isLeaf, pos, revHash, ctx, - opts) { - var rev = pos + '-' + revHash; - var idx = missingForId.indexOf(rev); - if (idx === -1) { - return; - } - - missingForId.splice(idx, 1); - if (opts.status !== 'available') { - addToMissing(id, rev); - } - }); - - // Traversing the tree is synchronous, so now `missingForId` contains - // revisions that were not found in the tree - missingForId.forEach(function (rev) { - addToMissing(id, rev); - }); - } - - ids.map(function (id) { - this._getRevisionTree(id, function (err, rev_tree) { - if (err && err.name === 'not_found' && err.message === 'missing') { - missing[id] = {missing: req[id]}; - } else if (err) { - return callback(err); - } else { - processDoc(id, rev_tree); - } - - if (++count === ids.length) { - return callback(null, missing); - } - }); - }, this); -}); - -// compact one document and fire callback -// by compacting we mean removing all revisions which -// are further from the leaf in revision tree than max_height -AbstractPouchDBVersion220.prototype.compactDocument = - function (docId, max_height, callback) { - var self = this; - this._getRevisionTree(docId, function (err, rev_tree) { - if (err) { - return callback(err); - } - var height = computeHeight(rev_tree); - var candidates = []; - var revs = []; - Object.keys(height).forEach(function (rev) { - if (height[rev] > max_height) { - candidates.push(rev); - } - }); - - merge.traverseRevTree(rev_tree, function (isLeaf, pos, revHash, ctx, opts) { - var rev = pos + '-' + revHash; - if (opts.status === 'available' && candidates.indexOf(rev) !== -1) { - opts.status = 'missing'; - revs.push(rev); - } - }); - self._doCompaction(docId, rev_tree, revs, callback); - }); -}; - -// compact the whole database using single document -// compaction -AbstractPouchDBVersion220.prototype.compact = - utils.adapterFun('compact', function (opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - var self = this; - this.changes({complete: function (err, res) { - if (err) { - callback(); // TODO: silently fail - return; - } - var count = res.results.length; - if (!count) { - callback(); - return; - } - res.results.forEach(function (row) { - self.compactDocument(row.id, 0, function () { - count--; - if (!count) { - callback(); - } - }); - }); - }}); -}); - -/* Begin api wrappers. Specific functionality to storage belongs in the - _[method] */ -AbstractPouchDBVersion220.prototype.get = - utils.adapterFun('get', function (id, opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - if (typeof id !== 'string') { - return callback(errors.INVALID_ID); - } - var leaves = [], self = this; - function finishOpenRevs() { - var result = []; - var count = leaves.length; - if (!count) { - return callback(null, result); - } - // order with open_revs is unspecified - leaves.forEach(function (leaf) { - self.get(id, - {rev: leaf, revs: opts.revs, attachments: opts.attachments}, - function (err, doc) { - if (!err) { - result.push({ok: doc}); - } else { - result.push({missing: leaf}); - } - count--; - if (!count) { - callback(null, result); - } - }); - }); - } - - if (opts.open_revs) { - if (opts.open_revs === "all") { - this._getRevisionTree(id, function (err, rev_tree) { - if (err) { - // if there's no such document we should treat this - // situation the same way as if revision tree was empty - rev_tree = []; - } - leaves = merge.collectLeaves(rev_tree).map(function (leaf) { - return leaf.rev; - }); - finishOpenRevs(); - }); - } else { - if (Array.isArray(opts.open_revs)) { - leaves = opts.open_revs; - for (var i = 0; i < leaves.length; i++) { - var l = leaves[i]; - // looks like it's the only thing couchdb checks - if (!(typeof(l) === "string" && /^\d+-/.test(l))) { - return callback(errors.error(errors.BAD_REQUEST, - "Invalid rev format")); - } - } - finishOpenRevs(); - } else { - return callback(errors.error(errors.UNKNOWN_ERROR, - 'function_clause')); - } - } - return; // open_revs does not like other options - } - - return this._get(id, opts, function (err, result) { - opts = utils.clone(opts); - if (err) { - return callback(err); - } - - var doc = result.doc; - if (!doc) { - // a smoke test for something being very wrong - return callback(new Error('no doc!')); - } - var metadata = result.metadata; - var ctx = result.ctx; - - if (opts.conflicts) { - var conflicts = merge.collectConflicts(metadata); - if (conflicts.length) { - doc._conflicts = conflicts; - } - } - - if (opts.revs || opts.revs_info) { - var paths = merge.rootToLeaf(metadata.rev_tree); - var path = arrayFirst(paths, function (arr) { - return arr.ids.map(function (x) { return x.id; }) - .indexOf(doc._rev.split('-')[1]) !== -1; - }); - - path.ids.splice(path.ids.map(function (x) {return x.id; }) - .indexOf(doc._rev.split('-')[1]) + 1); - path.ids.reverse(); - - if (opts.revs) { - doc._revisions = { - start: (path.pos + path.ids.length) - 1, - ids: path.ids.map(function (rev) { - return rev.id; - }) - }; - } - if (opts.revs_info) { - var pos = path.pos + path.ids.length; - doc._revs_info = path.ids.map(function (rev) { - pos--; - return { - rev: pos + '-' + rev.id, - status: rev.opts.status - }; - }); - } - } - - if (opts.local_seq) { - doc._local_seq = result.metadata.seq; - } - - if (opts.attachments && doc._attachments) { - var attachments = doc._attachments; - var count = Object.keys(attachments).length; - if (count === 0) { - return callback(null, doc); - } - Object.keys(attachments).forEach(function (key) { - this._getAttachment(attachments[key], - {encode: true, ctx: ctx}, function (err, data) { - doc._attachments[key].data = data; - if (!--count) { - callback(null, doc); - } - }); - }, self); - } else { - if (doc._attachments) { - for (var key in doc._attachments) { - if (doc._attachments.hasOwnProperty(key)) { - doc._attachments[key].stub = true; - } - } - } - callback(null, doc); - } - }); -}); - -AbstractPouchDBVersion220.prototype.getAttachment = - utils.adapterFun('getAttachment', function (docId, attachmentId, opts, - callback) { - var self = this; - if (opts instanceof Function) { - callback = opts; - opts = {}; - } - opts = utils.clone(opts); - this._get(docId, opts, function (err, res) { - if (err) { - return callback(err); - } - if (res.doc._attachments && res.doc._attachments[attachmentId]) { - opts.ctx = res.ctx; - self._getAttachment(res.doc._attachments[attachmentId], opts, callback); - } else { - return callback(errors.MISSING_DOC); - } - }); -}); - -AbstractPouchDBVersion220.prototype.allDocs = - utils.adapterFun('allDocs', function (opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - opts = utils.clone(opts); - opts.skip = typeof opts.skip !== 'undefined' ? opts.skip : 0; - if ('keys' in opts) { - if (!Array.isArray(opts.keys)) { - return callback(new TypeError('options.keys must be an array')); - } - var incompatibleOpt = - ['startkey', 'endkey', 'key'].filter(function (incompatibleOpt) { - return incompatibleOpt in opts; - })[0]; - if (incompatibleOpt) { - callback(errors.error(errors.QUERY_PARSE_ERROR, - 'Query parameter `' + incompatibleOpt + - '` is not compatible with multi-get' - )); - return; - } - if (this.type() !== 'http') { - return allDocsKeysQuery(this, opts, callback); - } - } - - return this._allDocs(opts, callback); -}); - -AbstractPouchDBVersion220.prototype.changes = function (opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - return new Changes(this, opts, callback); -}; - -AbstractPouchDBVersion220.prototype.close = - utils.adapterFun('close', function (callback) { - return this._close(callback); -}); - -AbstractPouchDBVersion220.prototype.info = utils.adapterFun('info', function (callback) { - var self = this; - this._info(function (err, info) { - if (err) { - return callback(err); - } - var len = self.prefix.length; - if (info.db_name.length > len && - info.db_name.slice(0, len) === self.prefix) { - info.db_name = info.db_name.slice(len); - } - callback(null, info); - }); -}); - -AbstractPouchDBVersion220.prototype.id = utils.adapterFun('id', function (callback) { - return this._id(callback); -}); - -AbstractPouchDBVersion220.prototype.type = function () { - return (typeof this._type === 'function') ? this._type() : this.adapter; -}; - -AbstractPouchDBVersion220.prototype.bulkDocs = - utils.adapterFun('bulkDocs', function (req, opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - - opts = utils.clone(opts); - - if (Array.isArray(req)) { - req = { - docs: req - }; - } - - if (!req || !req.docs || !Array.isArray(req.docs)) { - return callback(errors.MISSING_BULK_DOCS); - } - - for (var i = 0; i < req.docs.length; ++i) { - if (typeof req.docs[i] !== 'object' || Array.isArray(req.docs[i])) { - return callback(errors.NOT_AN_OBJECT); - } - } - - req = utils.clone(req); - if (!('new_edits' in opts)) { - if ('new_edits' in req) { - opts.new_edits = req.new_edits; - } else { - opts.new_edits = true; - } - } - - return this._bulkDocs(req, opts, this.autoCompact(callback)); -}); - -AbstractPouchDBVersion220.prototype.registerDependentDatabase = - utils.adapterFun('registerDependentDatabase', function (dependentDb, - callback) { - var depDB = new this.constructor(dependentDb, {adapter: this._adapter}); - function diffFun(doc) { - doc.dependentDbs = doc.dependentDbs || {}; - if (doc.dependentDbs[dependentDb]) { - return false; // no update required - } - doc.dependentDbs[dependentDb] = true; - return doc; - } - upsert(this, '_local/_pouch_dependentDbs', diffFun, function (err) { - if (err) { - return callback(err); - } - return callback(null, {db: depDB}); - }); -}); - -},{"./changes":6,"./deps/errors":10,"./deps/upsert":11,"./merge":16,"./utils":21,"events":24}],3:[function(_dereq_,module,exports){ -"use strict"; - -var utils = _dereq_('../utils'); -var errors = _dereq_('../deps/errors'); -// parseUri 1.2.2 -// (c) Steven Levithan <stevenlevithan.com> -// MIT License -function parseUri(str) { - var o = parseUri.options; - var m = o.parser[o.strictMode ? "strict" : "loose"].exec(str); - var uri = {}; - var i = 14; - - while (i--) { - uri[o.key[i]] = m[i] || ""; - } - - uri[o.q.name] = {}; - uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) { - if ($1) { - uri[o.q.name][$1] = $2; - } - }); - - return uri; -} - -function encodeDocId(id) { - if (/^_(design|local)/.test(id)) { - return id; - } - return encodeURIComponent(id); -} - -parseUri.options = { - strictMode: false, - key: ["source", "protocol", "authority", "userInfo", "user", "password", - "host", "port", "relative", "path", "directory", "file", "query", - "anchor"], - q: { - name: "queryKey", - parser: /(?:^|&)([^&=]*)=?([^&]*)/g - }, - parser: { - /* jshint maxlen: false */ - strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, - loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ - } -}; - -// Get all the information you possibly can about the URI given by name and -// return it as a suitable object. -function getHost(name, opts) { - // If the given name contains "http:" - if (/http(s?):/.test(name)) { - // Prase the URI into all its little bits - var uri = parseUri(name); - - // Store the fact that it is a remote URI - uri.remote = true; - - // 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 = 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('/'); - opts = opts || {}; - opts = utils.clone(opts); - uri.headers = opts.headers || {}; - - if (opts.auth || uri.auth) { - var nAuth = opts.auth || uri.auth; - var token = utils.btoa(nAuth.username + ':' + nAuth.password); - uri.headers.Authorization = 'Basic ' + token; - } - - if (opts.headers) { - uri.headers = opts.headers; - } - - return uri; - } - - // If the given name does not contain 'http:' then return a very basic object - // with no host, the current path, the given name as the database name and no - // username/password - return {host: '', path: '/', db: name, auth: false}; -} - -// Generate a URL with the host data given by opts and the given path -function genDBUrl(opts, path) { - return genUrl(opts, opts.db + '/' + path); -} - -// Generate a URL with the host data given by opts and the given path -function genUrl(opts, path) { - if (opts.remote) { - // If the host already has a path, then we need to have a path delimiter - // Otherwise, the path delimiter is the empty string - var pathDel = !opts.path ? '' : '/'; - - // If the host already has a path, then we need to have a path delimiter - // Otherwise, the path delimiter is the empty string - return opts.protocol + '://' + opts.host + ':' + opts.port + '/' + - opts.path + pathDel + path; - } - - return '/' + path; -} -// Implements the PouchDBVersion220 API for dealing with CouchDB instances over HTTP -function HttpPouch(opts, callback) { - // The functions that will be publicly available for HttpPouch - var api = this; - api.getHost = opts.getHost ? opts.getHost : getHost; - - // Parse the URI given by opts.name into an easy-to-use object - var host = api.getHost(opts.name, opts); - - // Generate the database URL based on the host - var dbUrl = genDBUrl(host, ''); - - api.getUrl = function () {return dbUrl; }; - - var ajaxOpts = opts.ajax || {}; - opts = utils.clone(opts); - function ajax(options, callback) { - return utils.ajax(utils.extend({}, ajaxOpts, options), callback); - } - var uuids = { - list: [], - get: function (opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {count: 10}; - } - var cb = function (err, body) { - if (err || !('uuids' in body)) { - callback(err || errors.UNKNOWN_ERROR); - } else { - uuids.list = uuids.list.concat(body.uuids); - callback(null, "OK"); - } - }; - var params = '?count=' + opts.count; - ajax({ - headers: host.headers, - method: 'GET', - url: genUrl(host, '_uuids') + params - }, cb); - } - }; - - // Create a new CouchDB database based on the given opts - var createDB = function () { - ajax({headers: host.headers, method: 'PUT', url: dbUrl}, - function (err, ret) { - // If we get an "Unauthorized" error - if (err && err.status === 401) { - // Test if the database already exists - ajax({headers: host.headers, method: 'HEAD', url: dbUrl}, - function (err, ret) { - // If there is still an error - if (err) { - // Give the error to the callback to deal with - callback(err); - } else { - // Continue as if there had been no errors - callback(null, api); - } - }); - // If there were no errros or if the only error is "Precondition Failed" - // (note: "Precondition Failed" occurs when we try to create a database - // that already exists) - } else if (!err || err.status === 412) { - // Continue as if there had been no errors - callback(null, api); - } else { - callback(err); - } - }); - }; - if (!opts.skipSetup) { - ajax({headers: host.headers, method: 'GET', url: dbUrl}, - function (err, ret) { - //check if the db exists - if (err) { - if (err.status === 404) { - //if it doesn't, create it - createDB(); - } else { - callback(err); - } - } else { - //go do stuff with the db - callback(null, api); - } - }); - } - - api.type = function () { - return 'http'; - }; - - api.id = utils.adapterFun('id', function (callback) { - ajax({ - headers: host.headers, - method: 'GET', - url: genUrl(host, '') - }, function (err, result) { - var uuid = (result && result.uuid) ? - result.uuid + host.db : genDBUrl(host, ''); - callback(null, uuid); - }); - }); - - api.request = utils.adapterFun('request', function (options, callback) { - options.headers = host.headers; - options.url = genDBUrl(host, options.url); - ajax(options, callback); - }); - - // Sends a POST request to the host calling the couchdb _compact function - // version: The version of CouchDB it is running - api.compact = utils.adapterFun('compact', function (opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - opts = utils.clone(opts); - ajax({ - headers: host.headers, - url: genDBUrl(host, '_compact'), - method: 'POST' - }, function () { - function ping() { - api.info(function (err, res) { - if (!res.compact_running) { - callback(); - } else { - setTimeout(ping, opts.interval || 200); - } - }); - } - // Ping the http if it's finished compaction - if (typeof callback === "function") { - ping(); - } - }); - }); - - // Calls GET on the host, which gets back a JSON string containing - // couchdb: A welcome string - // version: The version of CouchDB it is running - api._info = function (callback) { - ajax({ - headers: host.headers, - method: 'GET', - url: genDBUrl(host, '') - }, function (err, res) { - if (err) { - callback(err); - } else { - res.host = genDBUrl(host, ''); - callback(null, res); - } - }); - }; - - // Get the document with the given id from the database given by host. - // The id could be solely the _id in the database, or it may be a - // _design/ID or _local/ID path - api.get = utils.adapterFun('get', function (id, opts, callback) { - // If no options were given, set the callback to the second parameter - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - opts = utils.clone(opts); - if (opts.auto_encode === undefined) { - opts.auto_encode = true; - } - - // List of parameters to add to the GET request - var params = []; - - // If it exists, add the opts.revs value to the list of parameters. - // If revs=true then the resulting JSON will include a field - // _revisions containing an array of the revision IDs. - if (opts.revs) { - params.push('revs=true'); - } - - // If it exists, add the opts.revs_info value to the list of parameters. - // If revs_info=true then the resulting JSON will include the field - // _revs_info containing an array of objects in which each object - // representing an available revision. - if (opts.revs_info) { - params.push('revs_info=true'); - } - - if (opts.local_seq) { - params.push('local_seq=true'); - } - // If it exists, add the opts.open_revs value to the list of parameters. - // If open_revs=all then the resulting JSON will include all the leaf - // revisions. If open_revs=["rev1", "rev2",...] then the resulting JSON - // will contain an array of objects containing data of all revisions - if (opts.open_revs) { - if (opts.open_revs !== "all") { - opts.open_revs = JSON.stringify(opts.open_revs); - } - params.push('open_revs=' + opts.open_revs); - } - - // If it exists, add the opts.attachments value to the list of parameters. - // If attachments=true the resulting JSON will include the base64-encoded - // contents in the "data" property of each attachment. - if (opts.attachments) { - params.push('attachments=true'); - } - - // If it exists, add the opts.rev value to the list of parameters. - // If rev is given a revision number then get the specified revision. - if (opts.rev) { - params.push('rev=' + opts.rev); - } - - // If it exists, add the opts.conflicts value to the list of parameters. - // If conflicts=true then the resulting JSON will include the field - // _conflicts containing all the conflicting revisions. - if (opts.conflicts) { - params.push('conflicts=' + opts.conflicts); - } - - // Format the list of parameters into a valid URI query string - params = params.join('&'); - params = params === '' ? '' : '?' + params; - - if (opts.auto_encode) { - id = encodeDocId(id); - } - - // Set the options for the ajax call - var options = { - headers: host.headers, - method: 'GET', - url: genDBUrl(host, id + params) - }; - - // If the given id contains at least one '/' and the part before the '/' - // is NOT "_design" and is NOT "_local" - // OR - // If the given id contains at least two '/' and the part before the first - // '/' is "_design". - // TODO This second condition seems strange since if parts[0] === '_design' - // then we already know that parts[0] !== '_local'. - var parts = id.split('/'); - if ((parts.length > 1 && parts[0] !== '_design' && parts[0] !== '_local') || - (parts.length > 2 && parts[0] === '_design' && parts[0] !== '_local')) { - // Binary is expected back from the server - options.binary = true; - } - - // Get the document - ajax(options, function (err, doc, xhr) { - // If the document does not exist, send an error to the callback - if (err) { - return callback(err); - } - - // Send the document to the callback - callback(null, doc, xhr); - }); - }); - - // Delete the document given by doc from the database given by host. - api.remove = utils.adapterFun('remove', function (doc, opts, callback) { - // If no options were given, set the callback to be the second parameter - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } else if (typeof opts === 'string') { - doc = { - _id: doc, - _rev: opts - }; - } else if (opts === undefined) { - opts = {}; - } - // Delete the document - ajax({ - headers: host.headers, - method: 'DELETE', - url: genDBUrl(host, encodeDocId(doc._id)) + '?rev=' + doc._rev - }, callback); - }); - - // Get the attachment - api.getAttachment = - utils.adapterFun('getAttachment', function (docId, attachmentId, opts, - callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - opts = utils.clone(opts); - if (opts.auto_encode === undefined) { - opts.auto_encode = true; - } - if (opts.auto_encode) { - docId = encodeDocId(docId); - } - opts.auto_encode = false; - api.get(docId + '/' + attachmentId, opts, callback); - }); - - // Remove the attachment given by the id and rev - api.removeAttachment = - utils.adapterFun('removeAttachment', function (docId, attachmentId, rev, - callback) { - ajax({ - headers: host.headers, - method: 'DELETE', - url: genDBUrl(host, encodeDocId(docId) + '/' + attachmentId) + '?rev=' + - rev - }, callback); - }); - - // Add the attachment given by blob and its contentType property - // to the document with the given id, the revision given by rev, and - // add it to the database given by host. - api.putAttachment = - utils.adapterFun('putAttachment', function (docId, attachmentId, rev, blob, - type, callback) { - if (typeof type === 'function') { - callback = type; - type = blob; - blob = rev; - rev = null; - } - if (typeof type === 'undefined') { - type = blob; - blob = rev; - rev = null; - } - var id = encodeDocId(docId) + '/' + attachmentId; - var url = genDBUrl(host, id); - if (rev) { - url += '?rev=' + rev; - } - - var opts = { - headers: host.headers, - method: 'PUT', - url: url, - processData: false, - body: blob, - timeout: 60000 - }; - opts.headers['Content-Type'] = type; - // Add the attachment - ajax(opts, callback); - }); - - // Add the document given by doc (in JSON string format) to the database - // given by host. This fails if the doc has no _id field. - api.put = utils.adapterFun('put', utils.getArguments(function (args) { - var temp, temptype, opts, callback; - var doc = args.shift(); - var id = '_id' in doc; - if (typeof doc !== 'object' || Array.isArray(doc)) { - callback = args.pop(); - return callback(errors.NOT_AN_OBJECT); - } - doc = utils.clone(doc); - while (true) { - temp = args.shift(); - temptype = typeof temp; - if (temptype === "string" && !id) { - doc._id = temp; - id = true; - } else if (temptype === "string" && id && !('_rev' in doc)) { - doc._rev = temp; - } else if (temptype === "object") { - opts = utils.clone(temp); - } else if (temptype === "function") { - callback = temp; - } - if (!args.length) { - break; - } - } - opts = opts || {}; - var error = utils.invalidIdError(doc._id); - if (error) { - return callback(error); - } - - // List of parameter to add to the PUT request - var params = []; - - // If it exists, add the opts.new_edits value to the list of parameters. - // If new_edits = false then the database will NOT assign this document a - // new revision number - if (opts && typeof opts.new_edits !== 'undefined') { - params.push('new_edits=' + opts.new_edits); - } - - // Format the list of parameters into a valid URI query string - params = params.join('&'); - if (params !== '') { - params = '?' + params; - } - - // Add the document - ajax({ - headers: host.headers, - method: 'PUT', - url: genDBUrl(host, encodeDocId(doc._id)) + params, - body: doc - }, callback); - })); - - // Add the document given by doc (in JSON string format) to the database - // given by host. This does not assume that doc is a new document - // (i.e. does not have a _id or a _rev field.) - api.post = utils.adapterFun('post', function (doc, opts, callback) { - // If no options were given, set the callback to be the second parameter - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - opts = utils.clone(opts); - if (typeof doc !== 'object') { - return callback(errors.NOT_AN_OBJECT); - } - if (! ("_id" in doc)) { - if (uuids.list.length > 0) { - doc._id = uuids.list.pop(); - api.put(doc, opts, callback); - } else { - uuids.get(function (err, resp) { - if (err) { - return callback(errors.UNKNOWN_ERROR); - } - doc._id = uuids.list.pop(); - api.put(doc, opts, callback); - }); - } - } else { - api.put(doc, opts, callback); - } - }); - - // Update/create multiple documents given by req in the database - // given by host. - api._bulkDocs = function (req, opts, callback) { - // If opts.new_edits exists add it to the document data to be - // send to the database. - // If new_edits=false then it prevents the database from creating - // new revision numbers for the documents. Instead it just uses - // the old ones. This is used in database replication. - if (typeof opts.new_edits !== 'undefined') { - req.new_edits = opts.new_edits; - } - - // Update/create the documents - ajax({ - headers: host.headers, - method: 'POST', - url: genDBUrl(host, '_bulk_docs'), - body: req - }, callback); - }; - - // Get a listing of the documents in the database given - // by host and ordered by increasing id. - api.allDocs = utils.adapterFun('allDocs', function (opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - opts = utils.clone(opts); - // List of parameters to add to the GET request - var params = []; - var body; - var method = 'GET'; - - // TODO I don't see conflicts as a valid parameter for a - // _all_docs request - // (see http://wiki.apache.org/couchdb/HTTP_Document_API#all_docs) - if (opts.conflicts) { - params.push('conflicts=true'); - } - - // If opts.descending is truthy add it to params - if (opts.descending) { - params.push('descending=true'); - } - - // If opts.include_docs exists, add the include_docs value to the - // list of parameters. - // If include_docs=true then include the associated document with each - // result. - if (opts.include_docs) { - params.push('include_docs=true'); - } - - if (opts.key) { - params.push('key=' + encodeURIComponent(JSON.stringify(opts.key))); - } - - // If opts.startkey exists, add the startkey value to the list of - // parameters. - // If startkey is given then the returned list of documents will - // start with the document whose id is startkey. - if (opts.startkey) { - params.push('startkey=' + - encodeURIComponent(JSON.stringify(opts.startkey))); - } - - // If opts.endkey exists, add the endkey value to the list of parameters. - // If endkey is given then the returned list of docuemnts will - // end with the document whose id is endkey. - if (opts.endkey) { - params.push('endkey=' + encodeURIComponent(JSON.stringify(opts.endkey))); - } - - if (typeof opts.inclusive_end !== 'undefined') { - params.push('inclusive_end=' + !!opts.inclusive_end); - } - - // If opts.limit exists, add the limit value to the parameter list. - if (typeof opts.limit !== 'undefined') { - params.push('limit=' + opts.limit); - } - - if (typeof opts.skip !== 'undefined') { - params.push('skip=' + opts.skip); - } - - // Format the list of parameters into a valid URI query string - params = params.join('&'); - if (params !== '') { - params = '?' + params; - } - - if (typeof opts.keys !== 'undefined') { - - var MAX_URL_LENGTH = 2000; - // according to http://stackoverflow.com/a/417184/680742, - // the de factor URL length limit is 2000 characters - - var keysAsString = - 'keys=' + encodeURIComponent(JSON.stringify(opts.keys)); - if (keysAsString.length + params.length + 1 <= MAX_URL_LENGTH) { - // If the keys are short enough, do a GET. we do this to work around - // Safari not understanding 304s on POSTs (see issue #1239) - params += (params.indexOf('?') !== -1 ? '&' : '?') + keysAsString; - } else { - // If keys are too long, issue a POST request to circumvent GET - // query string limits - // see http://wiki.apache.org/couchdb/HTTP_view_API#Querying_Options - method = 'POST'; - body = JSON.stringify({keys: opts.keys}); - } - } - - // Get the document listing - ajax({ - headers: host.headers, - method: method, - url: genDBUrl(host, '_all_docs' + params), - body: body - }, callback); - }); - - // Get a list of changes made to documents in the database given by host. - // TODO According to the README, there should be two other methods here, - // api.changes.addListener and api.changes.removeListener. - api._changes = function (opts) { - // We internally page the results of a changes request, this means - // if there is a large set of changes to be returned we can start - // processing them quicker instead of waiting on the entire - // set of changes to return and attempting to process them at once - var CHANGES_LIMIT = 25; - - opts = utils.clone(opts); - opts.timeout = opts.timeout || 0; - - // set timeout to 20s to prevent aborting via Ajax timeout - var params = { timeout: 20 * 1000 }; - var limit = (typeof opts.limit !== 'undefined') ? opts.limit : false; - if (limit === 0) { - limit = 1; - } - var returnDocs; - if ('returnDocs' in opts) { - returnDocs = opts.returnDocs; - } else { - returnDocs = true; - } - // - var leftToFetch = limit; - - if (opts.style) { - params.style = opts.style; - } - - if (opts.include_docs || opts.filter && typeof opts.filter === 'function') { - params.include_docs = true; - } - - if (opts.continuous) { - params.feed = 'longpoll'; - } - - if (opts.conflicts) { - params.conflicts = true; - } - - if (opts.descending) { - params.descending = true; - } - - if (opts.filter && typeof opts.filter === 'string') { - params.filter = opts.filter; - if (opts.filter === '_view' && - opts.view && - typeof opts.view === 'string') { - params.view = opts.view; - } - } - - // If opts.query_params exists, pass it through to the changes request. - // These parameters may be used by the filter on the source database. - if (opts.query_params && typeof opts.query_params === 'object') { - for (var param_name in opts.query_params) { - if (opts.query_params.hasOwnProperty(param_name)) { - params[param_name] = opts.query_params[param_name]; - } - } - } - - var xhr; - var lastFetchedSeq; - - // Get all the changes starting wtih the one immediately after the - // sequence number given by since. - var fetch = function (since, callback) { - if (opts.aborted) { - return; - } - params.since = since; - if (opts.descending) { - if (limit) { - params.limit = leftToFetch; - } - } else { - params.limit = (!limit || leftToFetch > CHANGES_LIMIT) ? - CHANGES_LIMIT : leftToFetch; - } - - var paramStr = '?' + Object.keys(params).map(function (k) { - return k + '=' + params[k]; - }).join('&'); - - // Set the options for the ajax call - var xhrOpts = { - headers: host.headers, - method: 'GET', - url: genDBUrl(host, '_changes' + paramStr), - // _changes can take a long time to generate, especially when filtered - timeout: opts.timeout - }; - lastFetchedSeq = since; - - if (opts.aborted) { - return; - } - - // Get the changes - xhr = ajax(xhrOpts, callback); - }; - - // If opts.since exists, get all the changes from the sequence - // number given by opts.since. Otherwise, get all the changes - // from the sequence number 0. - var fetchTimeout = 10; - var fetchRetryCount = 0; - - var results = {results: []}; - - var fetched = function (err, res) { - if (opts.aborted) { - return; - } - var raw_results_length = 0; - // If the result of the ajax call (res) contains changes (res.results) - if (res && res.results) { - raw_results_length = res.results.length; - results.last_seq = res.last_seq; - // For each change - var req = {}; - req.query = opts.query_params; - res.results = res.results.filter(function (c) { - leftToFetch--; - var ret = utils.filterChange(opts)(c); - if (ret) { - if (returnDocs) { - results.results.push(c); - } - utils.call(opts.onChange, c); - } - return ret; - }); - } else if (err) { - // In case of an error, stop listening for changes and call - // opts.complete - opts.aborted = true; - utils.call(opts.complete, err); - return; - } - - // The changes feed may have timed out with no results - // if so reuse last update sequence - if (res && res.last_seq) { - lastFetchedSeq = res.last_seq; - } - - var finished = (limit && leftToFetch <= 0) || - (res && raw_results_length < CHANGES_LIMIT) || - (opts.descending); - - if ((opts.continuous && !(limit && leftToFetch <= 0)) || !finished) { - // Increase retry delay exponentially as long as errors persist - if (err) { - fetchRetryCount += 1; - } else { - fetchRetryCount = 0; - } - var timeoutMultiplier = 1 << fetchRetryCount; - var retryWait = fetchTimeout * timeoutMultiplier; - var maximumWait = opts.maximumWait || 30000; - - if (retryWait > maximumWait) { - utils.call(opts.complete, err || errors.UNKNOWN_ERROR); - return; - } - - // Queue a call to fetch again with the newest sequence number - setTimeout(function () { fetch(lastFetchedSeq, fetched); }, retryWait); - } else { - // We're done, call the callback - utils.call(opts.complete, null, results); - } - }; - - fetch(opts.since || 0, fetched); - - // Return a method to cancel this method from processing any more - return { - cancel: function () { - opts.aborted = true; - if (xhr) { - xhr.abort(); - } - } - }; - }; - - // Given a set of document/revision IDs (given by req), tets the subset of - // those that do NOT correspond to revisions stored in the database. - // See http://wiki.apache.org/couchdb/HttpPostRevsDiff - api.revsDiff = utils.adapterFun('revsDif', function (req, opts, callback) { - // If no options were given, set the callback to be the second parameter - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - - // Get the missing document/revision IDs - ajax({ - headers: host.headers, - method: 'POST', - url: genDBUrl(host, '_revs_diff'), - body: req - }, function (err, res) { - callback(err, res); - }); - }); - - api.close = utils.adapterFun('close', function (callback) { - callback(); - }); - - function replicateOnServer(target, opts, promise, targetHostUrl) { - opts = utils.clone(opts); - var targetHost = api.getHost(targetHostUrl); - var params = { - source: host.db, - target: targetHost.protocol === host.protocol && - targetHost.authority === - host.authority ? targetHost.db : targetHost.source - }; - - if (opts.continuous) { - params.continuous = true; - } - - if (opts.create_target) { - params.create_target = true; - } - - if (opts.doc_ids) { - params.doc_ids = opts.doc_ids; - } - - if (opts.filter && typeof opts.filter === 'string') { - params.filter = opts.filter; - } - - if (opts.query_params) { - params.query_params = opts.query_params; - } - - var result = {}; - var repOpts = { - headers: host.headers, - method: 'POST', - url: genUrl(host, '_replicate'), - body: params - }; - - var xhr; - promise.cancel = function () { - this.cancelled = true; - if (xhr && !result.ok) { - xhr.abort(); - } - if (result._local_id) { - repOpts.body = { - replication_id: result._local_id - }; - } - repOpts.body.cancel = true; - ajax(repOpts, function (err, resp, xhr) { - // If the replication cancel request fails, send an error to the - // callback - if (err) { - return callback(err); - } - // Send the replication cancel result to the complete callback - utils.call(opts.complete, null, result, xhr); - }); - }; - - if (promise.cancelled) { - return; - } - - xhr = ajax(repOpts, function (err, resp, xhr) { - // If the replication fails, send an error to the callback - if (err) { - return callback(err); - } - - result.ok = true; - - // Provided by CouchDB from 1.2.0 onward to cancel replication - if (resp._local_id) { - result._local_id = resp._local_id; - } - - // Send the replication result to the complete callback - utils.call(opts.complete, null, resp, xhr); - }); - } - - api.replicateOnServer = function (target, opts, promise) { - if (!api.taskqueue.isReady) { - api.taskqueue.addTask('replicateOnServer', [target, opts, promise]); - return promise; - } - target.info(function (err, info) { - replicateOnServer(target, opts, promise, info.host); - }); - }; - api.destroy = utils.adapterFun('destroy', function (callback) { - ajax({ - url: genDBUrl(host, ''), - method: 'DELETE', - headers: host.headers - }, function (err, resp) { - if (err) { - api.emit('error', err); - callback(err); - } else { - api.emit('destroyed'); - callback(null, resp); - } - }); - }); -} - -// Delete the HttpPouch specified by the given name. -HttpPouch.destroy = utils.toPromise(function (name, opts, callback) { - var host = getHost(name, opts); - opts = opts || {}; - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - opts = utils.clone(opts); - opts.headers = host.headers; - opts.method = 'DELETE'; - opts.url = genDBUrl(host, ''); - var ajaxOpts = opts.ajax || {}; - opts = utils.extend({}, opts, ajaxOpts); - utils.ajax(opts, callback); -}); - -// HttpPouch is a valid adapter. -HttpPouch.valid = function () { - return true; -}; - -module.exports = HttpPouch; - -},{"../deps/errors":10,"../utils":21}],4:[function(_dereq_,module,exports){ -(function (global){ -'use strict'; - -var utils = _dereq_('../utils'); -var merge = _dereq_('../merge'); -var errors = _dereq_('../deps/errors'); - -function idbError(callback) { - return function (event) { - callback(errors.error(errors.IDB_ERROR, event.target, event.type)); - }; -} - -function isModernIdb() { - // check for outdated implementations of IDB - // that rely on the setVersion method instead of onupgradeneeded (issue #1207) - - // cache based on appVersion, in case the browser is updated - var cacheKey = "_pouch__checkModernIdb_" + - (global.navigator && global.navigator.appVersion); - var cached = utils.hasLocalStorage() && global.localStorage[cacheKey]; - if (cached) { - return JSON.parse(cached); - } - - var dbName = '_pouch__checkModernIdb'; - var result = global.indexedDB.open(dbName, 1).onupgradeneeded === null; - - if (global.indexedDB.deleteDatabase) { - global.indexedDB.deleteDatabase(dbName); // db no longer needed - } - if (utils.hasLocalStorage()) { - global.localStorage[cacheKey] = JSON.stringify(result); // cache - } - return result; -} - -function IdbPouch(opts, callback) { - - // IndexedDB requires a versioned database structure, so we use the - // version here to manage migrations. - var ADAPTER_VERSION = 2; - - // The object stores created for each database - // DOC_STORE stores the document meta data, its revision history and state - var DOC_STORE = 'document-store'; - // BY_SEQ_STORE stores a particular version of a document, keyed by its - // sequence id - var BY_SEQ_STORE = 'by-sequence'; - // Where we store attachments - var ATTACH_STORE = 'attach-store'; - // Where we store meta data - var META_STORE = 'meta-store'; - // Where we detect blob support - var DETECT_BLOB_SUPPORT_STORE = 'detect-blob-support'; - - var name = opts.name; - var req = global.indexedDB.open(name, ADAPTER_VERSION); - var docCount = -1; - - if (!('openReqList' in IdbPouch)) { - IdbPouch.openReqList = {}; - } - IdbPouch.openReqList[name] = req; - - var blobSupport = null; - var instanceId = null; - var api = this; - var idb = null; - - req.onupgradeneeded = function (e) { - var db = e.target.result; - if (e.oldVersion < 1) { - // initial schema - createSchema(db); - } - if (e.oldVersion < 2) { - // version 2 adds the deletedOrLocal index - addDeletedOrLocalIndex(e); - } - }; - - function createSchema(db) { - db.createObjectStore(DOC_STORE, {keyPath : 'id'}) - .createIndex('seq', 'seq', {unique: true}); - db.createObjectStore(BY_SEQ_STORE, {autoIncrement: true}) - .createIndex('_doc_id_rev', '_doc_id_rev', {unique: true}); - db.createObjectStore(ATTACH_STORE, {keyPath: 'digest'}); - db.createObjectStore(META_STORE, {keyPath: 'id', autoIncrement: false}); - db.createObjectStore(DETECT_BLOB_SUPPORT_STORE); - } - - function addDeletedOrLocalIndex(e) { - var docStore = e.currentTarget.transaction.objectStore(DOC_STORE); - - docStore.openCursor().onsuccess = function (event) { - var cursor = event.target.result; - if (cursor) { - var metadata = cursor.value; - var deleted = utils.isDeleted(metadata); - var local = utils.isLocalId(metadata.id); - metadata.deletedOrLocal = (deleted || local) ? "1" : "0"; - docStore.put(metadata); - cursor["continue"](); - } else { - docStore.createIndex('deletedOrLocal', - 'deletedOrLocal', {unique : false}); - } - }; - } - - req.onsuccess = function (e) { - - idb = e.target.result; - - idb.onversionchange = function () { - idb.close(); - }; - - var txn = idb.transaction([META_STORE, DETECT_BLOB_SUPPORT_STORE], - 'readwrite'); - - var req = txn.objectStore(META_STORE).get(META_STORE); - - req.onsuccess = function (e) { - - var idStored = false; - var checkSetupComplete = function () { - if (blobSupport === null || !idStored) { - return; - } else { - callback(null, api); - } - }; - - var meta = e.target.result || {id: META_STORE}; - if (name + '_id' in meta) { - instanceId = meta[name + '_id']; - idStored = true; - checkSetupComplete(); - } else { - instanceId = utils.uuid(); - meta[name + '_id'] = instanceId; - txn.objectStore(META_STORE).put(meta).onsuccess = function () { - idStored = true; - checkSetupComplete(); - }; - } - - // detect blob support - try { - txn.objectStore(DETECT_BLOB_SUPPORT_STORE).put(utils.createBlob(), - "key"); - blobSupport = true; - } catch (err) { - blobSupport = false; - } finally { - checkSetupComplete(); - } - }; - }; - - req.onerror = idbError(callback); - - api.type = function () { - return 'idb'; - }; - - api._id = utils.toPromise(function (callback) { - callback(null, instanceId); - }); - - api._bulkDocs = function idb_bulkDocs(req, opts, callback) { - var newEdits = opts.new_edits; - var userDocs = req.docs; - // Parse the docs, give them a sequence number for the result - var docInfos = userDocs.map(function (doc, i) { - var newDoc = utils.parseDoc(doc, newEdits); - newDoc._bulk_seq = i; - return newDoc; - }); - - var docInfoErrors = docInfos.filter(function (docInfo) { - return docInfo.error; - }); - if (docInfoErrors.length) { - return callback(docInfoErrors[0]); - } - - var results = []; - var docsWritten = 0; - - function writeMetaData(e) { - var meta = e.target.result; - meta.updateSeq = (meta.updateSeq || 0) + docsWritten; - txn.objectStore(META_STORE).put(meta); - } - - function processDocs() { - if (!docInfos.length) { - txn.objectStore(META_STORE).get(META_STORE).onsuccess = writeMetaData; - return; - } - var currentDoc = docInfos.shift(); - var req = txn.objectStore(DOC_STORE).get(currentDoc.metadata.id); - req.onsuccess = function process_docRead(event) { - var oldDoc = event.target.result; - if (!oldDoc) { - insertDoc(currentDoc); - } else { - updateDoc(oldDoc, currentDoc); - } - }; - } - - function complete(event) { - var aresults = []; - results.sort(sortByBulkSeq); - results.forEach(function (result) { - delete result._bulk_seq; - if (result.error) { - aresults.push(result); - return; - } - var metadata = result.metadata; - var rev = merge.winningRev(metadata); - - aresults.push({ - ok: true, - id: metadata.id, - rev: rev - }); - - if (utils.isLocalId(metadata.id)) { - return; - } - - IdbPouch.Changes.notify(name); - IdbPouch.Changes.notifyLocalWindows(name); - }); - docCount = -1; // invalidate - callback(null, aresults); - } - - function preprocessAttachment(att, finish) { - if (att.stub) { - return finish(); - } - if (typeof att.data === 'string') { - var data; - try { - data = atob(att.data); - } catch (e) { - var err = errors.error(errors.BAD_ARG, - "Attachments need to be base64 encoded"); - return callback(err); - } - att.digest = 'md5-' + utils.MD5(data); - if (blobSupport) { - var type = att.content_type; - data = utils.fixBinary(data); - att.data = utils.createBlob([data], {type: type}); - } - return finish(); - } - var reader = new FileReader(); - reader.onloadend = function (e) { - var binary = utils.arrayBufferToBinaryString(this.result); - att.digest = 'md5-' + utils.MD5(binary); - if (!blobSupport) { - att.data = btoa(binary); - } - finish(); - }; - reader.readAsArrayBuffer(att.data); - } - - function preprocessAttachments(callback) { - if (!docInfos.length) { - return callback(); - } - - var docv = 0; - docInfos.forEach(function (docInfo) { - var attachments = docInfo.data && docInfo.data._attachments ? - Object.keys(docInfo.data._attachments) : []; - - if (!attachments.length) { - return done(); - } - - var recv = 0; - function attachmentProcessed() { - recv++; - if (recv === attachments.length) { - done(); - } - } - - for (var key in docInfo.data._attachments) { - if (docInfo.data._attachments.hasOwnProperty(key)) { - preprocessAttachment(docInfo.data._attachments[key], - attachmentProcessed); - } - } - }); - - function done() { - docv++; - if (docInfos.length === docv) { - callback(); - } - } - } - - function writeDoc(docInfo, winningRev, deleted, callback) { - var err = null; - var recv = 0; - docInfo.data._id = docInfo.metadata.id; - docInfo.data._rev = docInfo.metadata.rev; - - docsWritten++; - - if (deleted) { - docInfo.data._deleted = true; - } - - var attachments = docInfo.data._attachments ? - Object.keys(docInfo.data._attachments) : []; - - function collectResults(attachmentErr) { - if (!err) { - if (attachmentErr) { - err = attachmentErr; - callback(err); - } else if (recv === attachments.length) { - finish(); - } - } - } - - function attachmentSaved(err) { - recv++; - collectResults(err); - } - - for (var key in docInfo.data._attachments) { - if (!docInfo.data._attachments[key].stub) { - var data = docInfo.data._attachments[key].data; - delete docInfo.data._attachments[key].data; - var digest = docInfo.data._attachments[key].digest; - saveAttachment(docInfo, digest, data, attachmentSaved); - } else { - recv++; - collectResults(); - } - } - - function finish() { - - docInfo.data._doc_id_rev = docInfo.data._id + "::" + docInfo.data._rev; - var index = txn.objectStore(BY_SEQ_STORE).index('_doc_id_rev'); - - index.getKey(docInfo.data._doc_id_rev).onsuccess = function (e) { - - var dataReq = e.target.result ? - txn.objectStore(BY_SEQ_STORE).put(docInfo.data, e.target.result) : - txn.objectStore(BY_SEQ_STORE).put(docInfo.data); - - dataReq.onsuccess = function (e) { - var metadata = docInfo.metadata; - metadata.seq = e.target.result; - // Current _rev is calculated from _rev_tree on read - delete metadata.rev; - var local = utils.isLocalId(metadata.id); - metadata.deletedOrLocal = (deleted || local) ? "1" : "0"; - metadata.winningRev = merge.winningRev(metadata); - var metaDataReq = txn.objectStore(DOC_STORE).put(metadata); - metaDataReq.onsuccess = function () { - delete metadata.deletedOrLocal; - delete metadata.winningRev; - results.push(docInfo); - utils.call(callback); - }; - }; - }; - } - - if (!attachments.length) { - finish(); - } - } - - function updateDoc(oldDoc, docInfo) { - var winningRev = merge.winningRev(docInfo.metadata); - var deleted = utils.isDeleted(docInfo.metadata, winningRev); - - var merged = - merge.merge(oldDoc.rev_tree, docInfo.metadata.rev_tree[0], 1000); - var wasPreviouslyDeleted = utils.isDeleted(oldDoc); - var inConflict = (wasPreviouslyDeleted && deleted && newEdits) || - (!wasPreviouslyDeleted && newEdits && merged.conflicts !== 'new_leaf'); - - if (inConflict) { - results.push(makeErr(errors.REV_CONFLICT, docInfo._bulk_seq)); - return processDocs(); - } - - docInfo.metadata.rev_tree = merged.tree; - - writeDoc(docInfo, winningRev, deleted, processDocs); - } - - function insertDoc(docInfo) { - var winningRev = merge.winningRev(docInfo.metadata); - var deleted = utils.isDeleted(docInfo.metadata, winningRev); - // Cant insert new deleted documents - if ('was_delete' in opts && deleted) { - results.push(errors.MISSING_DOC); - return processDocs(); - } - - writeDoc(docInfo, winningRev, deleted, processDocs); - } - - // Insert sequence number into the error so we can sort later - function makeErr(err, seq) { - err._bulk_seq = seq; - return err; - } - - function saveAttachment(docInfo, digest, data, callback) { - var objectStore = txn.objectStore(ATTACH_STORE); - objectStore.get(digest).onsuccess = function (e) { - var originalRefs = e.target.result && e.target.result.refs || {}; - var ref = [docInfo.metadata.id, docInfo.metadata.rev].join('@'); - var newAtt = { - digest: digest, - body: data, - refs: originalRefs - }; - newAtt.refs[ref] = true; - objectStore.put(newAtt).onsuccess = function (e) { - utils.call(callback); - }; - }; - } - - var txn; - preprocessAttachments(function () { - txn = idb.transaction([DOC_STORE, BY_SEQ_STORE, ATTACH_STORE, META_STORE], - 'readwrite'); - txn.onerror = idbError(callback); - txn.ontimeout = idbError(callback); - txn.oncomplete = complete; - - processDocs(); - }); - }; - - function sortByBulkSeq(a, b) { - return a._bulk_seq - b._bulk_seq; - } - - // First we look up the metadata in the ids database, then we fetch the - // current revision(s) from the by sequence store - api._get = function idb_get(id, opts, callback) { - var doc; - var metadata; - var err; - var txn; - opts = utils.clone(opts); - if (opts.ctx) { - txn = opts.ctx; - } else { - txn = - idb.transaction([DOC_STORE, BY_SEQ_STORE, ATTACH_STORE], 'readonly'); - } - - function finish() { - callback(err, {doc: doc, metadata: metadata, ctx: txn}); - } - - txn.objectStore(DOC_STORE).get(id).onsuccess = function (e) { - metadata = e.target.result; - // we can determine the result here if: - // 1. there is no such document - // 2. the document is deleted and we don't ask about specific rev - // When we ask with opts.rev we expect the answer to be either - // doc (possibly with _deleted=true) or missing error - if (!metadata) { - err = errors.MISSING_DOC; - return finish(); - } - if (utils.isDeleted(metadata) && !opts.rev) { - err = errors.error(errors.MISSING_DOC, "deleted"); - return finish(); - } - var objectStore = txn.objectStore(BY_SEQ_STORE); - - // metadata.winningRev was added later, so older DBs might not have it - var rev = opts.rev || metadata.winningRev || merge.winningRev(metadata); - var key = metadata.id + '::' + rev; - - objectStore.index('_doc_id_rev').get(key).onsuccess = function (e) { - doc = e.target.result; - if (doc && doc._doc_id_rev) { - delete(doc._doc_id_rev); - } - if (!doc) { - err = errors.MISSING_DOC; - return finish(); - } - finish(); - }; - }; - }; - - api._getAttachment = function (attachment, opts, callback) { - var result; - var txn; - opts = utils.clone(opts); - if (opts.ctx) { - txn = opts.ctx; - } else { - txn = - idb.transaction([DOC_STORE, BY_SEQ_STORE, ATTACH_STORE], 'readonly'); - } - var digest = attachment.digest; - var type = attachment.content_type; - - txn.objectStore(ATTACH_STORE).get(digest).onsuccess = function (e) { - var data = e.target.result.body; - if (opts.encode) { - if (blobSupport) { - var reader = new FileReader(); - reader.onloadend = function (e) { - var binary = utils.arrayBufferToBinaryString(this.result); - result = btoa(binary); - callback(null, result); - }; - reader.readAsArrayBuffer(data); - } else { - result = data; - callback(null, result); - } - } else { - if (blobSupport) { - result = data; - } else { - data = utils.fixBinary(atob(data)); - result = utils.createBlob([data], {type: type}); - } - callback(null, result); - } - }; - }; - - function allDocsQuery(totalRows, opts, callback) { - var start = 'startkey' in opts ? opts.startkey : false; - var end = 'endkey' in opts ? opts.endkey : false; - var key = 'key' in opts ? opts.key : false; - var skip = opts.skip || 0; - var limit = typeof opts.limit === 'number' ? opts.limit : -1; - var inclusiveEnd = opts.inclusive_end !== false; - var descending = 'descending' in opts && opts.descending ? 'prev' : null; - - var manualDescEnd = false; - if (descending && start && end) { - // unfortunately IDB has a quirk where IDBKeyRange.bound is invalid if the - // start is less than the end, even in descending mode. Best bet - // is just to handle it manually in that case. - manualDescEnd = end; - end = false; - } - - var keyRange; - try { - keyRange = start && end ? global.IDBKeyRange.bound(start, end, false, - !inclusiveEnd) - : start ? (descending ? global.IDBKeyRange.upperBound(start) - : global.IDBKeyRange.lowerBound(start)) - : end ? (descending ? global.IDBKeyRange.lowerBound(end, !inclusiveEnd) - : global.IDBKeyRange.upperBound(end, !inclusiveEnd)) - : key ? global.IDBKeyRange.only(key) : null; - } catch (e) { - if (e.name === "DataError" && e.code === 0) { - // data error, start is less than end - return callback(null, { - total_rows : totalRows, - offset : opts.skip, - rows : [] - }); - } else { - return callback(errors.error(errors.IDB_ERROR, e.name, e.message)); - } - } - - var transaction = idb.transaction([DOC_STORE, BY_SEQ_STORE], 'readonly'); - transaction.oncomplete = function () { - callback(null, { - total_rows: totalRows, - offset: opts.skip, - rows: results - }); - }; - - var oStore = transaction.objectStore(DOC_STORE); - var oCursor = descending ? oStore.openCursor(keyRange, descending) - : oStore.openCursor(keyRange); - var results = []; - oCursor.onsuccess = function (e) { - if (!e.target.result) { - return; - } - var cursor = e.target.result; - var metadata = cursor.value; - // metadata.winningRev added later, some dbs might be missing it - var winningRev = metadata.winningRev || merge.winningRev(metadata); - - function allDocsInner(metadata, data) { - if (utils.isLocalId(metadata.id)) { - return cursor["continue"](); - } - var doc = { - id: metadata.id, - key: metadata.id, - value: { - rev: winningRev - } - }; - if (opts.include_docs) { - doc.doc = data; - doc.doc._rev = winningRev; - if (doc.doc._doc_id_rev) { - delete(doc.doc._doc_id_rev); - } - if (opts.conflicts) { - doc.doc._conflicts = merge.collectConflicts(metadata); - } - for (var att in doc.doc._attachments) { - if (doc.doc._attachments.hasOwnProperty(att)) { - doc.doc._attachments[att].stub = true; - } - } - } - var deleted = utils.isDeleted(metadata, winningRev); - if (opts.deleted === 'ok') { - // deleted docs are okay with keys_requests - if (deleted) { - doc.value.deleted = true; - doc.doc = null; - } - results.push(doc); - } else if (!deleted && skip-- <= 0) { - if (manualDescEnd && doc.key < manualDescEnd) { - return; - } - results.push(doc); - if (--limit === 0) { - return; - } - } - cursor["continue"](); - } - - if (!opts.include_docs) { - allDocsInner(metadata); - } else { - var index = transaction.objectStore(BY_SEQ_STORE).index('_doc_id_rev'); - var key = metadata.id + "::" + winningRev; - index.get(key).onsuccess = function (event) { - allDocsInner(cursor.value, event.target.result); - }; - } - }; - } - - function countDocs(callback) { - if (docCount !== -1) { - return callback(null, docCount); - } - - var count; - var txn = idb.transaction([DOC_STORE], 'readonly'); - var index = txn.objectStore(DOC_STORE).index('deletedOrLocal'); - index.count(global.IDBKeyRange.only("0")).onsuccess = function (e) { - count = e.target.result; - }; - txn.onerror = idbError(callback); - txn.oncomplete = function () { - docCount = count; - callback(null, docCount); - }; - } - - api._allDocs = function idb_allDocs(opts, callback) { - - // first count the total_rows - countDocs(function (err, totalRows) { - if (err) { - return callback(err); - } - if (opts.limit === 0) { - return callback(null, { - total_rows : totalRows, - offset : opts.skip, - rows : [] - }); - } - allDocsQuery(totalRows, opts, callback); - }); - }; - - api._info = function idb_info(callback) { - - countDocs(function (err, count) { - if (err) { - return callback(err); - } - if (idb === null) { - var error = new Error('db isn\'t open'); - error.id = 'idbNull'; - return callback(error); - } - var updateSeq = 0; - var txn = idb.transaction([META_STORE], 'readonly'); - - txn.objectStore(META_STORE).get(META_STORE).onsuccess = function (e) { - updateSeq = e.target.result && e.target.result.updateSeq || 0; - }; - - txn.oncomplete = function () { - callback(null, { - db_name: name, - doc_count: count, - update_seq: updateSeq - }); - }; - }); - }; - - api._changes = function (opts) { - opts = utils.clone(opts); - - if (opts.continuous) { - var id = name + ':' + utils.uuid(); - IdbPouch.Changes.addListener(name, id, api, opts); - IdbPouch.Changes.notify(name); - return { - cancel: function () { - IdbPouch.Changes.removeListener(name, id); - } - }; - } - - var descending = opts.descending ? 'prev' : null; - var lastSeq = 0; - - // Ignore the `since` parameter when `descending` is true - opts.since = opts.since && !descending ? opts.since : 0; - - var limit = 'limit' in opts ? opts.limit : -1; - if (limit === 0) { - limit = 1; // per CouchDB _changes spec - } - var returnDocs; - if ('returnDocs' in opts) { - returnDocs = opts.returnDocs; - } else { - returnDocs = true; - } - - var results = []; - var numResults = 0; - var filter = utils.filterChange(opts); - - var txn; - - function fetchChanges() { - txn = idb.transaction([DOC_STORE, BY_SEQ_STORE]); - txn.oncomplete = onTxnComplete; - - var req; - - if (descending) { - req = txn.objectStore(BY_SEQ_STORE) - .openCursor(global.IDBKeyRange.lowerBound(opts.since, true), - descending); - } else { - req = txn.objectStore(BY_SEQ_STORE) - .openCursor(global.IDBKeyRange.lowerBound(opts.since, true)); - } - - req.onsuccess = onsuccess; - req.onerror = onerror; - } - - fetchChanges(); - - function onsuccess(event) { - var cursor = event.target.result; - - if (!cursor) { - return; - } - - var doc = cursor.value; - - if (utils.isLocalId(doc._id) || - (opts.doc_ids && opts.doc_ids.indexOf(doc._id) === -1)) { - return cursor["continue"](); - } - - var index = txn.objectStore(DOC_STORE); - index.get(doc._id).onsuccess = function (event) { - var metadata = event.target.result; - - if (lastSeq < metadata.seq) { - lastSeq = metadata.seq; - } - // metadata.winningRev was only added later - var winningRev = metadata.winningRev || merge.winningRev(metadata); - if (doc._rev !== winningRev) { - return cursor["continue"](); - } - - delete doc['_doc_id_rev']; - - var change = opts.processChange(doc, metadata, opts); - change.seq = cursor.key; - if (filter(change)) { - numResults++; - if (returnDocs) { - results.push(change); - } - opts.onChange(change); - } - if (numResults !== limit) { - cursor["continue"](); - } - }; - } - - function onTxnComplete() { - if (!opts.continuous) { - opts.complete(null, { - results: results, - last_seq: lastSeq - }); - } - } - }; - - api._close = function (callback) { - if (idb === null) { - return callback(errors.NOT_OPEN); - } - - // https://developer.mozilla.org/en-US/docs/IndexedDB/IDBDatabase#close - // "Returns immediately and closes the connection in a separate thread..." - idb.close(); - idb = null; - callback(); - }; - - api._getRevisionTree = function (docId, callback) { - var txn = idb.transaction([DOC_STORE], 'readonly'); - var req = txn.objectStore(DOC_STORE).get(docId); - req.onsuccess = function (event) { - var doc = event.target.result; - if (!doc) { - callback(errors.MISSING_DOC); - } else { - callback(null, doc.rev_tree); - } - }; - }; - - // This function removes revisions of document docId - // which are listed in revs and sets this document - // revision to to rev_tree - api._doCompaction = function (docId, rev_tree, revs, callback) { - var txn = idb.transaction([DOC_STORE, BY_SEQ_STORE], 'readwrite'); - - var index = txn.objectStore(DOC_STORE); - index.get(docId).onsuccess = function (event) { - var metadata = event.target.result; - metadata.rev_tree = rev_tree; - - var count = revs.length; - revs.forEach(function (rev) { - var index = txn.objectStore(BY_SEQ_STORE).index('_doc_id_rev'); - var key = docId + "::" + rev; - index.getKey(key).onsuccess = function (e) { - var seq = e.target.result; - if (!seq) { - return; - } - txn.objectStore(BY_SEQ_STORE)['delete'](seq); - - count--; - if (!count) { - txn.objectStore(DOC_STORE).put(metadata); - } - }; - }); - }; - txn.oncomplete = function () { - utils.call(callback); - }; - }; - -} - -IdbPouch.valid = function () { - return global.indexedDB && isModernIdb(); -}; - -IdbPouch.destroy = utils.toPromise(function (name, opts, callback) { - if (!('openReqList' in IdbPouch)) { - IdbPouch.openReqList = {}; - } - IdbPouch.Changes.clearListeners(name); - - //Close open request for "name" database to fix ie delay. - if (IdbPouch.openReqList[name] && IdbPouch.openReqList[name].result) { - IdbPouch.openReqList[name].result.close(); - } - var req = global.indexedDB.deleteDatabase(name); - - req.onsuccess = function () { - //Remove open request from the list. - if (IdbPouch.openReqList[name]) { - IdbPouch.openReqList[name] = null; - } - if (utils.hasLocalStorage()) { - delete global.localStorage[name]; - } - - callback(null, { 'ok': true }); - }; - - req.onerror = idbError(callback); -}); - -IdbPouch.Changes = new utils.Changes(); - -module.exports = IdbPouch; - -}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../deps/errors":10,"../merge":16,"../utils":21}],5:[function(_dereq_,module,exports){ -(function (global){ -'use strict'; - -var utils = _dereq_('../utils'); -var merge = _dereq_('../merge'); -var errors = _dereq_('../deps/errors'); -function quote(str) { - return "'" + str + "'"; -} - -var cachedDatabases = {}; - -var openDB = utils.getArguments(function (args) { - if (typeof global !== 'undefined') { - if (global.navigator && global.navigator.sqlitePlugin && - global.navigator.sqlitePlugin.openDatabase) { - return navigator.sqlitePlugin.openDatabase - .apply(navigator.sqlitePlugin, args); - } else if (global.sqlitePlugin && global.sqlitePlugin.openDatabase) { - return global.sqlitePlugin.openDatabase - .apply(global.sqlitePlugin, args); - } else { - var db = cachedDatabases[args[0]]; - if (!db) { - db = cachedDatabases[args[0]] = - global.openDatabase.apply(global, args); - } - return db; - } - } -}); - -var POUCH_VERSION = 1; -var POUCH_SIZE = 3000000; -var ADAPTER_VERSION = 2; // used to manage migrations - -// The object stores created for each database -// DOC_STORE stores the document meta data, its revision history and state -var DOC_STORE = quote('document-store'); -// BY_SEQ_STORE stores a particular version of a document, keyed by its -// sequence id -var BY_SEQ_STORE = quote('by-sequence'); -// Where we store attachments -var ATTACH_STORE = quote('attach-store'); -var META_STORE = quote('metadata-store'); - -// these indexes cover the ground for most allDocs queries -var BY_SEQ_STORE_DELETED_INDEX_SQL = - 'CREATE INDEX IF NOT EXISTS \'by-seq-deleted-idx\' ON ' + - BY_SEQ_STORE + ' (seq, deleted)'; -var DOC_STORE_LOCAL_INDEX_SQL = - 'CREATE INDEX IF NOT EXISTS \'doc-store-local-idx\' ON ' + - DOC_STORE + ' (local, id)'; -var DOC_STORE_WINNINGSEQ_INDEX_SQL = - 'CREATE INDEX IF NOT EXISTS \'doc-winningseq-idx\' ON ' + - DOC_STORE + ' (winningseq)'; - -var DOC_STORE_AND_BY_SEQ_JOINER = BY_SEQ_STORE + - '.seq = ' + DOC_STORE + '.winningseq'; - -var SELECT_DOCS = BY_SEQ_STORE + '.seq AS seq, ' + - BY_SEQ_STORE + '.deleted AS deleted, ' + - BY_SEQ_STORE + '.json AS data, ' + - DOC_STORE + '.json AS metadata'; - -function select(selector, table, joiner, where, orderBy) { - return 'SELECT ' + selector + ' FROM ' + - (typeof table === 'string' ? table : table.join(' JOIN ')) + - (joiner ? (' ON ' + joiner) : '') + - (where ? (' WHERE ' + - (typeof where === 'string' ? where : where.join(' AND '))) : '') + - (orderBy ? (' ORDER BY ' + orderBy) : ''); -} - -function unknownError(callback) { - return function (event) { - // event may actually be a SQLError object, so report is as such - var errorNameMatch = event && event.constructor.toString() - .match(/function ([^\(]+)/); - var errorName = (errorNameMatch && errorNameMatch[1]) || event.type; - var errorReason = event.target || event.message; - callback(errors.error(errors.WSQ_ERROR, errorReason, errorName)); - }; -} -function decodeUtf8(str) { - return decodeURIComponent(window.escape(str)); -} -function parseHexString(str, encoding) { - var result = ''; - var charWidth = encoding === 'UTF-8' ? 2 : 4; - for (var i = 0, len = str.length; i < len; i += charWidth) { - var substring = str.substring(i, i + charWidth); - if (charWidth === 4) { // UTF-16, twiddle the bits - substring = substring.substring(2, 4) + substring.substring(0, 2); - } - result += String.fromCharCode(parseInt(substring, 16)); - } - result = encoding === 'UTF-8' ? decodeUtf8(result) : result; - return result; -} - -function WebSqlPouch(opts, callback) { - var api = this; - var instanceId = null; - var name = opts.name; - var idRequests = []; - var docCount = -1; // cache sqlite count(*) for performance - var encoding; - - var db = openDB(name, POUCH_VERSION, name, POUCH_SIZE); - if (!db) { - return callback(errors.UNKNOWN_ERROR); - } else if (typeof db.readTransaction !== 'function') { - // doesn't exist in sqlite plugin - db.readTransaction = db.transaction; - } - - function dbCreated() { - // note the db name in case the browser upgrades to idb - if (utils.hasLocalStorage()) { - global.localStorage['_pouch__websqldb_' + name] = true; - } - callback(null, api); - } - - // In this migration, we added the 'deleted' and 'local' columns to the - // by-seq and doc store tables. - // To preserve existing user data, we re-process all the existing JSON - // and add these values. - // Called migration2 because it corresponds to adapter version (db_version) #2 - function runMigration2(tx) { - // index used for the join in the allDocs query - tx.executeSql(DOC_STORE_WINNINGSEQ_INDEX_SQL); - - tx.executeSql('ALTER TABLE ' + BY_SEQ_STORE + - ' ADD COLUMN deleted TINYINT(1) DEFAULT 0', [], function () { - tx.executeSql(BY_SEQ_STORE_DELETED_INDEX_SQL); - tx.executeSql('ALTER TABLE ' + DOC_STORE + - ' ADD COLUMN local TINYINT(1) DEFAULT 0', [], function () { - tx.executeSql(DOC_STORE_LOCAL_INDEX_SQL); - - var sql = 'SELECT ' + DOC_STORE + '.winningseq AS seq, ' + DOC_STORE + - '.json AS metadata FROM ' + BY_SEQ_STORE + ' JOIN ' + DOC_STORE + - ' ON ' + BY_SEQ_STORE + '.seq = ' + DOC_STORE + '.winningseq'; - - tx.executeSql(sql, [], function (tx, result) { - - var deleted = []; - var local = []; - - for (var i = 0; i < result.rows.length; i++) { - var item = result.rows.item(i); - var seq = item.seq; - var metadata = JSON.parse(item.metadata); - if (utils.isDeleted(metadata)) { - deleted.push(seq); - } - if (utils.isLocalId(metadata.id)) { - local.push(metadata.id); - } - } - - tx.executeSql('UPDATE ' + DOC_STORE + 'SET local = 1 WHERE id IN (' + - local.map(function () { - return '?'; - }).join(',') + ')', local); - tx.executeSql('UPDATE ' + BY_SEQ_STORE + - ' SET deleted = 1 WHERE seq IN (' + deleted.map(function () { - return '?'; - }).join(',') + ')', deleted); - }); - }); - }); - } - - function onGetInstanceId(tx) { - while (idRequests.length > 0) { - var idCallback = idRequests.pop(); - idCallback(null, instanceId); - } - checkDbEncoding(tx); - } - - function checkDbEncoding(tx) { - // check db encoding - utf-8 (chrome, opera) or utf-16 (safari)? - tx.executeSql('SELECT dbid, hex(dbid) AS hexId FROM ' + META_STORE, [], - function (err, result) { - var id = result.rows.item(0).dbid; - var hexId = result.rows.item(0).hexId; - encoding = (hexId.length === id.length * 2) ? 'UTF-8' : 'UTF-16'; - } - ); - } - - function onGetVersion(tx, dbVersion) { - if (dbVersion === 0) { - // initial schema - - var meta = 'CREATE TABLE IF NOT EXISTS ' + META_STORE + - ' (update_seq, dbid, db_version INTEGER)'; - var attach = 'CREATE TABLE IF NOT EXISTS ' + ATTACH_STORE + - ' (digest, json, body BLOB)'; - var doc = 'CREATE TABLE IF NOT EXISTS ' + DOC_STORE + - ' (id unique, json, winningseq, local TINYINT(1))'; - var seq = 'CREATE TABLE IF NOT EXISTS ' + BY_SEQ_STORE + - ' (seq INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, ' + - 'doc_id_rev UNIQUE, json, deleted TINYINT(1))'; - - // creates - tx.executeSql(attach); - tx.executeSql(doc, [], function () { - tx.executeSql(DOC_STORE_WINNINGSEQ_INDEX_SQL); - tx.executeSql(DOC_STORE_LOCAL_INDEX_SQL); - }); - tx.executeSql(seq, [], function () { - tx.executeSql(BY_SEQ_STORE_DELETED_INDEX_SQL); - }); - tx.executeSql(meta, [], function () { - // mark the update_seq, db version, and new dbid - var initSeq = 'INSERT INTO ' + META_STORE + - ' (update_seq, db_version, dbid) VALUES (?, ?, ?)'; - instanceId = utils.uuid(); - tx.executeSql(initSeq, [0, ADAPTER_VERSION, instanceId]); - onGetInstanceId(tx); - }); - } else { // version > 0 - - if (dbVersion === 1) { - runMigration2(tx); - // mark the db version within this transaction - tx.executeSql('UPDATE ' + META_STORE + ' SET db_version = ' + - ADAPTER_VERSION); - } // in the future, add more migrations here - - // notify db.id() callers - tx.executeSql('SELECT dbid FROM ' + META_STORE, [], - function (tx, result) { - instanceId = result.rows.item(0).dbid; - onGetInstanceId(tx); - }); - } - } - - function setup() { - - db.transaction(function (tx) { - // first get the version - tx.executeSql('SELECT sql FROM sqlite_master WHERE tbl_name = ' + - META_STORE, [], function (tx, result) { - if (!result.rows.length) { - // database hasn't even been created yet (version 0) - onGetVersion(tx, 0); - } else if (!/db_version/.test(result.rows.item(0).sql)) { - // table was created, but without the new db_version column, - // so add it. - tx.executeSql('ALTER TABLE ' + META_STORE + - ' ADD COLUMN db_version INTEGER', [], function () { - // before version 2, this column didn't even exist - onGetVersion(tx, 1); - }); - } else { // column exists, we can safely get it - tx.executeSql('SELECT db_version FROM ' + META_STORE, [], - function (tx, result) { - var dbVersion = result.rows.item(0).db_version; - onGetVersion(tx, dbVersion); - }); - } - }); - }, unknownError(callback), dbCreated); - } - - if (utils.isCordova() && typeof global !== 'undefined') { - //to wait until custom api is made in pouch.adapters before doing setup - global.addEventListener(name + '_pouch', function cordova_init() { - global.removeEventListener(name + '_pouch', cordova_init, false); - setup(); - }, false); - } else { - setup(); - } - - api.type = function () { - return 'websql'; - }; - - api._id = utils.toPromise(function (callback) { - callback(null, instanceId); - }); - - api._info = function (callback) { - db.readTransaction(function (tx) { - countDocs(tx, function (docCount) { - var sql = 'SELECT update_seq FROM ' + META_STORE; - tx.executeSql(sql, [], function (tx, result) { - var updateSeq = result.rows.item(0).update_seq; - callback(null, { - db_name: name, - doc_count: docCount, - update_seq: updateSeq - }); - }); - }); - }, unknownError(callback)); - }; - - api._bulkDocs = function (req, opts, callback) { - - var newEdits = opts.new_edits; - var userDocs = req.docs; - var docsWritten = 0; - - // Parse the docs, give them a sequence number for the result - var docInfos = userDocs.map(function (doc, i) { - var newDoc = utils.parseDoc(doc, newEdits); - newDoc._bulk_seq = i; - return newDoc; - }); - - var docInfoErrors = docInfos.filter(function (docInfo) { - return docInfo.error; - }); - if (docInfoErrors.length) { - return callback(docInfoErrors[0]); - } - - var tx; - var results = []; - var fetchedDocs = {}; - - function sortByBulkSeq(a, b) { - return a._bulk_seq - b._bulk_seq; - } - - function complete(event) { - var aresults = []; - results.sort(sortByBulkSeq); - results.forEach(function (result) { - delete result._bulk_seq; - if (result.error) { - aresults.push(result); - return; - } - var metadata = result.metadata; - var rev = merge.winningRev(metadata); - - aresults.push({ - ok: true, - id: metadata.id, - rev: rev - }); - - if (utils.isLocalId(metadata.id)) { - return; - } - - docsWritten++; - - WebSqlPouch.Changes.notify(name); - WebSqlPouch.Changes.notifyLocalWindows(name); - }); - - var updateseq = 'SELECT update_seq FROM ' + META_STORE; - tx.executeSql(updateseq, [], function (tx, result) { - var update_seq = result.rows.item(0).update_seq + docsWritten; - var sql = 'UPDATE ' + META_STORE + ' SET update_seq=?'; - tx.executeSql(sql, [update_seq], function () { - callback(null, aresults); - }); - }); - } - - function preprocessAttachment(att, finish) { - if (att.stub) { - return finish(); - } - if (typeof att.data === 'string') { - try { - att.data = atob(att.data); - } catch (e) { - var err = errors.error(errors.BAD_ARG, - "Attachments need to be base64 encoded"); - return callback(err); - } - var data = utils.fixBinary(att.data); - att.data = utils.createBlob([data], {type: att.content_type}); - } - var reader = new FileReader(); - reader.onloadend = function (e) { - var binary = utils.arrayBufferToBinaryString(this.result); - att.data = binary; - att.digest = 'md5-' + utils.MD5(binary); - finish(); - }; - reader.readAsArrayBuffer(att.data); - } - - function preprocessAttachments(callback) { - if (!docInfos.length) { - return callback(); - } - - var docv = 0; - - docInfos.forEach(function (docInfo) { - var attachments = docInfo.data && docInfo.data._attachments ? - Object.keys(docInfo.data._attachments) : []; - var recv = 0; - - if (!attachments.length) { - return done(); - } - - function processedAttachment() { - recv++; - if (recv === attachments.length) { - done(); - } - } - - for (var key in docInfo.data._attachments) { - if (docInfo.data._attachments.hasOwnProperty(key)) { - preprocessAttachment(docInfo.data._attachments[key], - processedAttachment); - } - } - }); - - function done() { - docv++; - if (docInfos.length === docv) { - callback(); - } - } - } - - function writeDoc(docInfo, deleted, callback, isUpdate) { - - function finish() { - var data = docInfo.data; - var doc_id_rev = data._id + "::" + data._rev; - var deletedInt = deleted ? 1 : 0; - var fetchSql = select('seq', BY_SEQ_STORE, null, 'doc_id_rev=?'); - - tx.executeSql(fetchSql, [doc_id_rev], function (err, res) { - var sql, sqlArgs; - if (res.rows.length) { - sql = 'UPDATE ' + BY_SEQ_STORE + - ' SET json=?, deleted=? WHERE doc_id_rev=?;'; - sqlArgs = [JSON.stringify(data), deletedInt, doc_id_rev]; - tx.executeSql(sql, sqlArgs, function (tx) { - dataWritten(tx, res.rows.item(0).seq); - }); - } else { - sql = 'INSERT INTO ' + BY_SEQ_STORE + - ' (doc_id_rev, json, deleted) VALUES (?, ?, ?);'; - sqlArgs = [doc_id_rev, JSON.stringify(data), deletedInt]; - tx.executeSql(sql, sqlArgs, function (tx, result) { - dataWritten(tx, result.insertId); - }); - } - }); - } - - function collectResults(attachmentErr) { - if (!err) { - if (attachmentErr) { - err = attachmentErr; - callback(err); - } else if (recv === attachments.length) { - finish(); - } - } - } - - var err = null; - var recv = 0; - - docInfo.data._id = docInfo.metadata.id; - docInfo.data._rev = docInfo.metadata.rev; - - if (deleted) { - docInfo.data._deleted = true; - } - - var attachments = docInfo.data._attachments ? - Object.keys(docInfo.data._attachments) : []; - - function attachmentSaved(err) { - recv++; - collectResults(err); - } - - for (var key in docInfo.data._attachments) { - if (!docInfo.data._attachments[key].stub) { - var data = docInfo.data._attachments[key].data; - delete docInfo.data._attachments[key].data; - var digest = docInfo.data._attachments[key].digest; - saveAttachment(docInfo, digest, data, attachmentSaved); - } else { - recv++; - collectResults(); - } - } - - if (!attachments.length) { - finish(); - } - - function dataWritten(tx, seq) { - docInfo.metadata.seq = seq; - delete docInfo.metadata.rev; - - var mainRev = merge.winningRev(docInfo.metadata); - - var sql = isUpdate ? - 'UPDATE ' + DOC_STORE + - ' SET json=?, winningseq=(SELECT seq FROM ' + BY_SEQ_STORE + - ' WHERE doc_id_rev=?) WHERE id=?' - : 'INSERT INTO ' + DOC_STORE + - ' (id, winningseq, json, local) VALUES (?, ?, ?, ?);'; - var metadataStr = JSON.stringify(docInfo.metadata); - var key = docInfo.metadata.id + "::" + mainRev; - var local = utils.isLocalId(docInfo.metadata.id) ? 1 : 0; - var params = isUpdate ? - [metadataStr, key, docInfo.metadata.id] : - [docInfo.metadata.id, seq, metadataStr, local]; - tx.executeSql(sql, params, function () { - results.push(docInfo); - callback(); - }); - } - } - - function updateDoc(oldDoc, docInfo) { - var merged = - merge.merge(oldDoc.rev_tree, docInfo.metadata.rev_tree[0], 1000); - var deleted = utils.isDeleted(docInfo.metadata); - var oldDocDeleted = utils.isDeleted(oldDoc); - var inConflict = (oldDocDeleted && deleted && newEdits) || - (!oldDocDeleted && newEdits && merged.conflicts !== 'new_leaf'); - if (inConflict) { - results.push(makeErr(errors.REV_CONFLICT, docInfo._bulk_seq)); - return processDocs(); - } - - docInfo.metadata.rev_tree = merged.tree; - writeDoc(docInfo, deleted, processDocs, true); - } - - function insertDoc(docInfo) { - // Cant insert new deleted documents - var deleted = utils.isDeleted(docInfo.metadata); - if ('was_delete' in opts && deleted) { - results.push(errors.MISSING_DOC); - return processDocs(); - } - writeDoc(docInfo, deleted, processDocs, false); - } - - function processDocs() { - if (!docInfos.length) { - return complete(); - } - var currentDoc = docInfos.shift(); - var id = currentDoc.metadata.id; - if (id in fetchedDocs) { - updateDoc(fetchedDocs[id], currentDoc); - } else { - // if we have newEdits=false then we can update the same - // document twice in a single bulk docs call - fetchedDocs[id] = currentDoc.metadata; - insertDoc(currentDoc); - } - } - - // Insert sequence number into the error so we can sort later - function makeErr(err, seq) { - err._bulk_seq = seq; - return err; - } - - function saveAttachment(docInfo, digest, data, callback) { - var ref = [docInfo.metadata.id, docInfo.metadata.rev].join('@'); - var newAtt = {digest: digest}; - var sql = 'SELECT digest, json FROM ' + ATTACH_STORE + ' WHERE digest=?'; - tx.executeSql(sql, [digest], function (tx, result) { - if (!result.rows.length) { - newAtt.refs = {}; - newAtt.refs[ref] = true; - sql = 'INSERT INTO ' + ATTACH_STORE + - '(digest, json, body) VALUES (?, ?, ?)'; - tx.executeSql(sql, [digest, JSON.stringify(newAtt), data], - function () { - callback(); - }); - } else { - newAtt.refs = JSON.parse(result.rows.item(0).json).refs; - sql = 'UPDATE ' + ATTACH_STORE + ' SET json=?, body=? WHERE digest=?'; - tx.executeSql(sql, [JSON.stringify(newAtt), data, digest], - function () { - callback(); - }); - } - }); - } - - function metadataFetched(tx, results) { - for (var j = 0; j < results.rows.length; j++) { - var row = results.rows.item(j); - var id = parseHexString(row.hexId, encoding); - fetchedDocs[id] = JSON.parse(row.json); - } - processDocs(); - } - - preprocessAttachments(function () { - db.transaction(function (txn) { - tx = txn; - var sql = 'SELECT hex(id) AS hexId, json FROM ' + DOC_STORE + - ' WHERE id IN ' + '(' + - docInfos.map(function () {return '?'; }).join(',') + ')'; - var queryArgs = docInfos.map(function (d) { return d.metadata.id; }); - tx.executeSql(sql, queryArgs, metadataFetched); - }, unknownError(callback), function () { - docCount = -1; - }); - }); - }; - - api._get = function (id, opts, callback) { - opts = utils.clone(opts); - var doc; - var metadata; - var err; - if (!opts.ctx) { - db.readTransaction(function (txn) { - opts.ctx = txn; - api._get(id, opts, callback); - }); - return; - } - var tx = opts.ctx; - - function finish() { - callback(err, {doc: doc, metadata: metadata, ctx: tx}); - } - - var sql; - var sqlArgs; - if (opts.rev) { - sql = select( - SELECT_DOCS, - [DOC_STORE, BY_SEQ_STORE], - null, - [BY_SEQ_STORE + '.doc_id_rev=?', DOC_STORE + '.id=?']); - sqlArgs = [id + '::' + opts.rev, id]; - } else { - sql = select( - SELECT_DOCS, - [DOC_STORE, BY_SEQ_STORE], - DOC_STORE_AND_BY_SEQ_JOINER, - DOC_STORE + '.id=?'); - sqlArgs = [id]; - } - tx.executeSql(sql, sqlArgs, function (a, results) { - if (!results.rows.length) { - err = errors.MISSING_DOC; - return finish(); - } - var item = results.rows.item(0); - metadata = JSON.parse(item.metadata); - if (item.deleted && !opts.rev) { - err = errors.error(errors.MISSING_DOC, 'deleted'); - return finish(); - } - doc = JSON.parse(item.data); - finish(); - }); - }; - - function countDocs(tx, callback) { - - if (docCount !== -1) { - return callback(docCount); - } - - // count the total rows - var sql = select( - 'COUNT(' + DOC_STORE + '.id) AS \'num\'', - [DOC_STORE, BY_SEQ_STORE], - DOC_STORE_AND_BY_SEQ_JOINER, - [BY_SEQ_STORE + '.deleted=0', DOC_STORE + '.local=0']); - - tx.executeSql(sql, [], function (tx, result) { - docCount = result.rows.item(0).num; - callback(docCount); - }); - } - - api._allDocs = function (opts, callback) { - var results = []; - var totalRows; - - var start = 'startkey' in opts ? opts.startkey : false; - var end = 'endkey' in opts ? opts.endkey : false; - var key = 'key' in opts ? opts.key : false; - var descending = 'descending' in opts ? opts.descending : false; - var limit = 'limit' in opts ? opts.limit : -1; - var offset = 'skip' in opts ? opts.skip : 0; - var inclusiveEnd = opts.inclusive_end !== false; - - var sqlArgs = []; - var criteria = [DOC_STORE + '.local = 0']; - - if (key !== false) { - criteria.push(DOC_STORE + '.id = ?'); - sqlArgs.push(key); - } else if (start !== false || end !== false) { - if (start !== false) { - criteria.push(DOC_STORE + '.id ' + (descending ? '<=' : '>=') + ' ?'); - sqlArgs.push(start); - } - if (end !== false) { - var comparator = descending ? '>' : '<'; - if (inclusiveEnd) { - comparator += '='; - } - criteria.push(DOC_STORE + '.id ' + comparator + ' ?'); - sqlArgs.push(end); - } - if (key !== false) { - criteria.push(DOC_STORE + '.id = ?'); - sqlArgs.push(key); - } - } - - if (opts.deleted !== 'ok') { - // report deleted if keys are specified - criteria.push(BY_SEQ_STORE + '.deleted = 0'); - } - - db.readTransaction(function (tx) { - - // first count up the total rows - countDocs(tx, function (count) { - totalRows = count; - - if (limit === 0) { - return; - } - - // then actually fetch the documents - var sql = select( - SELECT_DOCS, - [DOC_STORE, BY_SEQ_STORE], - DOC_STORE_AND_BY_SEQ_JOINER, - criteria, - DOC_STORE + '.id ' + (descending ? 'DESC' : 'ASC') - ); - sql += ' LIMIT ' + limit + ' OFFSET ' + offset; - - tx.executeSql(sql, sqlArgs, function (tx, result) { - for (var i = 0, l = result.rows.length; i < l; i++) { - var item = result.rows.item(i); - var metadata = JSON.parse(item.metadata); - var data = JSON.parse(item.data); - var winningRev = data._rev; - var doc = { - id: metadata.id, - key: metadata.id, - value: {rev: winningRev} - }; - if (opts.include_docs) { - doc.doc = data; - doc.doc._rev = winningRev; - if (opts.conflicts) { - doc.doc._conflicts = merge.collectConflicts(metadata); - } - for (var att in doc.doc._attachments) { - if (doc.doc._attachments.hasOwnProperty(att)) { - doc.doc._attachments[att].stub = true; - } - } - } - if (item.deleted) { - if (opts.deleted === 'ok') { - doc.value.deleted = true; - doc.doc = null; - } else { - continue; - } - } - results.push(doc); - } - }); - }); - }, unknownError(callback), function () { - callback(null, { - total_rows: totalRows, - offset: opts.skip, - rows: results - }); - }); - }; - - api._changes = function (opts) { - opts = utils.clone(opts); - - if (opts.continuous) { - var id = name + ':' + utils.uuid(); - WebSqlPouch.Changes.addListener(name, id, api, opts); - WebSqlPouch.Changes.notify(name); - return { - cancel: function () { - WebSqlPouch.Changes.removeListener(name, id); - } - }; - } - - var descending = opts.descending; - - // Ignore the `since` parameter when `descending` is true - opts.since = opts.since && !descending ? opts.since : 0; - - var limit = 'limit' in opts ? opts.limit : -1; - if (limit === 0) { - limit = 1; // per CouchDB _changes spec - } - - var returnDocs; - if ('returnDocs' in opts) { - returnDocs = opts.returnDocs; - } else { - returnDocs = true; - } - var results = []; - var numResults = 0; - function fetchChanges() { - - var criteria = [ - DOC_STORE + '.winningseq > ' + opts.since, - DOC_STORE + '.local = 0' - ]; - var sqlArgs = []; - if (opts.doc_ids) { - criteria.push(DOC_STORE + '.id IN (' + opts.doc_ids.map(function () { - return '?'; - }).join(',') + ')'); - sqlArgs = opts.doc_ids; - } - - var sql = select(SELECT_DOCS, [DOC_STORE, BY_SEQ_STORE], - DOC_STORE_AND_BY_SEQ_JOINER, criteria, - DOC_STORE + '.winningseq ' + (descending ? 'DESC' : 'ASC')); - - var filter = utils.filterChange(opts); - if (!opts.view && !opts.filter) { - // we can just limit in the query - sql += ' LIMIT ' + limit; - } - - db.readTransaction(function (tx) { - tx.executeSql(sql, sqlArgs, function (tx, result) { - var lastSeq = 0; - for (var i = 0, l = result.rows.length; i < l; i++) { - var res = result.rows.item(i); - var metadata = JSON.parse(res.metadata); - if (lastSeq < res.seq) { - lastSeq = res.seq; - } - var doc = JSON.parse(res.data); - var change = opts.processChange(doc, metadata, opts); - change.seq = res.seq; - if (filter(change)) { - numResults++; - if (returnDocs) { - results.push(change); - } - opts.onChange(change); - } - if (numResults === limit) { - break; - } - } - if (!opts.continuous) { - opts.complete(null, { - results: results, - last_seq: lastSeq - }); - } - }); - }); - } - - fetchChanges(); - }; - - api._close = function (callback) { - //WebSQL databases do not need to be closed - callback(); - }; - - api._getAttachment = function (attachment, opts, callback) { - var res; - var tx = opts.ctx; - var digest = attachment.digest; - var type = attachment.content_type; - var sql = 'SELECT hex(body) as body FROM ' + ATTACH_STORE + - ' WHERE digest=?'; - tx.executeSql(sql, [digest], function (tx, result) { - // sqlite normally stores data as utf8, so even the hex() function - // "encodes" the binary data in utf8/16 before returning it. yet hex() - // is the only way to get the full data, so we do this. - var data = parseHexString(result.rows.item(0).body, encoding); - if (opts.encode) { - res = btoa(data); - } else { - data = utils.fixBinary(data); - res = utils.createBlob([data], {type: type}); - } - callback(null, res); - }); - }; - - api._getRevisionTree = function (docId, callback) { - db.readTransaction(function (tx) { - var sql = 'SELECT json AS metadata FROM ' + DOC_STORE + ' WHERE id = ?'; - tx.executeSql(sql, [docId], function (tx, result) { - if (!result.rows.length) { - callback(errors.MISSING_DOC); - } else { - var data = JSON.parse(result.rows.item(0).metadata); - callback(null, data.rev_tree); - } - }); - }); - }; - - api._doCompaction = function (docId, rev_tree, revs, callback) { - if (!revs.length) { - return callback(); - } - db.transaction(function (tx) { - var sql = 'SELECT json AS metadata FROM ' + DOC_STORE + ' WHERE id = ?'; - tx.executeSql(sql, [docId], function (tx, result) { - if (!result.rows.length) { - return utils.call(callback); - } - var metadata = JSON.parse(result.rows.item(0).metadata); - metadata.rev_tree = rev_tree; - - // websql never calls callback if we do WHERE doc_id_rev IN (...) - var numDone = 0; - revs.forEach(function (rev) { - var docIdRev = docId + '::' + rev; - var sql = 'DELETE FROM ' + BY_SEQ_STORE + ' WHERE doc_id_rev = ?'; - tx.executeSql(sql, [docIdRev], function (tx) { - if (++numDone === revs.length) { - var sql = 'UPDATE ' + DOC_STORE + ' SET json = ? WHERE id = ?'; - tx.executeSql(sql, [JSON.stringify(metadata), docId], - function () { - callback(); - }); - } - }); - }); - }); - }); - }; -} - -WebSqlPouch.valid = function () { - if (typeof global !== 'undefined') { - if (global.navigator && - global.navigator.sqlitePlugin && - global.navigator.sqlitePlugin.openDatabase) { - return true; - } else if (global.sqlitePlugin && global.sqlitePlugin.openDatabase) { - return true; - } else if (global.openDatabase) { - return true; - } - } - return false; -}; - -WebSqlPouch.destroy = utils.toPromise(function (name, opts, callback) { - var db = openDB(name, POUCH_VERSION, name, POUCH_SIZE); - db.transaction(function (tx) { - var stores = [DOC_STORE, BY_SEQ_STORE, ATTACH_STORE, META_STORE]; - stores.forEach(function (store) { - tx.executeSql('DROP TABLE IF EXISTS ' + store, []); - }); - }, unknownError(callback), function () { - if (utils.hasLocalStorage()) { - delete global.localStorage['_pouch__websqldb_' + name]; - delete global.localStorage[name]; - } - callback(null, {'ok': true}); - }); -}); - -WebSqlPouch.Changes = new utils.Changes(); - -module.exports = WebSqlPouch; - -}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../deps/errors":10,"../merge":16,"../utils":21}],6:[function(_dereq_,module,exports){ -'use strict'; -var utils = _dereq_('./utils'); -var merge = _dereq_('./merge'); -var errors = _dereq_('./deps/errors'); -var EE = _dereq_('events').EventEmitter; -var evalFilter = _dereq_('./evalFilter'); -var evalView = _dereq_('./evalView'); -module.exports = Changes; -utils.inherits(Changes, EE); - -function Changes(db, opts, callback) { - EE.call(this); - var self = this; - this.db = db; - opts = opts ? utils.clone(opts) : {}; - var oldComplete = callback || opts.complete || function () {}; - var complete = opts.complete = utils.once(function (err, resp) { - if (err) { - self.emit('error', err); - } else { - self.emit('complete', resp); - } - self.removeAllListeners(); - db.removeListener('destroyed', onDestroy); - }); - if (oldComplete) { - self.on('complete', function (resp) { - oldComplete(null, resp); - }); - self.on('error', function (err) { - oldComplete(err); - }); - } - var oldOnChange = opts.onChange; - if (oldOnChange) { - self.on('change', oldOnChange); - } - function onDestroy() { - self.cancel(); - } - db.once('destroyed', onDestroy); - - opts.onChange = function (change) { - if (opts.isCancelled) { - return; - } - self.emit('change', change); - if (self.startSeq && self.startSeq <= change.seq) { - self.emit('uptodate'); - self.startSeq = false; - } - if (change.deleted) { - self.emit('delete', change); - } else if (change.changes.length === 1 && - change.changes[0].rev.slice(0, 2) === '1-') { - self.emit('create', change); - } else { - self.emit('update', change); - } - }; - - var promise = new utils.Promise(function (fulfill, reject) { - opts.complete = function (err, res) { - if (err) { - reject(err); - } else { - fulfill(res); - } - }; - }); - self.once('cancel', function () { - if (oldOnChange) { - self.removeListener('change', oldOnChange); - } - opts.complete(null, {status: 'cancelled'}); - }); - this.then = promise.then.bind(promise); - this['catch'] = promise['catch'].bind(promise); - this.then(function (result) { - complete(null, result); - }, complete); - - - - if (!db.taskqueue.isReady) { - db.taskqueue.addTask(function () { - if (self.isCancelled) { - self.emit('cancel'); - } else { - self.doChanges(opts); - } - }); - } else { - self.doChanges(opts); - } -} -Changes.prototype.cancel = function () { - this.isCancelled = true; - if (this.db.taskqueue.isReady) { - this.emit('cancel'); - } -}; -function processChange(doc, metadata, opts) { - var changeList = [{rev: doc._rev}]; - if (opts.style === 'all_docs') { - changeList = merge.collectLeaves(metadata.rev_tree) - .map(function (x) { return {rev: x.rev}; }); - } - var change = { - id: metadata.id, - changes: changeList, - doc: doc - }; - - if (utils.isDeleted(metadata, doc._rev)) { - change.deleted = true; - } - if (opts.conflicts) { - change.doc._conflicts = merge.collectConflicts(metadata); - if (!change.doc._conflicts.length) { - delete change.doc._conflicts; - } - } - return change; -} - -Changes.prototype.doChanges = function (opts) { - var self = this; - var callback = opts.complete; - - opts = utils.clone(opts); - if ('live' in opts && !('continuous' in opts)) { - opts.continuous = opts.live; - } - opts.processChange = processChange; - - if (!opts.since) { - opts.since = 0; - } - if (opts.since === 'latest') { - this.db.info().then(function (info) { - if (self.isCancelled) { - callback(null, {status: 'cancelled'}); - return; - } - opts.since = info.update_seq - 1; - self.doChanges(opts); - }, callback); - return; - } - - if (opts.continuous && opts.since !== 'latest') { - this.db.info().then(function (info) { - self.startSeq = info.update_seq - 1; - }, function (err) { - if (err.id === 'idbNull') { - //db closed before this returned - //thats ok - return; - } - throw err; - }); - } - - if (this.db.type() !== 'http' && - opts.filter && typeof opts.filter === 'string') { - return this.filterChanges(opts); - } - - if (!('descending' in opts)) { - opts.descending = false; - } - - // 0 and 1 should return 1 document - opts.limit = opts.limit === 0 ? 1 : opts.limit; - opts.complete = callback; - var newPromise = this.db._changes(opts); - if (newPromise && typeof newPromise.cancel === 'function') { - var cancel = self.cancel; - self.cancel = utils.getArguments(function (args) { - newPromise.cancel(); - cancel.apply(this, args); - }); - } -}; - -Changes.prototype.filterChanges = function (opts) { - var self = this; - var callback = opts.complete; - if (opts.filter === '_view') { - if (!opts.view || typeof opts.view !== 'string') { - var err = new Error('`view` filter parameter is not provided.'); - err.status = errors.BAD_REQUEST.status; - err.name = errors.BAD_REQUEST.name; - err.error = true; - callback(err); - return; - } - // fetch a view from a design doc, make it behave like a filter - var viewName = opts.view.split('/'); - this.db.get('_design/' + viewName[0], function (err, ddoc) { - if (self.isCancelled) { - callback(null, {status: 'cancelled'}); - return; - } - if (err) { - callback(err); - return; - } - if (ddoc && ddoc.views && ddoc.views[viewName[1]]) { - - var filter = evalView(ddoc.views[viewName[1]].map); - opts.filter = filter; - self.doChanges(opts); - return; - } - var msg = ddoc.views ? 'missing json key: ' + viewName[1] : - 'missing json key: views'; - if (!err) { - err = new Error(msg); - err.status = errors.MISSING_DOC.status; - err.name = errors.MISSING_DOC.name; - err.error = true; - } - callback(err); - return; - }); - } else { - // fetch a filter from a design doc - var filterName = opts.filter.split('/'); - this.db.get('_design/' + filterName[0], function (err, ddoc) { - if (self.isCancelled) { - callback(null, {status: 'cancelled'}); - return; - } - if (err) { - callback(err); - return; - } - if (ddoc && ddoc.filters && ddoc.filters[filterName[1]]) { - var filter = evalFilter(ddoc.filters[filterName[1]]); - opts.filter = filter; - self.doChanges(opts); - return; - } else { - var msg = (ddoc && ddoc.filters) ? 'missing json key: ' + filterName[1] - : 'missing json key: filters'; - if (!err) { - err = new Error(msg); - err.status = errors.MISSING_DOC.status; - err.name = errors.MISSING_DOC.name; - err.error = true; - } - callback(err); - return; - } - }); - } -}; -},{"./deps/errors":10,"./evalFilter":13,"./evalView":14,"./merge":16,"./utils":21,"events":24}],7:[function(_dereq_,module,exports){ -(function (global){ -/*globals cordova */ -"use strict"; - -var Adapter = _dereq_('./adapter'); -var utils = _dereq_('./utils'); -var TaskQueue = _dereq_('./taskqueue'); -var Promise = utils.Promise; - -function defaultCallback(err) { - if (err && global.debug) { - console.error(err); - } -} - -utils.inherits(PouchDBVersion220, Adapter); -function PouchDBVersion220(name, opts, callback) { - - if (!(this instanceof PouchDBVersion220)) { - return new PouchDBVersion220(name, opts, callback); - } - var self = this; - if (typeof opts === 'function' || typeof opts === 'undefined') { - callback = opts; - opts = {}; - } - - if (typeof name === 'object') { - opts = name; - name = undefined; - } - if (typeof callback === 'undefined') { - callback = defaultCallback; - } - opts = opts || {}; - var oldCB = callback; - self.auto_compaction = opts.auto_compaction; - self.prefix = PouchDBVersion220.prefix; - Adapter.call(self); - self.taskqueue = new TaskQueue(); - var promise = new Promise(function (fulfill, reject) { - callback = function (err, resp) { - if (err) { - return reject(err); - } - delete resp.then; - fulfill(resp); - }; - - opts = utils.clone(opts); - var originalName = opts.name || name; - var backend, error; - (function () { - try { - - if (typeof originalName !== 'string') { - error = new Error('Missing/invalid DB name'); - error.code = 400; - throw error; - } - - backend = PouchDBVersion220.parseAdapter(originalName, opts); - - opts.originalName = originalName; - opts.name = backend.name; - opts.adapter = opts.adapter || backend.adapter; - self._adapter = opts.adapter; - if (!PouchDBVersion220.adapters[opts.adapter]) { - error = new Error('Adapter is missing'); - error.code = 404; - throw error; - } - - if (!PouchDBVersion220.adapters[opts.adapter].valid()) { - error = new Error('Invalid Adapter'); - error.code = 404; - throw error; - } - } catch (err) { - self.taskqueue.fail(err); - self.changes = utils.toPromise(function (opts) { - if (opts.complete) { - opts.complete(err); - } - }); - } - }()); - if (error) { - return reject(error); // constructor error, see above - } - self.adapter = opts.adapter; - - // needs access to PouchDBVersion220; - self.replicate = {}; - - self.replicate.from = function (url, opts, callback) { - return PouchDBVersion220.replicate(url, self, opts, callback); - }; - - self.replicate.to = function (url, opts, callback) { - return PouchDBVersion220.replicate(self, url, opts, callback); - }; - - self.sync = function (dbName, opts, callback) { - return PouchDBVersion220.sync(self, dbName, opts, callback); - }; - - self.replicate.sync = self.sync; - - self.destroy = utils.adapterFun('destroy', function (callback) { - var self = this; - self.info(function (err, info) { - if (err) { - return callback(err); - } - PouchDBVersion220.destroy(info.db_name, callback); - }); - }); - - PouchDBVersion220.adapters[opts.adapter].call(self, opts, function (err, db) { - if (err) { - if (callback) { - self.taskqueue.fail(err); - callback(err); - } - return; - } - function destructionListener(event) { - if (event === 'destroyed') { - self.emit('destroyed'); - PouchDBVersion220.removeListener(opts.name, destructionListener); - } - } - PouchDBVersion220.on(opts.name, destructionListener); - self.emit('created', self); - PouchDBVersion220.emit('created', opts.originalName); - self.taskqueue.ready(self); - callback(null, self); - - }); - if (opts.skipSetup) { - self.taskqueue.ready(self); - } - - if (utils.isCordova()) { - //to inform websql adapter that we can use api - cordova.fireWindowEvent(opts.name + "_pouch", {}); - } - }); - promise.then(function (resp) { - oldCB(null, resp); - }, oldCB); - self.then = promise.then.bind(promise); - self["catch"] = promise["catch"].bind(promise); - -} - -module.exports = PouchDBVersion220; - -}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./adapter":2,"./taskqueue":20,"./utils":21}],8:[function(_dereq_,module,exports){ -"use strict"; - -var createBlob = _dereq_('./blob.js'); -var errors = _dereq_('./errors'); -var utils = _dereq_("../utils"); - -function ajax(options, adapterCallback) { - - var requestCompleted = false; - var callback = utils.getArguments(function (args) { - if (requestCompleted) { - return; - } - adapterCallback.apply(this, args); - requestCompleted = true; - }); - - if (typeof options === "function") { - callback = options; - options = {}; - } - - options = utils.clone(options); - - var defaultOptions = { - method : "GET", - headers: {}, - json: true, - processData: true, - timeout: 10000, - cache: false - }; - - options = utils.extend(true, defaultOptions, options); - - // cache-buster, specifically designed to work around IE's aggressive caching - // see http://www.dashbay.com/2011/05/internet-explorer-caches-ajax/ - if (options.method === 'GET' && !options.cache) { - var hasArgs = options.url.indexOf('?') !== -1; - options.url += (hasArgs ? '&' : '?') + '_nonce=' + utils.uuid(16); - } - - function onSuccess(obj, resp, cb) { - if (!options.binary && !options.json && options.processData && - typeof obj !== 'string') { - obj = JSON.stringify(obj); - } else if (!options.binary && options.json && typeof obj === 'string') { - try { - obj = JSON.parse(obj); - } catch (e) { - // Probably a malformed JSON from server - return cb(e); - } - } - if (Array.isArray(obj)) { - obj = obj.map(function (v) { - var obj; - if (v.ok) { - return v; - } else if (v.error && v.error === 'conflict') { - obj = errors.REV_CONFLICT; - obj.id = v.id; - return obj; - } else if (v.error && v.error === 'forbidden') { - obj = errors.FORBIDDEN; - obj.id = v.id; - obj.reason = v.reason; - return obj; - } else if (v.missing) { - obj = errors.MISSING_DOC; - obj.missing = v.missing; - return obj; - } else { - return v; - } - }); - } - cb(null, obj, resp); - } - - function onError(err, cb) { - var errParsed, errObj, errType, key; - try { - errParsed = JSON.parse(err.responseText); - //would prefer not to have a try/catch clause - for (key in errors) { - if (errors.hasOwnProperty(key) && - errors[key].name === errParsed.error) { - errType = errors[key]; - break; - } - } - if (!errType) { - errType = errors.UNKNOWN_ERROR; - if (err.status) { - errType.status = err.status; - } - if (err.statusText) { - err.name = err.statusText; - } - } - errObj = errors.error(errType, errParsed.reason); - } catch (e) { - for (var key in errors) { - if (errors.hasOwnProperty(key) && errors[key].status === err.status) { - errType = errors[key]; - break; - } - } - if (!errType) { - errType = errors.UNKNOWN_ERROR; - if (err.status) { - errType.status = err.status; - } - if (err.statusText) { - err.name = err.statusText; - } - } - errObj = errors.error(errType); - } - cb(errObj); - } - - var timer; - var xhr; - if (options.xhr) { - xhr = new options.xhr(); - } else { - xhr = new XMLHttpRequest(); - } - xhr.open(options.method, options.url); - xhr.withCredentials = true; - - if (options.json) { - options.headers.Accept = 'application/json'; - options.headers['Content-Type'] = options.headers['Content-Type'] || - 'application/json'; - if (options.body && - options.processData && - typeof options.body !== "string") { - options.body = JSON.stringify(options.body); - } - } - - if (options.binary) { - xhr.responseType = 'arraybuffer'; - } - - var createCookie = function (name, value, days) { - var expires = ""; - if (days) { - var date = new Date(); - date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); - expires = "; expires=" + date.toGMTString(); - } - document.cookie = name + "=" + value + expires + "; path=/"; - }; - - for (var key in options.headers) { - if (key === 'Cookie') { - var cookie = options.headers[key].split('='); - createCookie(cookie[0], cookie[1], 10); - } else { - xhr.setRequestHeader(key, options.headers[key]); - } - } - - if (!("body" in options)) { - options.body = null; - } - - var abortReq = function () { - if (requestCompleted) { - return; - } - xhr.abort(); - onError(xhr, callback); - }; - - xhr.onreadystatechange = function () { - if (xhr.readyState !== 4 || requestCompleted) { - return; - } - clearTimeout(timer); - if (xhr.status >= 200 && xhr.status < 300) { - var data; - if (options.binary) { - data = createBlob([xhr.response || ''], { - type: xhr.getResponseHeader('Content-Type') - }); - } else { - data = xhr.responseText; - } - onSuccess(data, xhr, callback); - } else { - onError(xhr, callback); - } - }; - - if (options.timeout > 0) { - timer = setTimeout(abortReq, options.timeout); - xhr.onprogress = function () { - clearTimeout(timer); - timer = setTimeout(abortReq, options.timeout); - }; - if (xhr.upload) { // does not exist in ie9 - xhr.upload.onprogress = xhr.onprogress; - } - } - xhr.send(options.body); - return {abort: abortReq}; - -} - -module.exports = ajax; - -},{"../utils":21,"./blob.js":9,"./errors":10}],9:[function(_dereq_,module,exports){ -(function (global){ -"use strict"; - -//Abstracts constructing a Blob object, so it also works in older -//browsers that don't support the native Blob constructor. (i.e. -//old QtWebKit versions, at least). -function createBlob(parts, properties) { - parts = parts || []; - properties = properties || {}; - try { - return new Blob(parts, properties); - } catch (e) { - if (e.name !== "TypeError") { - throw e; - } - var BlobBuilder = global.BlobBuilder || - global.MSBlobBuilder || - global.MozBlobBuilder || - global.WebKitBlobBuilder; - var builder = new BlobBuilder(); - for (var i = 0; i < parts.length; i += 1) { - builder.append(parts[i]); - } - return builder.getBlob(properties.type); - } -} - -module.exports = createBlob; - - -}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],10:[function(_dereq_,module,exports){ -"use strict"; - -function PouchError(opts) { - this.status = opts.status; - this.name = opts.error; - this.message = opts.reason; - this.error = true; -} - -PouchError.prototype__proto__ = Error.prototype; - -PouchError.prototype.toString = function () { - return JSON.stringify({ - status: this.status, - name: this.name, - message: this.message - }); -}; - -exports.UNAUTHORIZED = new PouchError({ - status: 401, - error: 'unauthorized', - reason: "Name or password is incorrect." -}); -exports.MISSING_BULK_DOCS = new PouchError({ - status: 400, - error: 'bad_request', - reason: "Missing JSON list of 'docs'" -}); -exports.MISSING_DOC = new PouchError({ - status: 404, - error: 'not_found', - reason: 'missing' -}); -exports.REV_CONFLICT = new PouchError({ - status: 409, - error: 'conflict', - reason: 'Document update conflict' -}); -exports.INVALID_ID = new PouchError({ - status: 400, - error: 'invalid_id', - reason: '_id field must contain a string' -}); -exports.MISSING_ID = new PouchError({ - status: 412, - error: 'missing_id', - reason: '_id is required for puts' -}); -exports.RESERVED_ID = new PouchError({ - status: 400, - error: 'bad_request', - reason: 'Only reserved document ids may start with underscore.' -}); -exports.NOT_OPEN = new PouchError({ - status: 412, - error: 'precondition_failed', - reason: 'Database not open so cannot close' -}); -exports.UNKNOWN_ERROR = new PouchError({ - status: 500, - error: 'unknown_error', - reason: 'Database encountered an unknown error' -}); -exports.BAD_ARG = new PouchError({ - status: 500, - error: 'badarg', - reason: 'Some query argument is invalid' -}); -exports.INVALID_REQUEST = new PouchError({ - status: 400, - error: 'invalid_request', - reason: 'Request was invalid' -}); -exports.QUERY_PARSE_ERROR = new PouchError({ - status: 400, - error: 'query_parse_error', - reason: 'Some query parameter is invalid' -}); -exports.DOC_VALIDATION = new PouchError({ - status: 500, - error: 'doc_validation', - reason: 'Bad special document member' -}); -exports.BAD_REQUEST = new PouchError({ - status: 400, - error: 'bad_request', - reason: 'Something wrong with the request' -}); -exports.NOT_AN_OBJECT = new PouchError({ - status: 400, - error: 'bad_request', - reason: 'Document must be a JSON object' -}); -exports.DB_MISSING = new PouchError({ - status: 404, - error: 'not_found', - reason: 'Database not found' -}); -exports.IDB_ERROR = new PouchError({ - status: 500, - error: 'indexed_db_went_bad', - reason: 'unknown' -}); -exports.WSQ_ERROR = new PouchError({ - status: 500, - error: 'web_sql_went_bad', - reason: 'unknown' -}); -exports.LDB_ERROR = new PouchError({ - status: 500, - error: 'levelDB_went_went_bad', - reason: 'unknown' -}); -exports.FORBIDDEN = new PouchError({ - status: 403, - error: 'forbidden', - reason: 'Forbidden by design doc validate_doc_update function' -}); -exports.error = function (error, reason, name) { - function CustomPouchError(msg) { - this.message = reason; - if (name) { - this.name = name; - } - } - CustomPouchError.prototype = error; - return new CustomPouchError(reason); -}; - -},{}],11:[function(_dereq_,module,exports){ -'use strict'; -var Promise = _dereq_('../utils').Promise; - -// this is essentially the "update sugar" function from daleharvey/pouchdb#1388 -// the diffFun tells us what delta to apply to the doc. it either returns -// the doc, or false if it doesn't need to do an update after all -function upsert(db, docId, diffFun) { - return new Promise(function (fulfill, reject) { - if (docId && typeof docId === 'object') { - docId = docId._id; - } - if (typeof docId !== 'string') { - return reject(new Error('doc id is required')); - } - - db.get(docId, function (err, doc) { - if (err) { - if (err.name !== 'not_found') { - return reject(err); - } - return fulfill(tryAndPut(db, diffFun({_id : docId}), diffFun)); - } - var newDoc = diffFun(doc); - if (!newDoc) { - return fulfill(doc); - } - fulfill(tryAndPut(db, newDoc, diffFun)); - }); - }); -} - -function tryAndPut(db, doc, diffFun) { - return db.put(doc)["catch"](function (err) { - if (err.name !== 'conflict') { - throw err; - } - return upsert(db, doc, diffFun); - }); -} - -module.exports = function (db, docId, diffFun, cb) { - if (typeof cb === 'function') { - upsert(db, docId, diffFun).then(function (resp) { - cb(null, resp); - }, cb); - } else { - return upsert(db, docId, diffFun); - } -}; - -},{"../utils":21}],12:[function(_dereq_,module,exports){ -"use strict"; - -// BEGIN Math.uuid.js - -/*! -Math.uuid.js (v1.4) -http://www.broofa.com -mailto:robert@broofa.com - -Copyright (c) 2010 Robert Kieffer -Dual licensed under the MIT and GPL licenses. -*/ - -/* - * Generate a random uuid. - * - * USAGE: Math.uuid(length, radix) - * length - the desired number of characters - * radix - the number of allowable values for each character. - * - * EXAMPLES: - * // No arguments - returns RFC4122, version 4 ID - * >>> Math.uuid() - * "92329D39-6F5C-4520-ABFC-AAB64544E172" - * - * // One argument - returns ID of the specified length - * >>> Math.uuid(15) // 15 character ID (default base=62) - * "VcydxgltxrVZSTV" - * - * // Two arguments - returns ID of the specified length, and radix. - * // (Radix must be <= 62) - * >>> Math.uuid(8, 2) // 8 character ID (base=2) - * "01001010" - * >>> Math.uuid(8, 10) // 8 character ID (base=10) - * "47473046" - * >>> Math.uuid(8, 16) // 8 character ID (base=16) - * "098F4D35" - */ -var chars = ( - '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' + - 'abcdefghijklmnopqrstuvwxyz' -).split(''); -function getValue(radix) { - return 0 | Math.random() * radix; -} -function uuid(len, radix) { - radix = radix || chars.length; - var out = ''; - var i = -1; - - if (len) { - // Compact form - while (++i < len) { - out += chars[getValue(radix)]; - } - return out; - } - // rfc4122, version 4 form - // Fill in random data. At i==19 set the high bits of clock sequence as - // per rfc4122, sec. 4.1.5 - while (++i < 36) { - switch (i) { - case 8: - case 13: - case 18: - case 23: - out += '-'; - break; - case 19: - out += chars[(getValue(16) & 0x3) | 0x8]; - break; - default: - out += chars[getValue(16)]; - } - } - - return out; -} - - - -module.exports = uuid; - - -},{}],13:[function(_dereq_,module,exports){ -'use strict'; - -module.exports = evalFilter; -function evalFilter(input) { - /*jshint evil: true */ - return eval([ - '(function () { return ', - input, - ' })()' - ].join('')); -} -},{}],14:[function(_dereq_,module,exports){ -'use strict'; - -module.exports = evalView; -function evalView(input) { - /*jshint evil: true */ - return eval([ - '(function () {', - ' return function (doc) {', - ' var emitted = false;', - ' var emit = function (a, b) {', - ' emitted = true;', - ' };', - ' var view = ' + input + ';', - ' view(doc);', - ' if (emitted) {', - ' return true;', - ' }', - ' }', - '})()' - ].join('\n')); -} -},{}],15:[function(_dereq_,module,exports){ -(function (process){ -"use strict"; - -var PouchDBVersion220 = _dereq_('./setup'); - -module.exports = PouchDBVersion220; - -PouchDBVersion220.ajax = _dereq_('./deps/ajax'); -PouchDBVersion220.extend = _dereq_('extend'); -PouchDBVersion220.utils = _dereq_('./utils'); -PouchDBVersion220.Errors = _dereq_('./deps/errors'); -PouchDBVersion220.replicate = _dereq_('./replicate').replicate; -PouchDBVersion220.sync = _dereq_('./sync'); -PouchDBVersion220.version = _dereq_('./version'); -var httpAdapter = _dereq_('./adapters/http'); -PouchDBVersion220.adapter('http', httpAdapter); -PouchDBVersion220.adapter('https', httpAdapter); - -PouchDBVersion220.adapter('idb', _dereq_('./adapters/idb')); -PouchDBVersion220.adapter('websql', _dereq_('./adapters/websql')); -PouchDBVersion220.plugin(_dereq_('pouchdb-mapreduce')); - -if (!process.browser) { - var ldbAdapter = _dereq_('./adapters/leveldb'); - PouchDBVersion220.adapter('ldb', ldbAdapter); - PouchDBVersion220.adapter('leveldb', ldbAdapter); -} - -}).call(this,_dereq_("/Users/daleharvey/src/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js")) -},{"./adapters/http":3,"./adapters/idb":4,"./adapters/leveldb":23,"./adapters/websql":5,"./deps/ajax":8,"./deps/errors":10,"./replicate":17,"./setup":18,"./sync":19,"./utils":21,"./version":1,"/Users/daleharvey/src/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":25,"extend":26,"pouchdb-mapreduce":48}],16:[function(_dereq_,module,exports){ -'use strict'; -var utils = _dereq_('./utils'); - - -// for a better overview of what this is doing, read: -// https://github.com/apache/couchdb/blob/master/src/couchdb/couch_key_tree.erl -// -// But for a quick intro, CouchDB uses a revision tree to store a documents -// history, A -> B -> C, when a document has conflicts, that is a branch in the -// tree, A -> (B1 | B2 -> C), We store these as a nested array in the format -// -// KeyTree = [Path ... ] -// Path = {pos: position_from_root, ids: Tree} -// Tree = [Key, Opts, [Tree, ...]], in particular single node: [Key, []] - -// Turn a path as a flat array into a tree with a single branch -function pathToTree(path) { - var doc = path.shift(); - var root = [doc.id, doc.opts, []]; - var leaf = root; - var nleaf; - - while (path.length) { - doc = path.shift(); - nleaf = [doc.id, doc.opts, []]; - leaf[2].push(nleaf); - leaf = nleaf; - } - return root; -} - -// Merge two trees together -// The roots of tree1 and tree2 must be the same revision -function mergeTree(in_tree1, in_tree2) { - var queue = [{tree1: in_tree1, tree2: in_tree2}]; - var conflicts = false; - while (queue.length > 0) { - var item = queue.pop(); - var tree1 = item.tree1; - var tree2 = item.tree2; - - if (tree1[1].status || tree2[1].status) { - tree1[1].status = - (tree1[1].status === 'available' || - tree2[1].status === 'available') ? 'available' : 'missing'; - } - - for (var i = 0; i < tree2[2].length; i++) { - if (!tree1[2][0]) { - conflicts = 'new_leaf'; - tree1[2][0] = tree2[2][i]; - continue; - } - - var merged = false; - for (var j = 0; j < tree1[2].length; j++) { - if (tree1[2][j][0] === tree2[2][i][0]) { - queue.push({tree1: tree1[2][j], tree2: tree2[2][i]}); - merged = true; - } - } - if (!merged) { - conflicts = 'new_branch'; - tree1[2].push(tree2[2][i]); - tree1[2].sort(); - } - } - } - return {conflicts: conflicts, tree: in_tree1}; -} - -function doMerge(tree, path, dontExpand) { - var restree = []; - var conflicts = false; - var merged = false; - var res; - - if (!tree.length) { - return {tree: [path], conflicts: 'new_leaf'}; - } - - tree.forEach(function (branch) { - if (branch.pos === path.pos && branch.ids[0] === path.ids[0]) { - // Paths start at the same position and have the same root, so they need - // merged - res = mergeTree(branch.ids, path.ids); - restree.push({pos: branch.pos, ids: res.tree}); - conflicts = conflicts || res.conflicts; - merged = true; - } else if (dontExpand !== true) { - // The paths start at a different position, take the earliest path and - // traverse up until it as at the same point from root as the path we - // want to merge. If the keys match we return the longer path with the - // other merged After stemming we dont want to expand the trees - - var t1 = branch.pos < path.pos ? branch : path; - var t2 = branch.pos < path.pos ? path : branch; - var diff = t2.pos - t1.pos; - - var candidateParents = []; - - var trees = []; - trees.push({ids: t1.ids, diff: diff, parent: null, parentIdx: null}); - while (trees.length > 0) { - var item = trees.pop(); - if (item.diff === 0) { - if (item.ids[0] === t2.ids[0]) { - candidateParents.push(item); - } - continue; - } - if (!item.ids) { - continue; - } - /*jshint loopfunc:true */ - item.ids[2].forEach(function (el, idx) { - trees.push( - {ids: el, diff: item.diff - 1, parent: item.ids, parentIdx: idx}); - }); - } - - var el = candidateParents[0]; - - if (!el) { - restree.push(branch); - } else { - res = mergeTree(el.ids, t2.ids); - el.parent[2][el.parentIdx] = res.tree; - restree.push({pos: t1.pos, ids: t1.ids}); - conflicts = conflicts || res.conflicts; - merged = true; - } - } else { - restree.push(branch); - } - }); - - // We didnt find - if (!merged) { - restree.push(path); - } - - restree.sort(function (a, b) { - return a.pos - b.pos; - }); - - return { - tree: restree, - conflicts: conflicts || 'internal_node' - }; -} - -// To ensure we dont grow the revision tree infinitely, we stem old revisions -function stem(tree, depth) { - // First we break out the tree into a complete list of root to leaf paths, - // we cut off the start of the path and generate a new set of flat trees - var stemmedPaths = PouchMerge.rootToLeaf(tree).map(function (path) { - var stemmed = path.ids.slice(-depth); - return { - pos: path.pos + (path.ids.length - stemmed.length), - ids: pathToTree(stemmed) - }; - }); - // Then we remerge all those flat trees together, ensuring that we dont - // connect trees that would go beyond the depth limit - return stemmedPaths.reduce(function (prev, current, i, arr) { - return doMerge(prev, current, true).tree; - }, [stemmedPaths.shift()]); -} - -var PouchMerge = {}; - -PouchMerge.merge = function (tree, path, depth) { - // Ugh, nicer way to not modify arguments in place? - tree = utils.extend(true, [], tree); - path = utils.clone(path); - var newTree = doMerge(tree, path); - return { - tree: stem(newTree.tree, depth), - conflicts: newTree.conflicts - }; -}; - -// We fetch all leafs of the revision tree, and sort them based on tree length -// and whether they were deleted, undeleted documents with the longest revision -// tree (most edits) win -// The final sort algorithm is slightly documented in a sidebar here: -// http://guide.couchdb.org/draft/conflicts.html -PouchMerge.winningRev = function (metadata) { - var leafs = []; - PouchMerge.traverseRevTree(metadata.rev_tree, - function (isLeaf, pos, id, something, opts) { - if (isLeaf) { - leafs.push({pos: pos, id: id, deleted: !!opts.deleted}); - } - }); - leafs.sort(function (a, b) { - if (a.deleted !== b.deleted) { - return a.deleted > b.deleted ? 1 : -1; - } - if (a.pos !== b.pos) { - return b.pos - a.pos; - } - return a.id < b.id ? 1 : -1; - }); - - return leafs[0].pos + '-' + leafs[0].id; -}; - -// Pretty much all below can be combined into a higher order function to -// traverse revisions -// The return value from the callback will be passed as context to all -// children of that node -PouchMerge.traverseRevTree = function (revs, callback) { - var toVisit = revs.slice(); - - var node; - while ((node = toVisit.pop())) { - var pos = node.pos; - var tree = node.ids; - var branches = tree[2]; - var newCtx = - callback(branches.length === 0, pos, tree[0], node.ctx, tree[1]); - for (var i = 0, len = branches.length; i < len; i++) { - toVisit.push({pos: pos + 1, ids: branches[i], ctx: newCtx}); - } - } -}; - -PouchMerge.collectLeaves = function (revs) { - var leaves = []; - PouchMerge.traverseRevTree(revs, function (isLeaf, pos, id, acc, opts) { - if (isLeaf) { - leaves.unshift({rev: pos + "-" + id, pos: pos, opts: opts}); - } - }); - leaves.sort(function (a, b) { - return b.pos - a.pos; - }); - leaves.map(function (leaf) { delete leaf.pos; }); - return leaves; -}; - -// returns revs of all conflicts that is leaves such that -// 1. are not deleted and -// 2. are different than winning revision -PouchMerge.collectConflicts = function (metadata) { - var win = PouchMerge.winningRev(metadata); - var leaves = PouchMerge.collectLeaves(metadata.rev_tree); - var conflicts = []; - leaves.forEach(function (leaf) { - if (leaf.rev !== win && !leaf.opts.deleted) { - conflicts.push(leaf.rev); - } - }); - return conflicts; -}; - -PouchMerge.rootToLeaf = function (tree) { - var paths = []; - PouchMerge.traverseRevTree(tree, function (isLeaf, pos, id, history, opts) { - history = history ? history.slice(0) : []; - history.push({id: id, opts: opts}); - if (isLeaf) { - var rootPos = pos + 1 - history.length; - paths.unshift({pos: rootPos, ids: history}); - } - return history; - }); - return paths; -}; - - -module.exports = PouchMerge; - -},{"./utils":21}],17:[function(_dereq_,module,exports){ -'use strict'; - -var utils = _dereq_('./utils'); -var Pouch = _dereq_('./index'); -var EE = _dereq_('events').EventEmitter; - -// We create a basic promise so the caller can cancel the replication possibly -// before we have actually started listening to changes etc -utils.inherits(Replication, EE); -function Replication(opts) { - EE.call(this); - this.cancelled = false; - var self = this; - var promise = new utils.Promise(function (fulfill, reject) { - self.once('complete', fulfill); - self.once('error', reject); - }); - self.then = function (resolve, reject) { - return promise.then(resolve, reject); - }; - self["catch"] = function (reject) { - return promise["catch"](reject); - }; -} - -Replication.prototype.cancel = function () { - this.cancelled = true; - this.emit('cancel'); -}; - -Replication.prototype.ready = function (src, target) { - var self = this; - function onDestroy() { - self.cancel(); - } - src.once('destroyed', onDestroy); - target.once('destroyed', onDestroy); - function cleanup() { - self.removeAllListeners(); - src.removeListener('destroyed', onDestroy); - target.removeListener('destroyed', onDestroy); - } - this.then(cleanup, cleanup); -}; - - -// TODO: check CouchDB's replication id generation -// Generate a unique id particular to this replication -function genReplicationId(src, target, opts) { - var filterFun = opts.filter ? opts.filter.toString() : ''; - return src.id().then(function (src_id) { - return target.id().then(function (target_id) { - var queryData = src_id + target_id + filterFun + - JSON.stringify(opts.query_params) + opts.doc_ids; - return '_local/' + utils.MD5(queryData); - }); - }); -} - - -function updateCheckpoint(db, id, checkpoint) { - return db.get(id)["catch"](function (err) { - if (err.status === 404) { - return {_id: id}; - } - throw err; - }).then(function (doc) { - doc.last_seq = checkpoint; - return db.put(doc); - }); - } - -function Checkpointer(src, target, id) { - this.src = src; - this.target = target; - this.id = id; -} - -Checkpointer.prototype.writeCheckpoint = function (checkpoint) { - var self = this; - return this.updateTarget(checkpoint).then(function () { - return self.updateSource(checkpoint); - }); -}; -Checkpointer.prototype.updateTarget = function (checkpoint) { - return updateCheckpoint(this.target, this.id, checkpoint); -}; -Checkpointer.prototype.updateSource = function (checkpoint) { - var self = this; - if (this.readOnlySource) { - return utils.Promise.resolve(true); - } - return updateCheckpoint(this.src, this.id, checkpoint)["catch"](function (err) { - if (err.status === 401) { - self.readOnlySource = true; - return true; - } - throw err; - }); -}; -Checkpointer.prototype.getCheckpoint = function () { - var self = this; - return self.target.get(self.id).then(function (targetDoc) { - return self.src.get(self.id).then(function (sourceDoc) { - if (targetDoc.last_seq === sourceDoc.last_seq) { - return sourceDoc.last_seq; - } - return 0; - }, function (err) { - if (err.status === 404 && targetDoc.last_seq) { - return self.src.put({ - _id: self.id, - last_seq: 0 - }).then(function () { - return 0; - }, function (err) { - if (err.status === 401) { - self.readOnlySource = true; - return targetDoc.last_seq; - } - return 0; - }); - } - throw err; - }); - })["catch"](function (err) { - if (err.status !== 404) { - throw err; - } - return 0; - }); -}; -function replicate(repId, src, target, opts, returnValue) { - var batches = []; // list of batches to be processed - var currentBatch; // the batch currently being processed - var pendingBatch = { - seq: 0, - changes: [], - docs: [] - }; // next batch, not yet ready to be processed - var writingCheckpoint = false; // true while checkpoint is being written - var changesCompleted = false; // true when all changes received - var replicationCompleted = false; // true when replication has completed - var last_seq = 0; - var continuous = opts.continuous || opts.live || false; - var batch_size = opts.batch_size || 100; - var batches_limit = opts.batches_limit || 10; - var changesPending = false; // true while src.changes is running - var changesCount = 0; // number of changes received since calling src.changes - var doc_ids = opts.doc_ids; - var checkpointer = new Checkpointer(src, target, repId); - var result = { - ok: true, - start_time: new Date(), - docs_read: 0, - docs_written: 0, - doc_write_failures: 0, - errors: [] - }; - var changesOpts = {}; - returnValue.ready(src, target); - - - function writeDocs() { - if (currentBatch.docs.length === 0) { - return; - } - var docs = currentBatch.docs; - return target.bulkDocs({ - docs: docs - }, { - new_edits: false - }).then(function (res) { - if (returnValue.cancelled) { - completeReplication(); - throw new Error('cancelled'); - } - var errors = []; - res.forEach(function (res) { - if (!res.ok) { - result.doc_write_failures++; - errors.push(new Error(res.reason || res.message || 'Unknown reason')); - } - }); - if (errors.length > 0) { - var error = new Error('bulkDocs error'); - error.other_errors = errors; - abortReplication('target.bulkDocs failed to write docs', error); - throw new Error('bulkWrite partial failure'); - } - }, function (err) { - result.doc_write_failures += docs.length; - throw err; - }); - } - - - function getNextDoc() { - var diffs = currentBatch.diffs; - var id = Object.keys(diffs)[0]; - var revs = diffs[id].missing; - return src.get(id, {revs: true, open_revs: revs, attachments: true}) - .then(function (docs) { - docs.forEach(function (doc) { - if (returnValue.cancelled) { - return completeReplication(); - } - if (doc.ok) { - result.docs_read++; - currentBatch.pendingRevs++; - currentBatch.docs.push(doc.ok); - delete diffs[doc.ok._id]; - } - }); - }); - } - - - function getAllDocs() { - if (Object.keys(currentBatch.diffs).length > 0) { - return getNextDoc().then(getAllDocs); - } else { - return utils.Promise.resolve(); - } - } - - - function getRevisionOneDocs() { - // filter out the generation 1 docs and get them - // leaving the non-generation one docs to be got otherwise - var ids = Object.keys(currentBatch.diffs).filter(function (id) { - var missing = currentBatch.diffs[id].missing; - return missing.length === 1 && missing[0].slice(0, 2) === '1-'; - }); - return src.allDocs({ - keys: ids, - include_docs: true - }).then(function (res) { - if (returnValue.cancelled) { - completeReplication(); - throw (new Error('cancelled')); - } - res.rows.forEach(function (row, i) { - if (row.doc && !row.deleted && - row.value.rev.slice(0, 2) === '1-' && ( - !row.doc._attachments || - Object.keys(row.doc._attachments).length === 0 - ) - ) { - result.docs_read++; - currentBatch.pendingRevs++; - currentBatch.docs.push(row.doc); - delete currentBatch.diffs[row.id]; - } - }); - }); - } - - - function getDocs() { - if (src.type() === 'http') { - return getRevisionOneDocs().then(getAllDocs); - } else { - return getAllDocs(); - } - } - - - function finishBatch() { - writingCheckpoint = true; - return checkpointer.writeCheckpoint( - currentBatch.seq - ).then(function (res) { - writingCheckpoint = false; - if (returnValue.cancelled) { - completeReplication(); - throw new Error('cancelled'); - } - result.last_seq = last_seq = currentBatch.seq; - result.docs_written += currentBatch.docs.length; - returnValue.emit('change', utils.clone(result)); - currentBatch = undefined; - getChanges(); - })["catch"](function (err) { - writingCheckpoint = false; - abortReplication('writeCheckpoint completed with error', err); - throw err; - }); - } - - - function getDiffs() { - var diff = {}; - currentBatch.changes.forEach(function (change) { - diff[change.id] = change.changes.map(function (x) { - return x.rev; - }); - }); - return target.revsDiff(diff).then(function (diffs) { - if (returnValue.cancelled) { - completeReplication(); - throw new Error('cancelled'); - } - // currentBatch.diffs elements are deleted as the documents are written - currentBatch.diffs = diffs; - currentBatch.pendingRevs = 0; - }); - } - - - function startNextBatch() { - if (returnValue.cancelled || currentBatch) { - return; - } - if (batches.length === 0) { - processPendingBatch(true); - return; - } - currentBatch = batches.shift(); - getDiffs() - .then(getDocs) - .then(writeDocs) - .then(finishBatch) - .then(startNextBatch)[ - "catch"](function (err) { - abortReplication('batch processing terminated with error', err); - }); - } - - - function processPendingBatch(immediate) { - if (pendingBatch.changes.length === 0) { - if (batches.length === 0 && !currentBatch) { - if ((continuous && changesOpts.live) || changesCompleted) { - returnValue.emit('uptodate', utils.clone(result)); - } - if (changesCompleted) { - completeReplication(); - } - } - return; - } - if ( - immediate || - changesCompleted || - pendingBatch.changes.length >= batch_size - ) { - batches.push(pendingBatch); - pendingBatch = { - seq: 0, - changes: [], - docs: [] - }; - startNextBatch(); - } - } - - - function abortReplication(reason, err) { - if (replicationCompleted) { - return; - } - result.ok = false; - result.status = 'aborted'; - err.message = reason; - result.errors.push(err); - batches = []; - pendingBatch = { - seq: 0, - changes: [], - docs: [] - }; - completeReplication(); - } - - - function completeReplication() { - if (replicationCompleted) { - return; - } - if (returnValue.cancelled) { - result.status = 'cancelled'; - if (writingCheckpoint) { - return; - } - } - result.status = result.status || 'complete'; - result.end_time = new Date(); - result.last_seq = last_seq; - replicationCompleted = returnValue.cancelled = true; - if (result.errors.length > 0) { - var error = result.errors.pop(); - if (result.errors.length > 0) { - error.other_errors = result.errors; - } - error.result = result; - returnValue.emit('error', error); - } else { - returnValue.emit('complete', result); - } - } - - - function onChange(change) { - if (returnValue.cancelled) { - return completeReplication(); - } - changesCount++; - if ( - pendingBatch.changes.length === 0 && - batches.length === 0 && - !currentBatch - ) { - returnValue.emit('outofdate', utils.clone(result)); - } - pendingBatch.seq = change.seq; - pendingBatch.changes.push(change); - processPendingBatch(batches.length === 0); - } - - - function onChangesComplete(changes) { - changesPending = false; - if (returnValue.cancelled) { - return completeReplication(); - } - if (changesCount > 0) { - changesOpts.since = changes.last_seq; - getChanges(); - } else { - if (continuous) { - changesOpts.live = true; - getChanges(); - } else { - changesCompleted = true; - } - } - processPendingBatch(true); - } - - - function onChangesError(err) { - changesPending = false; - if (returnValue.cancelled) { - return completeReplication(); - } - abortReplication('changes rejected', err); - } - - - function getChanges() { - if ( - !changesPending && - !changesCompleted && - batches.length < batches_limit - ) { - changesPending = true; - changesCount = 0; - src.changes(changesOpts) - .on('change', onChange) - .then(onChangesComplete)[ - "catch"](onChangesError); - } - } - - - function startChanges() { - checkpointer.getCheckpoint().then(function (checkpoint) { - last_seq = checkpoint; - changesOpts = { - since: last_seq, - limit: batch_size, - style: 'all_docs', - doc_ids: doc_ids, - returnDocs: false - }; - if (opts.filter) { - changesOpts.filter = opts.filter; - } - if (opts.query_params) { - changesOpts.query_params = opts.query_params; - } - getChanges(); - })["catch"](function (err) { - abortReplication('getCheckpoint rejected with ', err); - }); - } - - - returnValue.once('cancel', completeReplication); - - if (typeof opts.onChange === 'function') { - returnValue.on('change', opts.onChange); - } - - if (typeof opts.complete === 'function') { - returnValue.once('error', opts.complete); - returnValue.once('complete', function (result) { - opts.complete(null, result); - }); - } - - if (typeof opts.since === 'undefined') { - startChanges(); - } else { - writingCheckpoint = true; - checkpointer.writeCheckpoint(opts.since).then(function (res) { - writingCheckpoint = false; - if (returnValue.cancelled) { - completeReplication(); - return; - } - last_seq = opts.since; - startChanges(); - })["catch"](function (err) { - writingCheckpoint = false; - abortReplication('writeCheckpoint completed with error', err); - throw err; - }); - } -} - - -function toPouch(db) { - if (typeof db === 'string') { - return new Pouch(db); - } else if (db.then) { - return db; - } else { - return utils.Promise.resolve(db); - } -} - - -function replicateWrapper(src, target, opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - if (typeof opts === 'undefined') { - opts = {}; - } - if (!opts.complete) { - opts.complete = callback || function () {}; - } - opts = utils.clone(opts); - opts.continuous = opts.continuous || opts.live; - var replicateRet = new Replication(opts); - toPouch(src).then(function (src) { - return toPouch(target).then(function (target) { - if (opts.server) { - if (typeof src.replicateOnServer !== 'function') { - throw new TypeError( - 'Server replication not supported for ' + src.type() + ' adapter' - ); - } - if (src.type() !== target.type()) { - throw new TypeError('Server replication' + - ' for different adapter types (' + - src.type() + ' and ' + target.type() + ') is not supported' - ); - } - src.replicateOnServer(target, opts, replicateRet); - } else { - return genReplicationId(src, target, opts).then(function (repId) { - replicate(repId, src, target, opts, replicateRet); - }); - } - }); - })["catch"](function (err) { - opts.complete(err); - }); - return replicateRet; -} - -exports.replicate = replicateWrapper; - -},{"./index":15,"./utils":21,"events":24}],18:[function(_dereq_,module,exports){ -(function (global){ -"use strict"; - -var PouchDBVersion220 = _dereq_("./constructor"); -var utils = _dereq_('./utils'); -var Promise = utils.Promise; -var EventEmitter = _dereq_('events').EventEmitter; -PouchDBVersion220.adapters = {}; - -PouchDBVersion220.prefix = '_pouch_'; - -var eventEmitter = new EventEmitter(); - -var eventEmitterMethods = [ - 'on', - 'addListener', - 'emit', - 'listeners', - 'once', - 'removeAllListeners', - 'removeListener', - 'setMaxListeners' -]; - -var preferredAdapters = ['levelalt', 'idb', 'leveldb', 'websql']; - -eventEmitterMethods.forEach(function (method) { - PouchDBVersion220[method] = eventEmitter[method].bind(eventEmitter); -}); -PouchDBVersion220.setMaxListeners(0); -PouchDBVersion220.parseAdapter = function (name, opts) { - var match = name.match(/([a-z\-]*):\/\/(.*)/); - var adapter, adapterName; - if (match) { - // the http adapter expects the fully qualified name - name = /http(s?)/.test(match[1]) ? match[1] + '://' + match[2] : match[2]; - adapter = match[1]; - if (!PouchDBVersion220.adapters[adapter].valid()) { - throw 'Invalid adapter'; - } - return {name: name, adapter: match[1]}; - } - - // check for browsers that have been upgraded from websql-only to websql+idb - var skipIdb = 'idb' in PouchDBVersion220.adapters && 'websql' in PouchDBVersion220.adapters && - utils.hasLocalStorage() && - global.localStorage['_pouch__websqldb_' + PouchDBVersion220.prefix + name]; - - if (typeof opts !== 'undefined' && opts.db) { - adapterName = 'leveldb'; - } else { - for (var i = 0; i < preferredAdapters.length; ++i) { - adapterName = preferredAdapters[i]; - if (adapterName in PouchDBVersion220.adapters) { - if (skipIdb && adapterName === 'idb') { - continue; // keep using websql to avoid user data loss - } - break; - } - } - } - - if (adapterName) { - adapter = PouchDBVersion220.adapters[adapterName]; - var use_prefix = 'use_prefix' in adapter ? adapter.use_prefix : true; - - return { - name: use_prefix ? PouchDBVersion220.prefix + name : name, - adapter: adapterName - }; - } - - throw 'No valid adapter found'; -}; - -PouchDBVersion220.destroy = utils.toPromise(function (name, opts, callback) { - if (typeof opts === 'function' || typeof opts === 'undefined') { - callback = opts; - opts = {}; - } - - if (typeof name === 'object') { - opts = name; - name = undefined; - } - - var backend = PouchDBVersion220.parseAdapter(opts.name || name, opts); - var dbName = backend.name; - - var adapter = PouchDBVersion220.adapters[backend.adapter]; - - function destroyDb() { - // call destroy method of the particular adaptor - adapter.destroy(dbName, opts, function (err, resp) { - if (err) { - callback(err); - } else { - PouchDBVersion220.emit('destroyed', dbName); - //so we don't have to sift through all dbnames - PouchDBVersion220.emit(dbName, 'destroyed'); - callback(null, resp || { 'ok': true }); - } - }); - } - - var usePrefix = 'use_prefix' in adapter ? adapter.use_prefix : true; - - var trueDbName = usePrefix ? - dbName.replace(new RegExp('^' + PouchDBVersion220.prefix), '') : dbName; - new PouchDBVersion220(trueDbName, {adapter : backend.adapter}, function (err, db) { - if (err) { - return callback(err); - } - db.get('_local/_pouch_dependentDbs', function (err, localDoc) { - if (err) { - if (err.name !== 'not_found') { - return callback(err); - } else { // no dependencies - return destroyDb(); - } - } - var dependentDbs = localDoc.dependentDbs; - var deletedMap = Object.keys(dependentDbs).map(function (name) { - var trueName = usePrefix ? - name.replace(new RegExp('^' + PouchDBVersion220.prefix), '') : name; - return PouchDBVersion220.destroy(trueName, {adapter: backend.adapter}); - }); - Promise.all(deletedMap).then(destroyDb, function (error) { - callback(error); - }); - }); - }); -}); - -PouchDBVersion220.allDbs = utils.toPromise(function (callback) { - var err = new Error('allDbs method removed'); - err.stats = '400'; - callback(err); -}); -PouchDBVersion220.adapter = function (id, obj) { - if (obj.valid()) { - PouchDBVersion220.adapters[id] = obj; - } -}; - -PouchDBVersion220.plugin = function (obj) { - Object.keys(obj).forEach(function (id) { - PouchDBVersion220.prototype[id] = obj[id]; - }); -}; - -module.exports = PouchDBVersion220; - -}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./constructor":7,"./utils":21,"events":24}],19:[function(_dereq_,module,exports){ -'use strict'; -var utils = _dereq_('./utils'); -var replicate = _dereq_('./replicate').replicate; -var EE = _dereq_('events').EventEmitter; - -module.exports = Sync; -utils.inherits(Sync, EE); -function Sync(src, target, opts, callback) { - if (!(this instanceof Sync)) { - return new Sync(src, target, opts, callback); - } - var self = this; - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - if (typeof opts === 'undefined') { - opts = {}; - } - this.canceled = false; - opts = utils.clone(opts); - var onChange, complete; - if ('onChange' in opts) { - onChange = opts.onChange; - delete opts.onChange; - } - if (typeof callback === 'function' && !opts.complete) { - complete = callback; - } else if ('complete' in opts) { - complete = opts.complete; - delete opts.complete; - } - this.push = replicate(src, target, opts); - - this.pull = replicate(target, src, opts); - var emittedCancel = false; - function onCancel(data) { - if (!emittedCancel) { - emittedCancel = true; - self.emit('cancel', data); - } - } - - function pullChange(change) { - self.emit('change', { - direction: 'pull', - change: change - }); - } - function pushChange(change) { - self.emit('change', { - direction: 'push', - change: change - }); - } - var listeners = {}; - - function removal(event, func) { - if (event === 'change' && - (func === pullChange || - func === pushChange)) { - self.removeAllListeners('change'); - } else if (event === 'cancel' && - func === onCancel) { - self.removeAllListeners('cancel'); - } else if (event in listeners && func === listeners[event]) { - self.removeAllListeners(event); - } - } - - this.on('newListener', function (event) { - if (event === 'change') { - self.pull.on('change', pullChange); - self.push.on('change', pushChange); - } else if (event === 'cancel') { - self.pull.on('cancel', onCancel); - self.push.on('cancel', onCancel); - } else if (event !== 'error' && - event !== 'complete' && !(event in listeners)) { - listeners[event] = function (e) { - self.emit(event, e); - }; - self.pull.on(event, listeners[event]); - self.push.on(event, listeners[event]); - } - }); - - this.on('removeListener', function (event) { - if (event === 'change') { - self.pull.removeListener('change', pullChange); - self.push.removeListener('change', pushChange); - } else if (event === 'cancel') { - self.pull.removeListener('cancel', onCancel); - self.push.removeListener('cancel', onCancel); - } else if (event in listeners) { - if (typeof listeners[event] === 'function') { - self.pull.removeListener(event, listeners[event]); - self.push.removeListener(event, listeners[event]); - delete listeners[event]; - } - } - }); - - this.pull.on('removeListener', removal); - this.push.on('removeListener', removal); - - var promise = utils.Promise.all([ - this.push, - this.pull - ]).then(function (resp) { - var out = { - push: resp[0], - pull: resp[1] - }; - self.emit('complete', out); - if (complete) { - complete(null, out); - } - self.removeAllListeners(); - return out; - }, function (err) { - self.cancel(); - self.emit('error', err); - if (complete) { - complete(err); - } - self.removeAllListeners(); - throw err; - }); - - this.then = function (success, err) { - return promise.then(success, err); - }; - - this["catch"] = function (err) { - return promise["catch"](err); - }; -} - -Sync.prototype.cancel = function () { - if (!this.canceled) { - this.canceled = true; - this.push.cancel(); - this.pull.cancel(); - } -}; -},{"./replicate":17,"./utils":21,"events":24}],20:[function(_dereq_,module,exports){ -'use strict'; - -module.exports = TaskQueue; - -function TaskQueue() { - this.isReady = false; - this.failed = false; - this.queue = []; -} - -TaskQueue.prototype.execute = function () { - var d, func; - if (this.failed) { - while ((d = this.queue.shift())) { - if (typeof d === 'function') { - d(this.failed); - continue; - } - func = d.parameters[d.parameters.length - 1]; - if (typeof func === 'function') { - func(this.failed); - } else if (d.name === 'changes' && typeof func.complete === 'function') { - func.complete(this.failed); - } - } - } else if (this.isReady) { - while ((d = this.queue.shift())) { - - if (typeof d === 'function') { - d(); - } else { - d.task = this.db[d.name].apply(this.db, d.parameters); - } - } - } -}; - -TaskQueue.prototype.fail = function (err) { - this.failed = err; - this.execute(); -}; - -TaskQueue.prototype.ready = function (db) { - if (this.failed) { - return false; - } else if (arguments.length === 0) { - return this.isReady; - } - this.isReady = db ? true: false; - this.db = db; - this.execute(); -}; - -TaskQueue.prototype.addTask = function (name, parameters) { - if (typeof name === 'function') { - this.queue.push(name); - if (this.failed) { - this.execute(); - } - } else { - var task = { name: name, parameters: parameters }; - this.queue.push(task); - if (this.failed) { - this.execute(); - } - return task; - } -}; - -},{}],21:[function(_dereq_,module,exports){ -(function (process,global){ -/*jshint strict: false */ -/*global chrome */ -var crypto = _dereq_('crypto'); -var md5 = _dereq_('md5-jkmyers'); -var merge = _dereq_('./merge'); -exports.extend = _dereq_('extend'); -exports.ajax = _dereq_('./deps/ajax'); -exports.createBlob = _dereq_('./deps/blob'); -exports.uuid = _dereq_('./deps/uuid'); -exports.getArguments = _dereq_('argsarray'); -var buffer = _dereq_('./deps/buffer'); -var errors = _dereq_('./deps/errors'); -var EventEmitter = _dereq_('events').EventEmitter; - -if (typeof global.Promise === 'function') { - exports.Promise = global.Promise; -} else { - exports.Promise = _dereq_('bluebird'); -} -var Promise = exports.Promise; - -function toObject(array) { - var obj = {}; - array.forEach(function (item) { obj[item] = true; }); - return obj; -} -// List of top level reserved words for doc -var reservedWords = toObject([ - '_id', - '_rev', - '_attachments', - '_deleted', - '_revisions', - '_revs_info', - '_conflicts', - '_deleted_conflicts', - '_local_seq', - '_rev_tree' -]); -exports.clone = function (obj) { - return exports.extend(true, {}, obj); -}; -exports.inherits = _dereq_('inherits'); -// Determine id an ID is valid -// - invalid IDs begin with an underescore that does not begin '_design' or -// '_local' -// - any other string value is a valid id -// Returns the specific error object for each case -exports.invalidIdError = function (id) { - if (!id) { - return errors.MISSING_ID; - } else if (typeof id !== 'string') { - return errors.INVALID_ID; - } else if (/^_/.test(id) && !(/^_(design|local)/).test(id)) { - return errors.RESERVED_ID; - } -}; - -function isChromeApp() { - return (typeof chrome !== "undefined" && - typeof chrome.storage !== "undefined" && - typeof chrome.storage.local !== "undefined"); -} - -// Pretty dumb name for a function, just wraps callback calls so we dont -// to if (callback) callback() everywhere -exports.call = exports.getArguments(function (args) { - if (!args.length) { - return; - } - var fun = args.shift(); - if (typeof fun === 'function') { - fun.apply(this, args); - } -}); - -exports.isLocalId = function (id) { - return (/^_local/).test(id); -}; - -// check if a specific revision of a doc has been deleted -// - metadata: the metadata object from the doc store -// - rev: (optional) the revision to check. defaults to winning revision -exports.isDeleted = function (metadata, rev) { - if (!rev) { - rev = merge.winningRev(metadata); - } - var dashIndex = rev.indexOf('-'); - if (dashIndex !== -1) { - rev = rev.substring(dashIndex + 1); - } - var deleted = false; - merge.traverseRevTree(metadata.rev_tree, - function (isLeaf, pos, id, acc, opts) { - if (id === rev) { - deleted = !!opts.deleted; - } - }); - - return deleted; -}; - -exports.filterChange = function (opts) { - return function (change) { - var req = {}; - var hasFilter = opts.filter && typeof opts.filter === 'function'; - - req.query = opts.query_params; - if (opts.filter && hasFilter && !opts.filter.call(this, change.doc, req)) { - return false; - } - if (opts.doc_ids && opts.doc_ids.indexOf(change.id) === -1) { - return false; - } - if (!opts.include_docs) { - delete change.doc; - } else { - for (var att in change.doc._attachments) { - if (change.doc._attachments.hasOwnProperty(att)) { - change.doc._attachments[att].stub = true; - } - } - } - return true; - }; -}; - -// Preprocess documents, parse their revisions, assign an id and a -// revision for new writes that are missing them, etc -exports.parseDoc = function (doc, newEdits) { - var nRevNum; - var newRevId; - var revInfo; - var opts = {status: 'available'}; - if (doc._deleted) { - opts.deleted = true; - } - - if (newEdits) { - if (!doc._id) { - doc._id = exports.uuid(); - } - newRevId = exports.uuid(32, 16).toLowerCase(); - if (doc._rev) { - revInfo = /^(\d+)-(.+)$/.exec(doc._rev); - if (!revInfo) { - throw "invalid value for property '_rev'"; - } - doc._rev_tree = [{ - pos: parseInt(revInfo[1], 10), - ids: [revInfo[2], {status: 'missing'}, [[newRevId, opts, []]]] - }]; - nRevNum = parseInt(revInfo[1], 10) + 1; - } else { - doc._rev_tree = [{ - pos: 1, - ids : [newRevId, opts, []] - }]; - nRevNum = 1; - } - } else { - if (doc._revisions) { - doc._rev_tree = [{ - pos: doc._revisions.start - doc._revisions.ids.length + 1, - ids: doc._revisions.ids.reduce(function (acc, x) { - if (acc === null) { - return [x, opts, []]; - } else { - return [x, {status: 'missing'}, [acc]]; - } - }, null) - }]; - nRevNum = doc._revisions.start; - newRevId = doc._revisions.ids[0]; - } - if (!doc._rev_tree) { - revInfo = /^(\d+)-(.+)$/.exec(doc._rev); - if (!revInfo) { - return errors.BAD_ARG; - } - nRevNum = parseInt(revInfo[1], 10); - newRevId = revInfo[2]; - doc._rev_tree = [{ - pos: parseInt(revInfo[1], 10), - ids: [revInfo[2], opts, []] - }]; - } - } - - var error = exports.invalidIdError(doc._id); - if (error) { - return error; - } - - doc._id = decodeURIComponent(doc._id); - doc._rev = [nRevNum, newRevId].join('-'); - - var result = {metadata : {}, data : {}}; - for (var key in doc) { - if (doc.hasOwnProperty(key)) { - var specialKey = key[0] === '_'; - if (specialKey && !reservedWords[key]) { - error = errors.error(errors.DOC_VALIDATION); - error.reason += ': ' + key; - return error; - } else if (specialKey && key !== '_attachments') { - result.metadata[key.slice(1)] = doc[key]; - } else { - result.data[key] = doc[key]; - } - } - } - return result; -}; - -exports.isCordova = function () { - return (typeof cordova !== "undefined" || - typeof PhoneGap !== "undefined" || - typeof phonegap !== "undefined"); -}; - -exports.hasLocalStorage = function () { - if (isChromeApp()) { - return false; - } - try { - return global.localStorage; - } catch (e) { - return false; - } -}; -exports.Changes = function () { - - var api = {}; - var eventEmitter = new EventEmitter(); - var isChrome = isChromeApp(); - var listeners = {}; - var hasLocal = false; - if (!isChrome) { - hasLocal = exports.hasLocalStorage(); - } - if (isChrome) { - chrome.storage.onChanged.addListener(function (e) { - // make sure it's event addressed to us - if (e.db_name != null) { - //object only has oldValue, newValue members - eventEmitter.emit(e.dbName.newValue); - } - }); - } else if (hasLocal) { - if (global.addEventListener) { - global.addEventListener("storage", function (e) { - eventEmitter.emit(e.key); - }); - } else { - global.attachEvent("storage", function (e) { - eventEmitter.emit(e.key); - }); - } - } - - api.addListener = function (dbName, id, db, opts) { - if (listeners[id]) { - return; - } - function eventFunction() { - db.changes({ - include_docs: opts.include_docs, - conflicts: opts.conflicts, - continuous: false, - descending: false, - filter: opts.filter, - view: opts.view, - since: opts.since, - query_params: opts.query_params, - onChange: function (c) { - if (c.seq > opts.since && !opts.cancelled) { - opts.since = c.seq; - exports.call(opts.onChange, c); - } - } - }); - } - listeners[id] = eventFunction; - eventEmitter.on(dbName, eventFunction); - }; - - api.removeListener = function (dbName, id) { - if (!(id in listeners)) { - return; - } - eventEmitter.removeListener(dbName, listeners[id]); - }; - - api.clearListeners = function (dbName) { - eventEmitter.removeAllListeners(dbName); - }; - - api.notifyLocalWindows = function (dbName) { - //do a useless change on a storage thing - //in order to get other windows's listeners to activate - if (isChrome) { - chrome.storage.local.set({dbName: dbName}); - } else if (hasLocal) { - localStorage[dbName] = (localStorage[dbName] === "a") ? "b" : "a"; - } - }; - - api.notify = function (dbName) { - eventEmitter.emit(dbName); - }; - - return api; -}; - -if (!process.browser || !('atob' in global)) { - exports.atob = function (str) { - var base64 = new buffer(str, 'base64'); - // Node.js will just skip the characters it can't encode instead of - // throwing and exception - if (base64.toString('base64') !== str) { - throw ("Cannot base64 encode full string"); - } - return base64.toString('binary'); - }; -} else { - exports.atob = function (str) { - return atob(str); - }; -} - -if (!process.browser || !('btoa' in global)) { - exports.btoa = function (str) { - return new buffer(str, 'binary').toString('base64'); - }; -} else { - exports.btoa = function (str) { - return btoa(str); - }; -} - -// From http://stackoverflow.com/questions/14967647/ (continues on next line) -// encode-decode-image-with-base64-breaks-image (2013-04-21) -exports.fixBinary = function (bin) { - if (!process.browser) { - // don't need to do this in Node - return bin; - } - - var length = bin.length; - var buf = new ArrayBuffer(length); - var arr = new Uint8Array(buf); - for (var i = 0; i < length; i++) { - arr[i] = bin.charCodeAt(i); - } - return buf; -}; - -exports.once = function (fun) { - var called = false; - return exports.getArguments(function (args) { - if (called) { - console.trace(); - throw new Error('once called more than once'); - } else { - called = true; - fun.apply(this, args); - } - }); -}; - -exports.toPromise = function (func) { - //create the function we will be returning - return exports.getArguments(function (args) { - var self = this; - var tempCB = - (typeof args[args.length - 1] === 'function') ? args.pop() : false; - // if the last argument is a function, assume its a callback - var usedCB; - if (tempCB) { - // if it was a callback, create a new callback which calls it, - // but do so async so we don't trap any errors - usedCB = function (err, resp) { - process.nextTick(function () { - tempCB(err, resp); - }); - }; - } - var promise = new Promise(function (fulfill, reject) { - var resp; - try { - var callback = exports.once(function (err, mesg) { - if (err) { - reject(err); - } else { - fulfill(mesg); - } - }); - // create a callback for this invocation - // apply the function in the orig context - args.push(callback); - resp = func.apply(self, args); - if (resp && typeof resp.then === 'function') { - fulfill(resp); - } - } catch (e) { - reject(e); - } - }); - // if there is a callback, call it back - if (usedCB) { - promise.then(function (result) { - usedCB(null, result); - }, usedCB); - } - promise.cancel = function () { - return this; - }; - return promise; - }); -}; - -exports.adapterFun = function (name, callback) { - return exports.toPromise(exports.getArguments(function (args) { - var self = this; - if (!this.taskqueue.isReady) { - return new exports.Promise(function (fulfill, reject) { - self.taskqueue.addTask(function (failed) { - if (failed) { - reject(failed); - } else { - fulfill(self[name].apply(self, args)); - } - }); - }); - } - return callback.apply(this, args); - })); -}; -//Can't find original post, but this is close -//http://stackoverflow.com/questions/6965107/ (continues on next line) -//converting-between-strings-and-arraybuffers -exports.arrayBufferToBinaryString = function (buffer) { - var binary = ""; - var bytes = new Uint8Array(buffer); - var length = bytes.byteLength; - for (var i = 0; i < length; i++) { - binary += String.fromCharCode(bytes[i]); - } - return binary; -}; - -exports.cancellableFun = function (fun, self, opts) { - - opts = opts ? exports.clone(true, {}, opts) : {}; - - var emitter = new EventEmitter(); - var oldComplete = opts.complete || function () { }; - var complete = opts.complete = exports.once(function (err, resp) { - if (err) { - oldComplete(err); - } else { - emitter.emit('end', resp); - oldComplete(null, resp); - } - emitter.removeAllListeners(); - }); - var oldOnChange = opts.onChange || function () {}; - var lastChange = 0; - self.on('destroyed', function () { - emitter.removeAllListeners(); - }); - opts.onChange = function (change) { - oldOnChange(change); - if (change.seq <= lastChange) { - return; - } - lastChange = change.seq; - emitter.emit('change', change); - if (change.deleted) { - emitter.emit('delete', change); - } else if (change.changes.length === 1 && - change.changes[0].rev.slice(0, 1) === '1-') { - emitter.emit('create', change); - } else { - emitter.emit('update', change); - } - }; - var promise = new Promise(function (fulfill, reject) { - opts.complete = function (err, res) { - if (err) { - reject(err); - } else { - fulfill(res); - } - }; - }); - - promise.then(function (result) { - complete(null, result); - }, complete); - - // this needs to be overwridden by caller, dont fire complete until - // the task is ready - promise.cancel = function () { - promise.isCancelled = true; - if (self.taskqueue.isReady) { - opts.complete(null, {status: 'cancelled'}); - } - }; - - if (!self.taskqueue.isReady) { - self.taskqueue.addTask(function () { - if (promise.isCancelled) { - opts.complete(null, {status: 'cancelled'}); - } else { - fun(self, opts, promise); - } - }); - } else { - fun(self, opts, promise); - } - promise.on = emitter.on.bind(emitter); - promise.once = emitter.once.bind(emitter); - promise.addListener = emitter.addListener.bind(emitter); - promise.removeListener = emitter.removeListener.bind(emitter); - promise.removeAllListeners = emitter.removeAllListeners.bind(emitter); - promise.setMaxListeners = emitter.setMaxListeners.bind(emitter); - promise.listeners = emitter.listeners.bind(emitter); - promise.emit = emitter.emit.bind(emitter); - return promise; -}; -exports.Crypto = {}; -exports.MD5 = exports.Crypto.MD5 = function (string) { - if (!process.browser) { - return crypto.createHash('md5').update(string).digest('hex'); - } else { - return md5(string); - } -}; - -}).call(this,_dereq_("/Users/daleharvey/src/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./deps/ajax":8,"./deps/blob":9,"./deps/buffer":23,"./deps/errors":10,"./deps/uuid":12,"./merge":16,"/Users/daleharvey/src/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":25,"argsarray":22,"bluebird":31,"crypto":23,"events":24,"extend":26,"inherits":27,"md5-jkmyers":45}],22:[function(_dereq_,module,exports){ -'use strict'; - -module.exports = argsArray; - -function argsArray(fun) { - return function () { - var len = arguments.length; - if (len) { - var args = []; - var i = -1; - while (++i < len) { - args[i] = arguments[i]; - } - return fun.call(this, args); - } else { - return fun.call(this, []); - } - }; -} -},{}],23:[function(_dereq_,module,exports){ - -},{}],24:[function(_dereq_,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -function EventEmitter() { - this._events = this._events || {}; - this._maxListeners = this._maxListeners || undefined; -} -module.exports = EventEmitter; - -// Backwards-compat with node 0.10.x -EventEmitter.EventEmitter = EventEmitter; - -EventEmitter.prototype._events = undefined; -EventEmitter.prototype._maxListeners = undefined; - -// By default EventEmitters will print a warning if more than 10 listeners are -// added to it. This is a useful default which helps finding memory leaks. -EventEmitter.defaultMaxListeners = 10; - -// Obviously not all Emitters should be limited to 10. This function allows -// that to be increased. Set to zero for unlimited. -EventEmitter.prototype.setMaxListeners = function(n) { - if (!isNumber(n) || n < 0 || isNaN(n)) - throw TypeError('n must be a positive number'); - this._maxListeners = n; - return this; -}; - -EventEmitter.prototype.emit = function(type) { - var er, handler, len, args, i, listeners; - - if (!this._events) - this._events = {}; - - // If there is no 'error' event listener then throw. - if (type === 'error') { - if (!this._events.error || - (isObject(this._events.error) && !this._events.error.length)) { - er = arguments[1]; - if (er instanceof Error) { - throw er; // Unhandled 'error' event - } else { - throw TypeError('Uncaught, unspecified "error" event.'); - } - return false; - } - } - - handler = this._events[type]; - - if (isUndefined(handler)) - return false; - - if (isFunction(handler)) { - switch (arguments.length) { - // fast cases - case 1: - handler.call(this); - break; - case 2: - handler.call(this, arguments[1]); - break; - case 3: - handler.call(this, arguments[1], arguments[2]); - break; - // slower - default: - len = arguments.length; - args = new Array(len - 1); - for (i = 1; i < len; i++) - args[i - 1] = arguments[i]; - handler.apply(this, args); - } - } else if (isObject(handler)) { - len = arguments.length; - args = new Array(len - 1); - for (i = 1; i < len; i++) - args[i - 1] = arguments[i]; - - listeners = handler.slice(); - len = listeners.length; - for (i = 0; i < len; i++) - listeners[i].apply(this, args); - } - - return true; -}; - -EventEmitter.prototype.addListener = function(type, listener) { - var m; - - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - if (!this._events) - this._events = {}; - - // To avoid recursion in the case that type === "newListener"! Before - // adding it to the listeners, first emit "newListener". - if (this._events.newListener) - this.emit('newListener', type, - isFunction(listener.listener) ? - listener.listener : listener); - - if (!this._events[type]) - // Optimize the case of one listener. Don't need the extra array object. - this._events[type] = listener; - else if (isObject(this._events[type])) - // If we've already got an array, just append. - this._events[type].push(listener); - else - // Adding the second element, need to change to array. - this._events[type] = [this._events[type], listener]; - - // Check for listener leak - if (isObject(this._events[type]) && !this._events[type].warned) { - var m; - if (!isUndefined(this._maxListeners)) { - m = this._maxListeners; - } else { - m = EventEmitter.defaultMaxListeners; - } - - if (m && m > 0 && this._events[type].length > m) { - this._events[type].warned = true; - console.error('(node) warning: possible EventEmitter memory ' + - 'leak detected. %d listeners added. ' + - 'Use emitter.setMaxListeners() to increase limit.', - this._events[type].length); - console.trace(); - } - } - - return this; -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.once = function(type, listener) { - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - var fired = false; - - function g() { - this.removeListener(type, g); - - if (!fired) { - fired = true; - listener.apply(this, arguments); - } - } - - g.listener = listener; - this.on(type, g); - - return this; -}; - -// emits a 'removeListener' event iff the listener was removed -EventEmitter.prototype.removeListener = function(type, listener) { - var list, position, length, i; - - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - if (!this._events || !this._events[type]) - return this; - - list = this._events[type]; - length = list.length; - position = -1; - - if (list === listener || - (isFunction(list.listener) && list.listener === listener)) { - delete this._events[type]; - if (this._events.removeListener) - this.emit('removeListener', type, listener); - - } else if (isObject(list)) { - for (i = length; i-- > 0;) { - if (list[i] === listener || - (list[i].listener && list[i].listener === listener)) { - position = i; - break; - } - } - - if (position < 0) - return this; - - if (list.length === 1) { - list.length = 0; - delete this._events[type]; - } else { - list.splice(position, 1); - } - - if (this._events.removeListener) - this.emit('removeListener', type, listener); - } - - return this; -}; - -EventEmitter.prototype.removeAllListeners = function(type) { - var key, listeners; - - if (!this._events) - return this; - - // not listening for removeListener, no need to emit - if (!this._events.removeListener) { - if (arguments.length === 0) - this._events = {}; - else if (this._events[type]) - delete this._events[type]; - return this; - } - - // emit removeListener for all listeners on all events - if (arguments.length === 0) { - for (key in this._events) { - if (key === 'removeListener') continue; - this.removeAllListeners(key); - } - this.removeAllListeners('removeListener'); - this._events = {}; - return this; - } - - listeners = this._events[type]; - - if (isFunction(listeners)) { - this.removeListener(type, listeners); - } else { - // LIFO order - while (listeners.length) - this.removeListener(type, listeners[listeners.length - 1]); - } - delete this._events[type]; - - return this; -}; - -EventEmitter.prototype.listeners = function(type) { - var ret; - if (!this._events || !this._events[type]) - ret = []; - else if (isFunction(this._events[type])) - ret = [this._events[type]]; - else - ret = this._events[type].slice(); - return ret; -}; - -EventEmitter.listenerCount = function(emitter, type) { - var ret; - if (!emitter._events || !emitter._events[type]) - ret = 0; - else if (isFunction(emitter._events[type])) - ret = 1; - else - ret = emitter._events[type].length; - return ret; -}; - -function isFunction(arg) { - return typeof arg === 'function'; -} - -function isNumber(arg) { - return typeof arg === 'number'; -} - -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} - -function isUndefined(arg) { - return arg === void 0; -} - -},{}],25:[function(_dereq_,module,exports){ -// shim for using process in browser - -var process = module.exports = {}; - -process.nextTick = (function () { - var canSetImmediate = typeof window !== 'undefined' - && window.setImmediate; - var canPost = typeof window !== 'undefined' - && window.postMessage && window.addEventListener - ; - - if (canSetImmediate) { - return function (f) { return window.setImmediate(f) }; - } - - if (canPost) { - var queue = []; - window.addEventListener('message', function (ev) { - var source = ev.source; - if ((source === window || source === null) && ev.data === 'process-tick') { - ev.stopPropagation(); - if (queue.length > 0) { - var fn = queue.shift(); - fn(); - } - } - }, true); - - return function nextTick(fn) { - queue.push(fn); - window.postMessage('process-tick', '*'); - }; - } - - return function nextTick(fn) { - setTimeout(fn, 0); - }; -})(); - -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; - -process.binding = function (name) { - throw new Error('process.binding is not supported'); -} - -// TODO(shtylman) -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; - -},{}],26:[function(_dereq_,module,exports){ -var hasOwn = Object.prototype.hasOwnProperty; -var toString = Object.prototype.toString; - -function isPlainObject(obj) { - if (!obj || toString.call(obj) !== '[object Object]' || obj.nodeType || obj.setInterval) - return false; - - var has_own_constructor = hasOwn.call(obj, 'constructor'); - var has_is_property_of_method = hasOwn.call(obj.constructor.prototype, 'isPrototypeOf'); - // Not own constructor property must be Object - if (obj.constructor && !has_own_constructor && !has_is_property_of_method) - return false; - - // Own properties are enumerated firstly, so to speed up, - // if last one is own, then all properties are own. - var key; - for ( key in obj ) {} - - return key === undefined || hasOwn.call( obj, key ); -}; - -module.exports = function extend() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[0] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - target = arguments[1] || {}; - // skip the boolean and the target - i = 2; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && typeof target !== "function") { - target = {}; - } - - for ( ; i < length; i++ ) { - // Only deal with non-null/undefined values - if ( (options = arguments[ i ]) != null ) { - // Extend the base object - for ( name in options ) { - src = target[ name ]; - copy = options[ name ]; - - // Prevent never-ending loop - if ( target === copy ) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( isPlainObject(copy) || (copyIsArray = Array.isArray(copy)) ) ) { - if ( copyIsArray ) { - copyIsArray = false; - clone = src && Array.isArray(src) ? src : []; - - } else { - clone = src && isPlainObject(src) ? src : {}; - } - - // Never move original objects, clone them - target[ name ] = extend( deep, clone, copy ); - - // Don't bring in undefined values - } else if ( copy !== undefined ) { - target[ name ] = copy; - } - } - } - } - - // Return the modified object - return target; -}; - -},{}],27:[function(_dereq_,module,exports){ -if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); - }; -} else { - // old school shim for old browsers - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - var TempCtor = function () {} - TempCtor.prototype = superCtor.prototype - ctor.prototype = new TempCtor() - ctor.prototype.constructor = ctor - } -} - -},{}],28:[function(_dereq_,module,exports){ -'use strict'; - -module.exports = INTERNAL; - -function INTERNAL() {} -},{}],29:[function(_dereq_,module,exports){ -'use strict'; -var INTERNAL = _dereq_('./INTERNAL'); -var Promise = _dereq_('./promise'); -var reject = _dereq_('./reject'); -var resolve = _dereq_('./resolve'); - -module.exports = function all(iterable) { - if (Object.prototype.toString.call(iterable) !== '[object Array]') { - return reject(new TypeError('must be an array')); - } - var len = iterable.length; - if (!len) { - return resolve([]); - } - var values = []; - var resolved = 0; - var i = -1; - var promise = new Promise(INTERNAL); - function allResolver(value, i) { - resolve(value).then(function (outValue) { - values[i] = outValue; - if (++resolved === len) { - promise.resolve(values); - } - }, function (error) { - promise.reject(error); - }); - } - - while (++i < len) { - allResolver(iterable[i], i); - } - return promise; -}; -},{"./INTERNAL":28,"./promise":33,"./reject":34,"./resolve":35}],30:[function(_dereq_,module,exports){ -'use strict'; - -module.exports = getThen; - -function getThen(obj) { - // Make sure we only access the accessor once as required by the spec - var then = obj && obj.then; - if (obj && typeof obj === 'object' && typeof then === 'function') { - return function appyThen() { - then.apply(obj, arguments); - }; - } -} -},{}],31:[function(_dereq_,module,exports){ -module.exports = exports = _dereq_('./promise'); - -exports.resolve = _dereq_('./resolve'); -exports.reject = _dereq_('./reject'); -exports.all = _dereq_('./all'); -},{"./all":29,"./promise":33,"./reject":34,"./resolve":35}],32:[function(_dereq_,module,exports){ -'use strict'; - -module.exports = once; - -/* Wrap an arbitrary number of functions and allow only one of them to be - executed and only once */ -function once() { - var called = 0; - return function wrapper(wrappedFunction) { - return function () { - if (called++) { - return; - } - wrappedFunction.apply(this, arguments); - }; - }; -} -},{}],33:[function(_dereq_,module,exports){ -'use strict'; - -var unwrap = _dereq_('./unwrap'); -var INTERNAL = _dereq_('./INTERNAL'); -var once = _dereq_('./once'); -var tryCatch = _dereq_('./tryCatch'); -var getThen = _dereq_('./getThen'); - -// Lazy man's symbols for states -var PENDING = ['PENDING'], - FULFILLED = ['FULFILLED'], - REJECTED = ['REJECTED']; -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 = PENDING; - this.queue = []; - if (resolver !== INTERNAL) { - safelyResolveThenable(this, resolver); - } -} -Promise.prototype.resolve = function (value) { - var result = tryCatch(getThen, value); - if (result.status === 'error') { - return this.reject(result.value); - } - var thenable = result.value; - - if (thenable) { - safelyResolveThenable(this, thenable); - } else { - this.state = FULFILLED; - this.outcome = value; - var i = -1; - var len = this.queue.length; - while (++i < len) { - this.queue[i].callFulfilled(value); - } - } - return this; -}; -Promise.prototype.reject = function (error) { - this.state = REJECTED; - this.outcome = error; - var i = -1; - var len = this.queue.length; - while (++i < len) { - this.queue[i].callRejected(error); - } - return this; -}; - -Promise.prototype['catch'] = function (onRejected) { - return this.then(null, onRejected); -}; -Promise.prototype.then = function (onFulfilled, onRejected) { - var onFulfilledFunc = typeof onFulfilled === 'function'; - var onRejectedFunc = typeof onRejected === 'function'; - if (!onFulfilledFunc && this.state === FULFILLED || !onRejected && this.state === REJECTED) { - return this; - } - var promise = new Promise(INTERNAL); - - var thenHandler = { - promise: promise, - }; - if (this.state !== REJECTED) { - if (onFulfilledFunc) { - thenHandler.callFulfilled = function (value) { - unwrap(promise, onFulfilled, value); - }; - } else { - thenHandler.callFulfilled = function (value) { - promise.resolve(value); - }; - } - } - if (this.state !== FULFILLED) { - if (onRejectedFunc) { - thenHandler.callRejected = function (value) { - unwrap(promise, onRejected, value); - }; - } else { - thenHandler.callRejected = function (value) { - promise.reject(value); - }; - } - } - if (this.state === FULFILLED) { - thenHandler.callFulfilled(this.outcome); - } else if (this.state === REJECTED) { - thenHandler.callRejected(this.outcome); - } else { - this.queue.push(thenHandler); - } - - return promise; -}; -function safelyResolveThenable(self, thenable) { - // Either fulfill, reject or reject with error - var onceWrapper = once(); - var onError = onceWrapper(function (value) { - return self.reject(value); - }); - var result = tryCatch(function () { - thenable( - onceWrapper(function (value) { - return self.resolve(value); - }), - onError - ); - }); - if (result.status === 'error') { - onError(result.value); - } -} -},{"./INTERNAL":28,"./getThen":30,"./once":32,"./tryCatch":36,"./unwrap":37}],34:[function(_dereq_,module,exports){ -'use strict'; - -var Promise = _dereq_('./promise'); -var INTERNAL = _dereq_('./INTERNAL'); - -module.exports = reject; - -function reject(reason) { - var promise = new Promise(INTERNAL); - return promise.reject(reason); -} -},{"./INTERNAL":28,"./promise":33}],35:[function(_dereq_,module,exports){ -'use strict'; - -var Promise = _dereq_('./promise'); -var INTERNAL = _dereq_('./INTERNAL'); - -module.exports = resolve; - -var FALSE = new Promise(INTERNAL).resolve(false); -var NULL = new Promise(INTERNAL).resolve(null); -var UNDEFINED = new Promise(INTERNAL).resolve(void 0); -var ZERO = new Promise(INTERNAL).resolve(0); -var EMPTYSTRING = new Promise(INTERNAL).resolve(''); - -function resolve(value) { - if (value) { - return new Promise(INTERNAL).resolve(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":28,"./promise":33}],36:[function(_dereq_,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; -} -},{}],37:[function(_dereq_,module,exports){ -'use strict'; - -var immediate = _dereq_('immediate'); - -module.exports = unwrap; - -function unwrap(promise, func, value) { - immediate(function () { - var returnValue; - try { - returnValue = func(value); - } catch (e) { - return promise.reject(e); - } - if (returnValue === promise) { - promise.reject(new TypeError('Cannot resolve promise with itself')); - } else { - promise.resolve(returnValue); - } - }); -} -},{"immediate":39}],38:[function(_dereq_,module,exports){ -'use strict'; -exports.test = function () { - return false; -}; -},{}],39:[function(_dereq_,module,exports){ -'use strict'; -var types = [ - _dereq_('./nextTick'), - _dereq_('./mutation'), - _dereq_('./postMessage'), - _dereq_('./messageChannel'), - _dereq_('./stateChange'), - _dereq_('./timeout') -]; -var handlerQueue = []; -function drainQueue() { - var i = 0, - task, - innerQueue = handlerQueue; - handlerQueue = []; - while ((task = innerQueue[i++])) { - task(); - } -} -var nextTick; -var i = -1; -var len = types.length; -while (++ i < len) { - if (types[i].test()) { - nextTick = types[i].install(drainQueue); - break; - } -} -module.exports = function (task) { - var len, i, args; - var nTask = task; - if (arguments.length > 1 && typeof task === 'function') { - args = new Array(arguments.length - 1); - i = 0; - while (++i < arguments.length) { - args[i - 1] = arguments[i]; - } - nTask = function () { - task.apply(undefined, args); - }; - } - if ((len = handlerQueue.push(nTask)) === 1) { - nextTick(drainQueue); - } - return len; -}; -module.exports.clear = function (n) { - if (n <= handlerQueue.length) { - handlerQueue[n - 1] = function () {}; - } - return this; -}; - -},{"./messageChannel":40,"./mutation":41,"./nextTick":38,"./postMessage":42,"./stateChange":43,"./timeout":44}],40:[function(_dereq_,module,exports){ -(function (global){ -'use strict'; - -exports.test = function () { - 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 self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],41:[function(_dereq_,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 self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],42:[function(_dereq_,module,exports){ -(function (global){ -'use strict'; -// The test against `importScripts` prevents this implementation from being installed inside a web worker, -// where `global.postMessage` means something completely different and can't be used for this purpose. - -exports.test = function () { - if (!global.postMessage || global.importScripts) { - return false; - } - - var postMessageIsAsynchronous = true; - var oldOnMessage = global.onmessage; - global.onmessage = function () { - postMessageIsAsynchronous = false; - }; - global.postMessage('', '*'); - global.onmessage = oldOnMessage; - - return postMessageIsAsynchronous; -}; - -exports.install = function (func) { - var codeWord = 'com.calvinmetcalf.setImmediate' + Math.random(); - function globalMessage(event) { - if (event.source === global && event.data === codeWord) { - func(); - } - } - if (global.addEventListener) { - global.addEventListener('message', globalMessage, false); - } else { - global.attachEvent('onmessage', globalMessage); - } - return function () { - global.postMessage(codeWord, '*'); - }; -}; -}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],43:[function(_dereq_,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 <script> 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 self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],44:[function(_dereq_,module,exports){ -'use strict'; -exports.test = function () { - return true; -}; - -exports.install = function (t) { - return function () { - setTimeout(t, 0); - }; -}; -},{}],45:[function(_dereq_,module,exports){ -!function(a,b){"function"==typeof define&&define.amd?define(b):"object"==typeof exports?module.exports=b():a.md5=b()}(this,function(){function a(a,b){var g=a[0],h=a[1],i=a[2],j=a[3];g=c(g,h,i,j,b[0],7,-680876936),j=c(j,g,h,i,b[1],12,-389564586),i=c(i,j,g,h,b[2],17,606105819),h=c(h,i,j,g,b[3],22,-1044525330),g=c(g,h,i,j,b[4],7,-176418897),j=c(j,g,h,i,b[5],12,1200080426),i=c(i,j,g,h,b[6],17,-1473231341),h=c(h,i,j,g,b[7],22,-45705983),g=c(g,h,i,j,b[8],7,1770035416),j=c(j,g,h,i,b[9],12,-1958414417),i=c(i,j,g,h,b[10],17,-42063),h=c(h,i,j,g,b[11],22,-1990404162),g=c(g,h,i,j,b[12],7,1804603682),j=c(j,g,h,i,b[13],12,-40341101),i=c(i,j,g,h,b[14],17,-1502002290),h=c(h,i,j,g,b[15],22,1236535329),g=d(g,h,i,j,b[1],5,-165796510),j=d(j,g,h,i,b[6],9,-1069501632),i=d(i,j,g,h,b[11],14,643717713),h=d(h,i,j,g,b[0],20,-373897302),g=d(g,h,i,j,b[5],5,-701558691),j=d(j,g,h,i,b[10],9,38016083),i=d(i,j,g,h,b[15],14,-660478335),h=d(h,i,j,g,b[4],20,-405537848),g=d(g,h,i,j,b[9],5,568446438),j=d(j,g,h,i,b[14],9,-1019803690),i=d(i,j,g,h,b[3],14,-187363961),h=d(h,i,j,g,b[8],20,1163531501),g=d(g,h,i,j,b[13],5,-1444681467),j=d(j,g,h,i,b[2],9,-51403784),i=d(i,j,g,h,b[7],14,1735328473),h=d(h,i,j,g,b[12],20,-1926607734),g=e(g,h,i,j,b[5],4,-378558),j=e(j,g,h,i,b[8],11,-2022574463),i=e(i,j,g,h,b[11],16,1839030562),h=e(h,i,j,g,b[14],23,-35309556),g=e(g,h,i,j,b[1],4,-1530992060),j=e(j,g,h,i,b[4],11,1272893353),i=e(i,j,g,h,b[7],16,-155497632),h=e(h,i,j,g,b[10],23,-1094730640),g=e(g,h,i,j,b[13],4,681279174),j=e(j,g,h,i,b[0],11,-358537222),i=e(i,j,g,h,b[3],16,-722521979),h=e(h,i,j,g,b[6],23,76029189),g=e(g,h,i,j,b[9],4,-640364487),j=e(j,g,h,i,b[12],11,-421815835),i=e(i,j,g,h,b[15],16,530742520),h=e(h,i,j,g,b[2],23,-995338651),g=f(g,h,i,j,b[0],6,-198630844),j=f(j,g,h,i,b[7],10,1126891415),i=f(i,j,g,h,b[14],15,-1416354905),h=f(h,i,j,g,b[5],21,-57434055),g=f(g,h,i,j,b[12],6,1700485571),j=f(j,g,h,i,b[3],10,-1894986606),i=f(i,j,g,h,b[10],15,-1051523),h=f(h,i,j,g,b[1],21,-2054922799),g=f(g,h,i,j,b[8],6,1873313359),j=f(j,g,h,i,b[15],10,-30611744),i=f(i,j,g,h,b[6],15,-1560198380),h=f(h,i,j,g,b[13],21,1309151649),g=f(g,h,i,j,b[4],6,-145523070),j=f(j,g,h,i,b[11],10,-1120210379),i=f(i,j,g,h,b[2],15,718787259),h=f(h,i,j,g,b[9],21,-343485551),a[0]=l(g,a[0]),a[1]=l(h,a[1]),a[2]=l(i,a[2]),a[3]=l(j,a[3])}function b(a,b,c,d,e,f){return b=l(l(b,a),l(d,f)),l(b<<e|b>>>32-e,c)}function c(a,c,d,e,f,g,h){return b(c&d|~c&e,a,c,f,g,h)}function d(a,c,d,e,f,g,h){return b(c&e|d&~e,a,c,f,g,h)}function e(a,c,d,e,f,g,h){return b(c^d^e,a,c,f,g,h)}function f(a,c,d,e,f,g,h){return b(d^(c|~e),a,c,f,g,h)}function g(b){txt="";var c,d=b.length,e=[1732584193,-271733879,-1732584194,271733878];for(c=64;c<=b.length;c+=64)a(e,h(b.substring(c-64,c)));b=b.substring(c-64);var f=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];for(c=0;c<b.length;c++)f[c>>2]|=b.charCodeAt(c)<<(c%4<<3);if(f[c>>2]|=128<<(c%4<<3),c>55)for(a(e,f),c=0;16>c;c++)f[c]=0;return f[14]=8*d,a(e,f),e}function h(a){var b,c=[];for(b=0;64>b;b+=4)c[b>>2]=a.charCodeAt(b)+(a.charCodeAt(b+1)<<8)+(a.charCodeAt(b+2)<<16)+(a.charCodeAt(b+3)<<24);return c}function i(a){for(var b="",c=0;4>c;c++)b+=m[a>>8*c+4&15]+m[a>>8*c&15];return b}function j(a){for(var b=0;b<a.length;b++)a[b]=i(a[b]);return a.join("")}function k(a){return j(g(a))}function l(a,b){return a+b&4294967295}function l(a,b){var c=(65535&a)+(65535&b),d=(a>>16)+(b>>16)+(c>>16);return d<<16|65535&c}var m="0123456789abcdef".split("");return"5d41402abc4b2a76b9719d911017c592"!=k("hello"),k}); -},{}],46:[function(_dereq_,module,exports){ -'use strict'; - -var upsert = _dereq_('./upsert'); -var utils = _dereq_('./utils'); -var Promise = utils.Promise; - -module.exports = function (opts) { - var sourceDB = opts.db; - var viewName = opts.viewName; - var mapFun = opts.map; - var reduceFun = opts.reduce; - var randomizer = opts.randomizer; - - var viewSignature = mapFun.toString() + (reduceFun && reduceFun.toString()) + - (randomizer && randomizer.toString()); - - if (sourceDB._cachedViews) { - var cachedView = sourceDB._cachedViews[viewSignature]; - if (cachedView) { - return Promise.resolve(cachedView); - } - } - - return sourceDB.info().then(function (info) { - var depDbName = info.db_name + '-mrview-' + utils.MD5(viewSignature); - - // save the view name in the source PouchDBVersion220 so it can be cleaned up if necessary - // (e.g. when the _design doc is deleted, remove all associated view data) - function diffFunction(doc) { - doc.views = doc.views || {}; - var depDbs = doc.views[viewName] = doc.views[viewName] || {}; - /* istanbul ignore if */ - if (depDbs[depDbName]) { - return; // no update necessary - } - depDbs[depDbName] = true; - return doc; - } - return upsert(sourceDB, '_local/mrviews', diffFunction).then(function () { - return sourceDB.registerDependentDatabase(depDbName).then(function (res) { - var db = res.db; - db.auto_compaction = true; - var view = { - name: depDbName, - db: db, - sourceDB: sourceDB, - adapter: sourceDB.adapter, - mapFun: mapFun, - reduceFun: reduceFun - }; - return view.db.get('_local/lastSeq').then(null, function (err) { - /* istanbul ignore if */ - if (err.name !== 'not_found') { - throw err; - } - }).then(function (lastSeqDoc) { - view.seq = lastSeqDoc ? lastSeqDoc.seq : 0; - if (!randomizer) { - // randomizer implies the view is temporary, no need to cache it - sourceDB._cachedViews = sourceDB._cachedViews || {}; - sourceDB._cachedViews[viewSignature] = view; - view.db.on('destroyed', function () { - delete sourceDB._cachedViews[viewSignature]; - }); - } - return view; - }); - }); - }); - }); -}; - -},{"./upsert":52,"./utils":53}],47:[function(_dereq_,module,exports){ -'use strict'; - -module.exports = function (func, emit, sum, log, isArray, toJSON) { - /*jshint evil:true,unused:false */ - return eval("'use strict'; (" + func + ");"); -}; - -},{}],48:[function(_dereq_,module,exports){ -'use strict'; - -var pouchCollate = _dereq_('pouchdb-collate'); -var TaskQueue = _dereq_('./taskqueue'); -var collate = pouchCollate.collate; -var toIndexableString = pouchCollate.toIndexableString; -var normalizeKey = pouchCollate.normalizeKey; -var createView = _dereq_('./create-view'); -var evalFunc = _dereq_('./evalfunc'); -var log; -/* istanbul ignore else */ -if ((typeof console !== 'undefined') && (typeof console.log === 'function')) { - log = Function.prototype.bind.call(console.log, console); -} else { - log = function () {}; -} -var utils = _dereq_('./utils'); -var Promise = utils.Promise; -var mainQueue = new TaskQueue(); -var CHANGES_BATCH_SIZE = 50; - -function parseViewName(name) { - // can be either 'ddocname/viewname' or just 'viewname' - // (where the ddoc name is the same) - return name.indexOf('/') === -1 ? [name, name] : name.split('/'); -} - -function tryCode(db, fun, args) { - // emit an event if there was an error thrown by a map/reduce function. - // putting try/catches in a single function also avoids deoptimizations. - try { - return { - output : fun.apply(null, args) - }; - } catch (e) { - db.emit('error', e); - return {error : e}; - } -} - -function sortByKeyThenValue(x, y) { - var keyCompare = collate(x.key, y.key); - return keyCompare !== 0 ? keyCompare : collate(x.value, y.value); -} - -function sliceResults(results, limit, skip) { - skip = skip || 0; - if (typeof limit === 'number') { - return results.slice(skip, limit + skip); - } else if (skip > 0) { - return results.slice(skip); - } - return results; -} - -function createBuiltInError(name) { - var error = new Error('builtin ' + name + - ' function requires map values to be numbers' + - ' or number arrays'); - error.name = 'invalid_value'; - error.status = 500; - return error; -} - -function sum(values) { - var result = 0; - for (var i = 0, len = values.length; i < len; i++) { - var num = values[i]; - if (typeof num !== 'number') { - if (Array.isArray(num)) { - // lists of numbers are also allowed, sum them separately - result = typeof result === 'number' ? [result] : result; - for (var j = 0, jLen = num.length; j < jLen; j++) { - var jNum = num[j]; - if (typeof jNum !== 'number') { - throw createBuiltInError('_sum'); - } else if (typeof result[j] === 'undefined') { - result.push(jNum); - } else { - result[j] += jNum; - } - } - } else { // not array/number - throw createBuiltInError('_sum'); - } - } else if (typeof result === 'number') { - result += num; - } else { // add number to array - result[0] += num; - } - } - return result; -} - -var builtInReduce = { - _sum: function (keys, values) { - return sum(values); - }, - - _count: function (keys, values) { - return values.length; - }, - - _stats: function (keys, values) { - // no need to implement rereduce=true, because Pouch - // will never call it - function sumsqr(values) { - var _sumsqr = 0; - for (var i = 0, len = values.length; i < len; i++) { - var num = values[i]; - _sumsqr += (num * num); - } - return _sumsqr; - } - return { - sum : sum(values), - min : Math.min.apply(null, values), - max : Math.max.apply(null, values), - count : values.length, - sumsqr : sumsqr(values) - }; - } -}; - -function addHttpParam(paramName, opts, params, asJson) { - // add an http param from opts to params, optionally json-encoded - var val = opts[paramName]; - if (typeof val !== 'undefined') { - if (asJson) { - val = encodeURIComponent(JSON.stringify(val)); - } - params.push(paramName + '=' + val); - } -} - -function checkQueryParseError(options, fun) { - var startkeyName = options.descending ? 'endkey' : 'startkey'; - var endkeyName = options.descending ? 'startkey' : 'endkey'; - - if (typeof options[startkeyName] !== 'undefined' && - typeof options[endkeyName] !== 'undefined' && - collate(options[startkeyName], options[endkeyName]) > 0) { - throw new QueryParseError('No rows can match your key range, reverse your ' + - 'start_key and end_key or set {descending : true}'); - } else if (fun.reduce && options.reduce !== false) { - if (options.include_docs) { - throw new QueryParseError('{include_docs:true} is invalid for reduce'); - } else if (options.keys && options.keys.length > 1 && - !options.group && !options.group_level) { - throw new QueryParseError('Multi-key fetches for reduce views must use {group: true}'); - } - } - if (options.group_level) { - if (typeof options.group_level !== 'number') { - throw new QueryParseError('Invalid value for integer: "' + options.group_level + '"'); - } - if (options.group_level < 0) { - throw new QueryParseError('Invalid value for positive integer: ' + - '"' + options.group_level + '"'); - } - } -} - -function httpQuery(db, fun, opts) { - // List of parameters to add to the PUT request - var params = []; - var body; - var method = 'GET'; - - // If opts.reduce exists and is defined, then add it to the list - // of parameters. - // If reduce=false then the results are that of only the map function - // not the final result of map and reduce. - addHttpParam('reduce', opts, params); - addHttpParam('include_docs', opts, params); - addHttpParam('limit', opts, params); - addHttpParam('descending', opts, params); - addHttpParam('group', opts, params); - addHttpParam('group_level', opts, params); - addHttpParam('skip', opts, params); - addHttpParam('startkey', opts, params, true); - addHttpParam('endkey', opts, params, true); - addHttpParam('inclusive_end', opts, params); - addHttpParam('key', opts, params, true); - - // Format the list of parameters into a valid URI query string - params = params.join('&'); - params = params === '' ? '' : '?' + params; - - // If keys are supplied, issue a POST request to circumvent GET query string limits - // see http://wiki.apache.org/couchdb/HTTP_view_API#Querying_Options - if (typeof opts.keys !== 'undefined') { - var MAX_URL_LENGTH = 2000; - // according to http://stackoverflow.com/a/417184/680742, - // the de facto URL length limit is 2000 characters - - var keysAsString = - 'keys=' + encodeURIComponent(JSON.stringify(opts.keys)); - if (keysAsString.length + params.length + 1 <= MAX_URL_LENGTH) { - // If the keys are short enough, do a GET. we do this to work around - // Safari not understanding 304s on POSTs (see pouchdb/pouchdb#1239) - params += (params[0] === '?' ? '&' : '?') + keysAsString; - } else { - method = 'POST'; - if (typeof fun === 'string') { - body = JSON.stringify({keys: opts.keys}); - } else { // fun is {map : mapfun}, so append to this - fun.keys = opts.keys; - } - } - } - - // We are referencing a query defined in the design doc - if (typeof fun === 'string') { - var parts = parseViewName(fun); - return db.request({ - method: method, - url: '_design/' + parts[0] + '/_view/' + parts[1] + params, - body: body - }); - } - - // We are using a temporary view, terrible for performance but good for testing - body = body || {}; - Object.keys(fun).forEach(function (key) { - if (Array.isArray(fun[key])) { - body[key] = fun[key]; - } else { - body[key] = fun[key].toString(); - } - }); - return db.request({ - method: 'POST', - url: '_temp_view' + params, - body: body - }); -} - -function defaultsTo(value) { - return function (reason) { - /* istanbul ignore else */ - if (reason.name === 'not_found') { - return value; - } else { - throw reason; - } - }; -} -function saveKeyValues(view, docIdsToEmits, seq) { - return view.db.get('_local/lastSeq') - .then(null, defaultsTo({_id: '_local/lastSeq', seq: 0})) - .then(function (lastSeqDoc) { - return Promise.all(Object.keys(docIdsToEmits).map(function (docId) { - return view.db.get('_local/doc_' + docId) - .then(null, defaultsTo({_id : '_local/doc_' + docId, keys : []})) - .then(function (metaDoc) { - return view.db.allDocs({keys : metaDoc.keys, include_docs : true}).then(function (res) { - var kvDocs = res.rows.map(function (row) { - return row.doc; - }).filter(function (row) { - return row; - }); - - var indexableKeysToKeyValues = docIdsToEmits[docId]; - var oldKeysMap = {}; - kvDocs.forEach(function (kvDoc) { - oldKeysMap[kvDoc._id] = true; - kvDoc._deleted = !indexableKeysToKeyValues[kvDoc._id]; - if (!kvDoc._deleted) { - kvDoc.value = indexableKeysToKeyValues[kvDoc._id]; - } - }); - - var newKeys = Object.keys(indexableKeysToKeyValues); - newKeys.forEach(function (key) { - if (!oldKeysMap[key]) { - // new doc - kvDocs.push({ - _id : key, - value : indexableKeysToKeyValues[key] - }); - } - }); - metaDoc.keys = utils.uniq(newKeys.concat(metaDoc.keys)); - kvDocs.push(metaDoc); - - return kvDocs; - }); - }); - })).then(function (listOfDocsToPersist) { - var docsToPersist = []; - listOfDocsToPersist.forEach(function (docList) { - docsToPersist = docsToPersist.concat(docList); - }); - - lastSeqDoc.seq = seq; - docsToPersist.push(lastSeqDoc); - - return view.db.bulkDocs({docs : docsToPersist}); - }); - }); -} - -var updateView = utils.sequentialize(mainQueue, function (view) { - // bind the emit function once - var mapResults; - var doc; - - function emit(key, value) { - mapResults.push({ - id : doc._id, - key : normalizeKey(key), - value : normalizeKey(value) - }); - } - - var mapFun; - // for temp_views one can use emit(doc, emit), see #38 - if (typeof view.mapFun === "function" && view.mapFun.length === 2) { - var origMap = view.mapFun; - mapFun = function (doc) { - return origMap(doc, emit); - }; - } else { - mapFun = evalFunc(view.mapFun.toString(), emit, sum, log, Array.isArray, JSON.parse); - } - - var currentSeq = view.seq || 0; - - function processChange(docIdsToEmits, seq) { - return function () { - return saveKeyValues(view, docIdsToEmits, seq); - }; - } - var queue = new TaskQueue(); - // TODO(neojski): https://github.com/daleharvey/pouchdb/issues/1521 - - return new Promise(function (resolve, reject) { - - function complete() { - queue.finish().then(function () { - view.seq = currentSeq; - resolve(); - }); - } - - function processNextBatch() { - view.sourceDB.changes({ - conflicts: true, - include_docs: true, - since : currentSeq, - limit : CHANGES_BATCH_SIZE - }).on('complete', function (response) { - var results = response.results; - if (!results.length) { - return complete(); - } - var docIdsToEmits = {}; - for (var i = 0, l = results.length; i < l; i++) { - var change = results[i]; - if (change.doc._id[0] !== '_') { - mapResults = []; - doc = change.doc; - - if (!doc._deleted) { - tryCode(view.sourceDB, mapFun, [doc]); - } - mapResults.sort(sortByKeyThenValue); - - var indexableKeysToKeyValues = {}; - for (var j = 0, jl = mapResults.length; j < jl; j++) { - var obj = mapResults[j]; - var indexableKey = toIndexableString([obj.key, obj.id, j]); - indexableKeysToKeyValues[indexableKey] = obj; - } - docIdsToEmits[change.doc._id] = indexableKeysToKeyValues; - } - currentSeq = change.seq; - } - queue.add(processChange(docIdsToEmits, currentSeq)); - if (results.length < CHANGES_BATCH_SIZE) { - return complete(); - } - return processNextBatch(); - }).on('error', onError); - /* istanbul ignore next */ - function onError(err) { - reject(err); - } - } - processNextBatch(); - }); -}); - -function reduceView(view, results, options) { - if (options.group_level === 0) { - delete options.group_level; - } - - var shouldGroup = options.group || options.group_level; - - var reduceFun; - if (builtInReduce[view.reduceFun]) { - reduceFun = builtInReduce[view.reduceFun]; - } else { - reduceFun = evalFunc( - view.reduceFun.toString(), null, sum, log, Array.isArray, JSON.parse); - } - - var groups = []; - var lvl = options.group_level; - results.forEach(function (e) { - var last = groups[groups.length - 1]; - var key = shouldGroup ? e.key : null; - - // only set group_level for array keys - if (shouldGroup && Array.isArray(key) && typeof lvl === 'number') { - key = key.length > lvl ? key.slice(0, lvl) : key; - } - - if (last && collate(last.key[0][0], key) === 0) { - last.key.push([key, e.id]); - last.value.push(e.value); - return; - } - groups.push({key: [ - [key, e.id] - ], value: [e.value]}); - }); - for (var i = 0, len = groups.length; i < len; i++) { - var e = groups[i]; - var reduceTry = tryCode(view.sourceDB, reduceFun, [e.key, e.value, false]); - // CouchDB typically just sets the value to null if reduce errors out - e.value = reduceTry.error ? null : reduceTry.output; - e.key = e.key[0][0]; - } - // no total_rows/offset when reducing - return {rows: sliceResults(groups, options.limit, options.skip)}; -} - -var queryView = utils.sequentialize(mainQueue, function (view, opts) { - var totalRows; - var shouldReduce = view.reduceFun && opts.reduce !== false; - var skip = opts.skip || 0; - if (typeof opts.keys !== 'undefined' && !opts.keys.length) { - // equivalent query - opts.limit = 0; - delete opts.keys; - } - - function fetchFromView(viewOpts) { - viewOpts.include_docs = true; - return view.db.allDocs(viewOpts).then(function (res) { - totalRows = res.total_rows; - return res.rows.map(function (result) { - return result.doc.value; - }); - }); - } - - function onMapResultsReady(results) { - var res; - if (shouldReduce) { - res = reduceView(view, results, opts); - } else { - res = { - total_rows: totalRows, - offset: skip, - rows: results - }; - } - if (opts.include_docs) { - var getDocsPromises = results.map(function (row) { - var val = row.value; - var docId = (val && typeof val === 'object' && val._id) || row.id; - return view.sourceDB.get(docId).then(function (joinedDoc) { - row.doc = joinedDoc; - }, function () { - // document error = don't join - }); - }); - return Promise.all(getDocsPromises).then(function () { - return res; - }); - } else { - return res; - } - } - - var flatten = function (array) { - return array.reduce(function (prev, cur) { - return prev.concat(cur); - }); - }; - - if (typeof opts.keys !== 'undefined') { - var keys = opts.keys; - var fetchPromises = keys.map(function (key) { - var viewOpts = { - startkey : toIndexableString([key]), - endkey : toIndexableString([key, {}]) - }; - return fetchFromView(viewOpts); - }); - return Promise.all(fetchPromises).then(flatten).then(onMapResultsReady); - } else { // normal query, no 'keys' - var viewOpts = { - descending : opts.descending - }; - if (typeof opts.startkey !== 'undefined') { - viewOpts.startkey = opts.descending ? - toIndexableString([opts.startkey, {}]) : - toIndexableString([opts.startkey]); - } - if (typeof opts.endkey !== 'undefined') { - var inclusiveEnd = opts.inclusive_end !== false; - if (opts.descending) { - inclusiveEnd = !inclusiveEnd; - } - - viewOpts.endkey = toIndexableString(inclusiveEnd ? [opts.endkey, {}] : [opts.endkey]); - } - if (typeof opts.key !== 'undefined') { - var keyStart = toIndexableString([opts.key]); - var keyEnd = toIndexableString([opts.key, {}]); - if (viewOpts.descending) { - viewOpts.endkey = keyStart; - viewOpts.startkey = keyEnd; - } else { - viewOpts.startkey = keyStart; - viewOpts.endkey = keyEnd; - } - } - if (!shouldReduce) { - if (typeof opts.limit === 'number') { - viewOpts.limit = opts.limit; - } - viewOpts.skip = skip; - } - return fetchFromView(viewOpts).then(onMapResultsReady); - } -}); - -function httpViewCleanup(db) { - return db.request({ - method: 'POST', - url: '_view_cleanup' - }); -} - -var localViewCleanup = utils.sequentialize(mainQueue, function (db) { - return db.get('_local/mrviews').then(function (metaDoc) { - var docsToViews = {}; - Object.keys(metaDoc.views).forEach(function (fullViewName) { - var parts = fullViewName.split('/'); - var designDocName = '_design/' + parts[0]; - var viewName = parts[1]; - docsToViews[designDocName] = docsToViews[designDocName] || {}; - docsToViews[designDocName][viewName] = true; - }); - var opts = { - keys : Object.keys(docsToViews), - include_docs : true - }; - return db.allDocs(opts).then(function (res) { - var viewsToStatus = {}; - res.rows.forEach(function (row) { - Object.keys(docsToViews[row.key]).forEach(function (viewName) { - var viewDBNames = Object.keys(metaDoc.views[row.key.substring(8) + '/' + viewName]); - // design doc deleted, or view function nonexistent - var statusIsGood = row.doc && row.doc.views && row.doc.views[viewName]; - viewDBNames.forEach(function (viewDBName) { - viewsToStatus[viewDBName] = viewsToStatus[viewDBName] || statusIsGood; - }); - }); - }); - var dbsToDelete = Object.keys(viewsToStatus).filter(function (viewDBName) { - return !viewsToStatus[viewDBName]; - }); - var destroyPromises = dbsToDelete.map(function (viewDBName) { - return db.constructor.destroy(viewDBName, {adapter : db.adapter}); - }); - return Promise.all(destroyPromises).then(function () { - return {ok: true}; - }); - }); - }, defaultsTo({ok: true})); -}); - -exports.viewCleanup = utils.callbackify(function () { - var db = this; - if (db.type() === 'http') { - return httpViewCleanup(db); - } - return localViewCleanup(db); -}); - -function queryPromised(db, fun, opts) { - if (db.type() === 'http') { - return httpQuery(db, fun, opts); - } - - if (typeof fun !== 'string') { - // temp_view - checkQueryParseError(opts, fun); - - var randomizer = Math.round(Math.random() * 1000000) + 1; - var createViewOpts = { - db : db, - viewName : 'temp_view/temp_view', - map : fun.map, - reduce : fun.reduce, - randomizer : randomizer - }; - return createView(createViewOpts).then(function (view) { - function cleanup() { - return view.db.destroy(); - } - return utils.fin(updateView(view).then(function () { - return queryView(view, opts); - }), cleanup); - }); - } else { - // persistent view - var fullViewName = fun; - var parts = parseViewName(fullViewName); - var designDocName = parts[0]; - var viewName = parts[1]; - return db.get('_design/' + designDocName).then(function (doc) { - var fun = doc.views && doc.views[viewName]; - - if (!fun || typeof fun.map !== 'string') { - var error = new Error('ddoc ' + designDocName + ' has no view named ' + - viewName); - error.name = 'not_found'; - error.status = 400; - throw error; - } - checkQueryParseError(opts, fun); - - var createViewOpts = { - db : db, - viewName : fullViewName, - map : fun.map, - reduce : fun.reduce - }; - return createView(createViewOpts).then(function (view) { - if (opts.stale === 'ok' || opts.stale === 'update_after') { - if (opts.stale === 'update_after') { - updateView(view); - } - return queryView(view, opts); - } else { // stale not ok - return updateView(view).then(function () { - return queryView(view, opts); - }); - } - }); - }); - } -} - -exports.query = function (fun, opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - opts = utils.extend({}, opts); - - if (typeof fun === 'function') { - fun = {map : fun}; - } - - var db = this; - var promise = Promise.resolve().then(function () { - return queryPromised(db, fun, opts); - }); - utils.promisedCallback(promise, callback); - return promise; -}; - -exports.putView = function (name, fun, rev, opts, callback) { - if (typeof rev === 'object') { - callback = opts; - opts = rev; - rev = null; - } else if (typeof rev === 'function') { - callback = rev; - rev = opts = null; - } else if (typeof opts === 'function') { - callback = opts; - opts = null; - } - opts = utils.extend({}, opts || {}); - - if (typeof fun === 'function' || typeof fun === 'string') { - fun = {map : fun}; - } - - var error; - - if (typeof name !== 'string') { - error = new Error('you must supply a design doc/view name'); - error.name = 'putview_error'; - error.status = 400; - return utils.promisedCallback(Promise.reject(error), callback); - } else if (!fun || ['function', 'string'].indexOf(typeof fun.map) === -1) { - error = new Error('you must supply a map function'); - error.name = 'putview_error'; - error.status = 400; - return utils.promisedCallback(Promise.reject(error), callback); - } - - if (typeof fun.map === 'function') { - fun.map = fun.map.toString(); - } - if (typeof fun.reduce === 'function') { - fun.reduce = fun.reduce.toString(); - } - - var parts = name.split('/'); - var designDocName = '_design/' + parts[0]; - var viewName = parts[1]; - - var doc = { - _id : designDocName, - views : {} - }; - doc.views[viewName] = fun; - if (rev) { - doc._rev = rev; - } - - return this.put(doc, callback); -}; - -function QueryParseError(message) { - this.status = 400; - this.name = 'query_parse_error'; - this.message = message; - this.error = true; - try { - Error.captureStackTrace(this, QueryParseError); - } catch (e) {} -} - -utils.inherits(QueryParseError, Error); - -},{"./create-view":46,"./evalfunc":47,"./taskqueue":51,"./utils":53,"pouchdb-collate":49}],49:[function(_dereq_,module,exports){ -'use strict'; - -var MIN_MAGNITUDE = -324; // verified by -Number.MIN_VALUE -var MAGNITUDE_DIGITS = 3; // ditto -var SEP = ''; // set to '_' for easier debugging - -var utils = _dereq_('./utils'); - -exports.collate = function (a, b) { - - if (a === b) { - return 0; - } - - a = exports.normalizeKey(a); - b = exports.normalizeKey(b); - - var ai = collationIndex(a); - var bi = collationIndex(b); - if ((ai - bi) !== 0) { - return ai - bi; - } - if (a === null) { - return 0; - } - switch (typeof a) { - case 'number': - return a - b; - case 'boolean': - return a === b ? 0 : (a < b ? -1 : 1); - case 'string': - return stringCollate(a, b); - } - return Array.isArray(a) ? arrayCollate(a, b) : objectCollate(a, b); -}; - -// couch considers null/NaN/Infinity/-Infinity === undefined, -// for the purposes of mapreduce indexes. also, dates get stringified. -exports.normalizeKey = function (key) { - switch (typeof key) { - case 'undefined': - return null; - case 'number': - if (key === Infinity || key === -Infinity || isNaN(key)) { - return null; - } - return key; - case 'object': - var origKey = key; - if (Array.isArray(key)) { - var len = key.length; - key = new Array(len); - for (var i = 0; i < len; i++) { - key[i] = exports.normalizeKey(origKey[i]); - } - } else if (key instanceof Date) { - return key.toJSON(); - } else if (key !== null) { // generic object - key = {}; - for (var k in origKey) { - if (origKey.hasOwnProperty(k)) { - var val = origKey[k]; - if (typeof val !== 'undefined') { - key[k] = exports.normalizeKey(val); - } - } - } - } - } - return key; -}; - -function indexify(key) { - if (key !== null) { - switch (typeof key) { - case 'boolean': - return key ? 1 : 0; - case 'number': - return numToIndexableString(key); - case 'string': - // We've to be sure that key does not contain \u0000 - // Do order-preserving replacements: - // 0 -> 1, 1 - // 1 -> 1, 2 - // 2 -> 2, 2 - return key - .replace(/\u0002/g, '\u0002\u0002') - .replace(/\u0001/g, '\u0001\u0002') - .replace(/\u0000/g, '\u0001\u0001'); - case 'object': - var isArray = Array.isArray(key); - var arr = isArray ? key : Object.keys(key); - var i = -1; - var len = arr.length; - var result = ''; - if (isArray) { - while (++i < len) { - result += exports.toIndexableString(arr[i]); - } - } else { - while (++i < len) { - var objKey = arr[i]; - result += exports.toIndexableString(objKey) + - exports.toIndexableString(key[objKey]); - } - } - return result; - } - } - return ''; -} - -// convert the given key to a string that would be appropriate -// for lexical sorting, e.g. within a database, where the -// sorting is the same given by the collate() function. -exports.toIndexableString = function (key) { - var zero = '\u0000'; - key = exports.normalizeKey(key); - return collationIndex(key) + SEP + indexify(key) + zero; -}; - -function arrayCollate(a, b) { - var len = Math.min(a.length, b.length); - for (var i = 0; i < len; i++) { - var sort = exports.collate(a[i], b[i]); - if (sort !== 0) { - return sort; - } - } - return (a.length === b.length) ? 0 : - (a.length > b.length) ? 1 : -1; -} -function stringCollate(a, b) { - // See: https://github.com/daleharvey/pouchdb/issues/40 - // This is incompatible with the CouchDB implementation, but its the - // best we can do for now - return (a === b) ? 0 : ((a > b) ? 1 : -1); -} -function objectCollate(a, b) { - var ak = Object.keys(a), bk = Object.keys(b); - var len = Math.min(ak.length, bk.length); - for (var i = 0; i < len; i++) { - // First sort the keys - var sort = exports.collate(ak[i], bk[i]); - if (sort !== 0) { - return sort; - } - // if the keys are equal sort the values - sort = exports.collate(a[ak[i]], b[bk[i]]); - if (sort !== 0) { - return sort; - } - - } - return (ak.length === bk.length) ? 0 : - (ak.length > bk.length) ? 1 : -1; -} -// The collation is defined by erlangs ordered terms -// the atoms null, true, false come first, then numbers, strings, -// arrays, then objects -// null/undefined/NaN/Infinity/-Infinity are all considered null -function collationIndex(x) { - var id = ['boolean', 'number', 'string', 'object']; - var idx = id.indexOf(typeof x); - //false if -1 otherwise true, but fast!!!!1 - if (~idx) { - if (x === null) { - return 1; - } - if (Array.isArray(x)) { - return 5; - } - return idx < 3 ? (idx + 2) : (idx + 3); - } - if (Array.isArray(x)) { - return 5; - } -} - -// conversion: -// x yyy zz...zz -// x = 0 for negative, 1 for 0, 2 for positive -// y = exponent (for negative numbers negated) moved so that it's >= 0 -// z = mantisse -function numToIndexableString(num) { - - if (num === 0) { - return '1'; - } - - // convert number to exponential format for easier and - // more succinct string sorting - var expFormat = num.toExponential().split(/e\+?/); - var magnitude = parseInt(expFormat[1], 10); - - var neg = num < 0; - - var result = neg ? '0' : '2'; - - // first sort by magnitude - // it's easier if all magnitudes are positive - var magForComparison = ((neg ? -magnitude : magnitude) - MIN_MAGNITUDE); - var magString = utils.padLeft((magForComparison).toString(), '0', MAGNITUDE_DIGITS); - - result += SEP + magString; - - // then sort by the factor - var factor = Math.abs(parseFloat(expFormat[0])); // [1..10) - if (neg) { // for negative reverse ordering - factor = 10 - factor; - } - - var factorStr = factor.toFixed(20); - - // strip zeros from the end - factorStr = factorStr.replace(/\.?0+$/, ''); - - result += SEP + factorStr; - - return result; -} - -},{"./utils":50}],50:[function(_dereq_,module,exports){ -'use strict'; - -function pad(str, padWith, upToLength) { - var padding = ''; - var targetLength = upToLength - str.length; - while (padding.length < targetLength) { - padding += padWith; - } - return padding; -} - -exports.padLeft = function (str, padWith, upToLength) { - var padding = pad(str, padWith, upToLength); - return padding + str; -}; - -exports.padRight = function (str, padWith, upToLength) { - var padding = pad(str, padWith, upToLength); - return str + padding; -}; - -exports.stringLexCompare = function (a, b) { - - var aLen = a.length; - var bLen = b.length; - - var i; - for (i = 0; i < aLen; i++) { - if (i === bLen) { - // b is shorter substring of a - return 1; - } - var aChar = a.charAt(i); - var bChar = b.charAt(i); - if (aChar !== bChar) { - return aChar < bChar ? -1 : 1; - } - } - - if (aLen < bLen) { - // a is shorter substring of b - return -1; - } - - return 0; -}; - -/* - * returns the decimal form for the given integer, i.e. writes - * out all the digits (in base-10) instead of using scientific notation - */ -exports.intToDecimalForm = function (int) { - - var isNeg = int < 0; - var result = ''; - - do { - var remainder = isNeg ? -Math.ceil(int % 10) : Math.floor(int % 10); - - result = remainder + result; - int = isNeg ? Math.ceil(int / 10) : Math.floor(int / 10); - } while (int); - - - if (isNeg && result !== '0') { - result = '-' + result; - } - - return result; -}; -},{}],51:[function(_dereq_,module,exports){ -'use strict'; -/* - * Simple task queue to sequentialize actions. Assumes callbacks will eventually fire (once). - */ - -var Promise = _dereq_('./utils').Promise; - -function TaskQueue() { - this.promise = new Promise(function (fulfill) {fulfill(); }); -} -TaskQueue.prototype.add = function (promiseFactory) { - this.promise = this.promise.then(null, function () { - // just recover - }).then(function () { - return promiseFactory(); - }); - return this.promise; -}; -TaskQueue.prototype.finish = function () { - return this.promise; -}; - -module.exports = TaskQueue; - -},{"./utils":53}],52:[function(_dereq_,module,exports){ -'use strict'; -var Promise = _dereq_('./utils').Promise; - -// this is essentially the "update sugar" function from daleharvey/pouchdb#1388 -// the diffFun tells us what delta to apply to the doc. it either returns -// the doc, or false if it doesn't need to do an update after all -function upsert(db, docId, diffFun) { - return new Promise(function (fulfill, reject) { - if (docId && typeof docId === 'object') { - docId = docId._id; - } - if (typeof docId !== 'string') { - return reject(new Error('doc id is required')); - } - - db.get(docId, function (err, doc) { - if (err) { - if (err.name !== 'not_found') { - return reject(err); - } - return fulfill(tryAndPut(db, diffFun({_id : docId}), diffFun)); - } - var newDoc = diffFun(doc); - if (!newDoc) { - return fulfill(doc); - } - fulfill(tryAndPut(db, newDoc, diffFun)); - }); - }); -} - -function tryAndPut(db, doc, diffFun) { - return db.put(doc).then(null, function (err) { - if (err.name !== 'conflict') { - throw err; - } - return upsert(db, doc, diffFun); - }); -} - -module.exports = upsert; - -},{"./utils":53}],53:[function(_dereq_,module,exports){ -(function (process,global){ -'use strict'; -/* istanbul ignore if */ -if (typeof global.Promise === 'function') { - exports.Promise = global.Promise; -} else { - exports.Promise = _dereq_('lie'); -} -// uniquify a list, similar to underscore's _.uniq -exports.uniq = function (arr) { - var map = {}; - arr.forEach(function (element) { - map[element] = true; - }); - return Object.keys(map); -}; - -exports.inherits = _dereq_('inherits'); -exports.extend = _dereq_('extend'); -var argsarray = _dereq_('argsarray'); - -exports.promisedCallback = function (promise, callback) { - if (callback) { - promise.then(function (res) { - callback(null, res); - }, function (reason) { - callback(reason); - }); - } - return promise; -}; - -exports.callbackify = function (fun) { - return argsarray(function (args) { - var cb = args.pop(); - var promise = fun.apply(this, args); - if (typeof cb === 'function') { - exports.promisedCallback(promise, cb); - } - return promise; - }); -}; - -// Promise finally util similar to Q.finally -exports.fin = function (promise, cb) { - return promise.then(function (res) { - var promise2 = cb(); - if (typeof promise2.then === 'function') { - return promise2.then(function () { - return res; - }); - } - return res; - }, function (reason) { - var promise2 = cb(); - if (typeof promise2.then === 'function') { - return promise2.then(function () { - throw reason; - }); - } - throw reason; - }); -}; - -exports.sequentialize = function (queue, promiseFactory) { - return function () { - var args = arguments; - var that = this; - return queue.add(function () { - return promiseFactory.apply(that, args); - }); - }; -}; - -var crypto = _dereq_('crypto'); -var md5 = _dereq_('md5-jkmyers'); - -exports.MD5 = function (string) { - /* istanbul ignore else */ - if (!process.browser) { - return crypto.createHash('md5').update(string).digest('hex'); - } else { - return md5(string); - } -}; -}).call(this,_dereq_("/Users/daleharvey/src/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"/Users/daleharvey/src/pouchdb/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":25,"argsarray":22,"crypto":23,"extend":26,"inherits":27,"lie":31,"md5-jkmyers":45}]},{},[15]) -(15) -}); \ No newline at end of file
diff --git a/tests/integration/index.html b/tests/integration/index.html deleted file mode 100644 index 3e73adf..0000000 --- a/tests/integration/index.html +++ /dev/null
@@ -1,57 +0,0 @@ -<!doctype html> -<html> - <head> - <meta charset="utf-8"> - <title>Mocha</title> - <link rel="stylesheet" type="text/css" href="../../node_modules/mocha/mocha.css"> - </head> - <body> - <div id="mocha"></div> - <script> - var val = window.location.search.match(/[&\?]es5shims?=([^&\?]+)/); - if (val && val[1] === 'true') { - document.write('<script src="../../node_modules/es5-shim/es5-shim.js"></' + 'script>'); - } - </script> - <script src="../../node_modules/mocha/mocha.js"></script> - <script src="../../node_modules/chai/chai.js"></script> - <script> - mocha.setup({ - timeout:100000, - ui: 'bdd' - }); - var should = chai.should(); - </script> - <script src='deps/pouchdb-1.1.0-postfixed.js'></script> - <script src='deps/pouchdb-2.0.0-postfixed.js'></script> - <script src='deps/pouchdb-2.2.0-postfixed.js'></script> - <script src='deps/pouchdb-3.0.6-postfixed.js'></script> - <script src='utils.js'></script> - <script src='test.aa.setup.js'></script> - <script src='test.basics.js'></script> - <script src='test.constructor.js'></script> - <script src='test.changes.js'></script> - <script src='test.bulk_docs.js'></script> - <script src='test.all_docs.js'></script> - <script src='test.events.js'></script> - <script src='test.conflicts.js'></script> - <script src='test.revs_diff.js'></script> - <script src='test.replication.js'></script> - <script src='test.sync.js'></script> - <script src='test.views.js'></script> - <script src='test.taskqueue.js'></script> - <script src='test.design_docs.js'></script> - <script src='test.issue221.js'></script> - <script src='test.http.js'></script> - <script src='test.compaction.js'></script> - <script src='test.get.js'></script> - <script src='test.local_docs.js'></script> - <script src='test.attachments.js'></script> - <script src='browser.migration.js'></script> - <script src='test.uuids.js'></script> - <script src='test.slash_id.js'></script> - <script src='test.reserved.js'></script> - <script src='browser.worker.js'></script> - <script type="text/javascript" src="./webrunner.js"></script> - </body> -</html>
diff --git a/tests/integration/leveldb/lateStyle/000003.log b/tests/integration/leveldb/lateStyle/000003.log deleted file mode 100644 index 33de8cc..0000000 --- a/tests/integration/leveldb/lateStyle/000003.log +++ /dev/null Binary files differ
diff --git a/tests/integration/leveldb/lateStyle/CURRENT b/tests/integration/leveldb/lateStyle/CURRENT deleted file mode 100644 index 1a84852..0000000 --- a/tests/integration/leveldb/lateStyle/CURRENT +++ /dev/null
@@ -1 +0,0 @@ -MANIFEST-000002
diff --git a/tests/integration/leveldb/lateStyle/LOCK b/tests/integration/leveldb/lateStyle/LOCK deleted file mode 100644 index e69de29..0000000 --- a/tests/integration/leveldb/lateStyle/LOCK +++ /dev/null
diff --git a/tests/integration/leveldb/lateStyle/LOG b/tests/integration/leveldb/lateStyle/LOG deleted file mode 100644 index b83544f..0000000 --- a/tests/integration/leveldb/lateStyle/LOG +++ /dev/null
@@ -1 +0,0 @@ -2014/10/18-13:54:18.233480 103b7a000 Delete type=3 #1
diff --git a/tests/integration/leveldb/lateStyle/MANIFEST-000002 b/tests/integration/leveldb/lateStyle/MANIFEST-000002 deleted file mode 100644 index bbbc585..0000000 --- a/tests/integration/leveldb/lateStyle/MANIFEST-000002 +++ /dev/null Binary files differ
diff --git a/tests/integration/leveldb/middleStyle/000003.log b/tests/integration/leveldb/middleStyle/000003.log deleted file mode 100644 index 05cc845..0000000 --- a/tests/integration/leveldb/middleStyle/000003.log +++ /dev/null Binary files differ
diff --git a/tests/integration/leveldb/middleStyle/CURRENT b/tests/integration/leveldb/middleStyle/CURRENT deleted file mode 100644 index 1a84852..0000000 --- a/tests/integration/leveldb/middleStyle/CURRENT +++ /dev/null
@@ -1 +0,0 @@ -MANIFEST-000002
diff --git a/tests/integration/leveldb/middleStyle/LOCK b/tests/integration/leveldb/middleStyle/LOCK deleted file mode 100644 index e69de29..0000000 --- a/tests/integration/leveldb/middleStyle/LOCK +++ /dev/null
diff --git a/tests/integration/leveldb/middleStyle/LOG b/tests/integration/leveldb/middleStyle/LOG deleted file mode 100644 index bc24db1..0000000 --- a/tests/integration/leveldb/middleStyle/LOG +++ /dev/null
@@ -1 +0,0 @@ -2014/04/30-13:26:08.586711 106881000 Delete type=3 #1
diff --git a/tests/integration/leveldb/middleStyle/MANIFEST-000002 b/tests/integration/leveldb/middleStyle/MANIFEST-000002 deleted file mode 100644 index dbf594e..0000000 --- a/tests/integration/leveldb/middleStyle/MANIFEST-000002 +++ /dev/null Binary files differ
diff --git a/tests/integration/leveldb/oldStyle.uuid b/tests/integration/leveldb/oldStyle.uuid deleted file mode 100644 index 751fa94..0000000 --- a/tests/integration/leveldb/oldStyle.uuid +++ /dev/null
@@ -1 +0,0 @@ -F25693E5-4052-4F30-BEAF-9D1E48DD05CF \ No newline at end of file
diff --git a/tests/integration/leveldb/oldStyle/attach-binary-store/000003.log b/tests/integration/leveldb/oldStyle/attach-binary-store/000003.log deleted file mode 100644 index e69de29..0000000 --- a/tests/integration/leveldb/oldStyle/attach-binary-store/000003.log +++ /dev/null
diff --git a/tests/integration/leveldb/oldStyle/attach-binary-store/CURRENT b/tests/integration/leveldb/oldStyle/attach-binary-store/CURRENT deleted file mode 100644 index 1a84852..0000000 --- a/tests/integration/leveldb/oldStyle/attach-binary-store/CURRENT +++ /dev/null
@@ -1 +0,0 @@ -MANIFEST-000002
diff --git a/tests/integration/leveldb/oldStyle/attach-binary-store/LOCK b/tests/integration/leveldb/oldStyle/attach-binary-store/LOCK deleted file mode 100644 index e69de29..0000000 --- a/tests/integration/leveldb/oldStyle/attach-binary-store/LOCK +++ /dev/null
diff --git a/tests/integration/leveldb/oldStyle/attach-binary-store/LOG b/tests/integration/leveldb/oldStyle/attach-binary-store/LOG deleted file mode 100644 index 5b9c46e..0000000 --- a/tests/integration/leveldb/oldStyle/attach-binary-store/LOG +++ /dev/null
@@ -1 +0,0 @@ -2014/02/21-19:45:02.682927 103b87000 Delete type=3 #1
diff --git a/tests/integration/leveldb/oldStyle/attach-binary-store/MANIFEST-000002 b/tests/integration/leveldb/oldStyle/attach-binary-store/MANIFEST-000002 deleted file mode 100644 index bbbc585..0000000 --- a/tests/integration/leveldb/oldStyle/attach-binary-store/MANIFEST-000002 +++ /dev/null Binary files differ
diff --git a/tests/integration/leveldb/oldStyle/attach-store/000003.log b/tests/integration/leveldb/oldStyle/attach-store/000003.log deleted file mode 100644 index e69de29..0000000 --- a/tests/integration/leveldb/oldStyle/attach-store/000003.log +++ /dev/null
diff --git a/tests/integration/leveldb/oldStyle/attach-store/CURRENT b/tests/integration/leveldb/oldStyle/attach-store/CURRENT deleted file mode 100644 index 1a84852..0000000 --- a/tests/integration/leveldb/oldStyle/attach-store/CURRENT +++ /dev/null
@@ -1 +0,0 @@ -MANIFEST-000002
diff --git a/tests/integration/leveldb/oldStyle/attach-store/LOCK b/tests/integration/leveldb/oldStyle/attach-store/LOCK deleted file mode 100644 index e69de29..0000000 --- a/tests/integration/leveldb/oldStyle/attach-store/LOCK +++ /dev/null
diff --git a/tests/integration/leveldb/oldStyle/attach-store/LOG b/tests/integration/leveldb/oldStyle/attach-store/LOG deleted file mode 100644 index 2c68122..0000000 --- a/tests/integration/leveldb/oldStyle/attach-store/LOG +++ /dev/null
@@ -1 +0,0 @@ -2014/02/21-19:45:02.682637 103a81000 Delete type=3 #1
diff --git a/tests/integration/leveldb/oldStyle/attach-store/MANIFEST-000002 b/tests/integration/leveldb/oldStyle/attach-store/MANIFEST-000002 deleted file mode 100644 index bbbc585..0000000 --- a/tests/integration/leveldb/oldStyle/attach-store/MANIFEST-000002 +++ /dev/null Binary files differ
diff --git a/tests/integration/leveldb/oldStyle/by-sequence/000003.log b/tests/integration/leveldb/oldStyle/by-sequence/000003.log deleted file mode 100644 index 953ab4b..0000000 --- a/tests/integration/leveldb/oldStyle/by-sequence/000003.log +++ /dev/null Binary files differ
diff --git a/tests/integration/leveldb/oldStyle/by-sequence/CURRENT b/tests/integration/leveldb/oldStyle/by-sequence/CURRENT deleted file mode 100644 index 1a84852..0000000 --- a/tests/integration/leveldb/oldStyle/by-sequence/CURRENT +++ /dev/null
@@ -1 +0,0 @@ -MANIFEST-000002
diff --git a/tests/integration/leveldb/oldStyle/by-sequence/LOCK b/tests/integration/leveldb/oldStyle/by-sequence/LOCK deleted file mode 100644 index e69de29..0000000 --- a/tests/integration/leveldb/oldStyle/by-sequence/LOCK +++ /dev/null
diff --git a/tests/integration/leveldb/oldStyle/by-sequence/LOG b/tests/integration/leveldb/oldStyle/by-sequence/LOG deleted file mode 100644 index 52362b6..0000000 --- a/tests/integration/leveldb/oldStyle/by-sequence/LOG +++ /dev/null
@@ -1 +0,0 @@ -2014/02/21-19:45:02.682960 103b04000 Delete type=3 #1
diff --git a/tests/integration/leveldb/oldStyle/by-sequence/MANIFEST-000002 b/tests/integration/leveldb/oldStyle/by-sequence/MANIFEST-000002 deleted file mode 100644 index bbbc585..0000000 --- a/tests/integration/leveldb/oldStyle/by-sequence/MANIFEST-000002 +++ /dev/null Binary files differ
diff --git a/tests/integration/leveldb/oldStyle/document-store/000003.log b/tests/integration/leveldb/oldStyle/document-store/000003.log deleted file mode 100644 index c011370..0000000 --- a/tests/integration/leveldb/oldStyle/document-store/000003.log +++ /dev/null Binary files differ
diff --git a/tests/integration/leveldb/oldStyle/document-store/CURRENT b/tests/integration/leveldb/oldStyle/document-store/CURRENT deleted file mode 100644 index 1a84852..0000000 --- a/tests/integration/leveldb/oldStyle/document-store/CURRENT +++ /dev/null
@@ -1 +0,0 @@ -MANIFEST-000002
diff --git a/tests/integration/leveldb/oldStyle/document-store/LOCK b/tests/integration/leveldb/oldStyle/document-store/LOCK deleted file mode 100644 index e69de29..0000000 --- a/tests/integration/leveldb/oldStyle/document-store/LOCK +++ /dev/null
diff --git a/tests/integration/leveldb/oldStyle/document-store/LOG b/tests/integration/leveldb/oldStyle/document-store/LOG deleted file mode 100644 index 4833ff5..0000000 --- a/tests/integration/leveldb/oldStyle/document-store/LOG +++ /dev/null
@@ -1 +0,0 @@ -2014/02/21-19:45:02.682986 102781000 Delete type=3 #1
diff --git a/tests/integration/leveldb/oldStyle/document-store/MANIFEST-000002 b/tests/integration/leveldb/oldStyle/document-store/MANIFEST-000002 deleted file mode 100644 index bbbc585..0000000 --- a/tests/integration/leveldb/oldStyle/document-store/MANIFEST-000002 +++ /dev/null Binary files differ
diff --git a/tests/integration/node.setup.js b/tests/integration/node.setup.js deleted file mode 100644 index 8f83b0f..0000000 --- a/tests/integration/node.setup.js +++ /dev/null
@@ -1,14 +0,0 @@ -"use strict"; - -var testsDir = process.env.TESTS_DIR || './tmp'; -var exec = require('child_process').exec; -function cleanup() { - // Remove test databases - exec('rm -r ' + testsDir); -} -exec('mkdir -p ' + testsDir, function () { - process.on('SIGINT', cleanup); - process.on('exit', cleanup); -}); -global.testUtils = require('./utils.js'); -global.should = require('chai').should();
diff --git a/tests/integration/test.aa.setup.js b/tests/integration/test.aa.setup.js deleted file mode 100644 index 4f5daa8..0000000 --- a/tests/integration/test.aa.setup.js +++ /dev/null
@@ -1,13 +0,0 @@ -'use strict'; -describe('DB Setup', function () { - it('we can find CouchDB with admin credentials', function (done) { - PouchDB.ajax({ url: testUtils.couchHost() + '/_session' }, - function (err, res) { - if (err) { return done(err); } - should.exist(res.ok, 'Found CouchDB'); - res.userCtx.roles.should.include('_admin', 'Found admin permissions'); - done(); - } - ); - }); -});
diff --git a/tests/integration/test.all_docs.js b/tests/integration/test.all_docs.js deleted file mode 100644 index 97e4d23..0000000 --- a/tests/integration/test.all_docs.js +++ /dev/null
@@ -1,592 +0,0 @@ -'use strict'; - -var adapters = ['http', 'local']; - -adapters.forEach(function (adapter) { - describe('test.all_docs.js-' + adapter, function () { - - var dbs = {}; - beforeEach(function (done) { - dbs = {name: testUtils.adapterUrl(adapter, 'testdb')}; - testUtils.cleanup([dbs.name], done); - }); - - afterEach(function (done) { - testUtils.cleanup([dbs.name], done); - }); - - - var origDocs = [ - {_id: '0', a: 1, b: 1}, - {_id: '3', a: 4, b: 16}, - {_id: '1', a: 2, b: 4}, - {_id: '2', a: 3, b: 9} - ]; - - it('Testing all docs', function (done) { - var db = new PouchDB(dbs.name); - testUtils.writeDocs(db, JSON.parse(JSON.stringify(origDocs)), - function () { - db.allDocs(function (err, result) { - should.not.exist(err); - var rows = result.rows; - result.total_rows.should.equal(4, 'correct number of results'); - for (var i = 0; i < rows.length; i++) { - rows[i].id.should.be.at.least('0'); - rows[i].id.should.be.at.most('4'); - } - db.allDocs({ - startkey: '2', - include_docs: true - }, function (err, all) { - all.rows.should.have - .length(2, 'correct number when opts.startkey set'); - all.rows[0].id.should - .equal('2', 'correct docs when opts.startkey set'); - var opts = { - startkey: 'org.couchdb.user:', - endkey: 'org.couchdb.user;' - }; - db.allDocs(opts, function (err, raw) { - raw.rows.should.have.length(0, 'raw collation'); - var ids = ['0', '3', '1', '2']; - db.changes({ - complete: function (err, changes) { - changes.results.forEach(function (row, i) { - row.id.should.equal(ids[i], 'seq order'); - }); - db.changes({ - descending: true, - complete: function (err, changes) { - ids = ['2', '1', '3', '0']; - changes.results.forEach(function (row, i) { - row.id.should.equal(ids[i], 'descending=true'); - }); - done(); - } - }); - } - }); - }); - }); - }); - }); - }); - - it('Testing allDocs opts.keys', function (done) { - var db = new PouchDB(dbs.name); - function keyFunc(doc) { - return doc.key; - } - testUtils.writeDocs(db, JSON.parse(JSON.stringify(origDocs)), - function () { - var keys = ['3', '1']; - db.allDocs({ keys: keys }, function (err, result) { - result.rows.map(keyFunc).should.deep.equal(keys); - keys = ['2', '0', '1000']; - db.allDocs({ keys: keys }, function (err, result) { - result.rows.map(keyFunc).should.deep.equal(keys); - result.rows[2].error.should.equal('not_found'); - db.allDocs({ - keys: keys, - descending: true - }, function (err, result) { - result.rows.map(keyFunc).should.deep.equal(['1000', '0', '2']); - result.rows[0].error.should.equal('not_found'); - db.allDocs({ - keys: keys, - startkey: 'a' - }, function (err, result) { - should.exist(err); - db.allDocs({ - keys: keys, - endkey: 'a' - }, function (err, result) { - should.exist(err); - db.allDocs({ keys: [] }, function (err, result) { - result.rows.should.have.length(0); - db.get('2', function (err, doc) { - db.remove(doc, function (err, doc) { - db.allDocs({ - keys: keys, - include_docs: true - }, function (err, result) { - result.rows.map(keyFunc).should.deep.equal(keys); - done(); - }); - }); - }); - }); - }); - }); - }); - }); - }); - }); - }); - - it('Testing deleting in changes', function (done) { - var db = new PouchDB(dbs.name); - testUtils.writeDocs(db, JSON.parse(JSON.stringify(origDocs)), - function () { - db.get('1', function (err, doc) { - db.remove(doc, function (err, deleted) { - should.exist(deleted.ok); - db.changes({ - complete: function (err, changes) { - changes.results.should.have.length(4); - changes.results[3].id.should.equal('1'); - should.exist(changes.results[3].deleted); - done(); - } - }); - }); - }); - }); - }); - - it('Testing updating in changes', function (done) { - var db = new PouchDB(dbs.name); - testUtils.writeDocs(db, JSON.parse(JSON.stringify(origDocs)), - function () { - db.get('3', function (err, doc) { - doc.updated = 'totally'; - db.put(doc, function (err, doc) { - db.changes({ - complete: function (err, changes) { - changes.results.should.have.length(4); - changes.results[3].id.should.equal('3'); - done(); - } - }); - }); - }); - }); - }); - - it('Testing include docs', function (done) { - var db = new PouchDB(dbs.name); - testUtils.writeDocs(db, JSON.parse(JSON.stringify(origDocs)), - function () { - db.changes({ - include_docs: true, - complete: function (err, changes) { - changes.results[0].doc.a.should.equal(1); - done(); - } - }); - }); - }); - - it('Testing conflicts', function (done) { - var db = new PouchDB(dbs.name); - testUtils.writeDocs(db, JSON.parse(JSON.stringify(origDocs)), - function () { - // add conflicts - var conflictDoc1 = { - _id: '3', - _rev: '2-aa01552213fafa022e6167113ed01087', - value: 'X' - }; - var conflictDoc2 = { - _id: '3', - _rev: '2-ff01552213fafa022e6167113ed01087', - value: 'Z' - }; - db.put(conflictDoc1, { new_edits: false }, function (err, doc) { - db.put(conflictDoc2, { new_edits: false }, function (err, doc) { - db.get('3', function (err, winRev) { - winRev._rev.should.equal(conflictDoc2._rev); - db.changes({ - include_docs: true, - conflicts: true, - style: 'all_docs', - complete: function (err, changes) { - var result = changes.results[3]; - result.id.should.equal('3', 'changes are ordered'); - result.changes.should.have - .length(3, 'correct number of changes'); - result.doc._rev.should.equal(conflictDoc2._rev); - result.doc._id.should.equal('3', 'correct doc id'); - winRev._rev.should.equal(result.doc._rev); - result.doc._conflicts.should.be.instanceof(Array); - result.doc._conflicts.should.have.length(2); - conflictDoc1._rev.should.equal(result.doc._conflicts[0]); - db.allDocs({ - include_docs: true, - conflicts: true - }, function (err, res) { - var row = res.rows[3]; - res.rows.should.have.length(4, 'correct number of changes'); - row.key.should.equal('3', 'correct key'); - row.id.should.equal('3', 'correct id'); - row.value.rev.should.equal(winRev._rev, 'correct rev'); - row.doc._rev.should.equal(winRev._rev, 'correct rev'); - row.doc._id.should.equal('3', 'correct order'); - row.doc._conflicts.should.be.instanceof(Array); - row.doc._conflicts.should.have.length(2); - conflictDoc1._rev.should - .equal(res.rows[3].doc._conflicts[0]); - done(); - }); - } - }); - }); - }); - }); - }); - }); - - it('test basic collation', function (done) { - var db = new PouchDB(dbs.name); - var docs = { - docs: [ - {_id: 'z', foo: 'z'}, - {_id: 'a', foo: 'a'} - ] - }; - db.bulkDocs(docs, function (err, res) { - db.allDocs({ - startkey: 'z', - endkey: 'z' - }, function (err, result) { - result.rows.should.have.length(1, 'Exclude a result'); - done(); - }); - }); - }); - - it('test total_rows with a variety of criteria', function (done) { - this.timeout(20000); - var db = new PouchDB(dbs.name); - - var docs = [ - {_id : '0'}, - {_id : '1'}, - {_id : '2'}, - {_id : '3'}, - {_id : '4'}, - {_id : '5'}, - {_id : '6'}, - {_id : '7'}, - {_id : '8'}, - {_id : '9'} - ]; - db.bulkDocs({docs : docs}).then(function (res) { - docs[3]._deleted = true; - docs[7]._deleted = true; - docs[3]._rev = res[3].rev; - docs[7]._rev = res[7].rev; - return db.remove(docs[3]); - }).then(function () { - return db.remove(docs[7]); - }).then(function () { - return db.allDocs(); - }).then(function (res) { - res.rows.should.have.length(8, 'correctly return rows'); - res.total_rows.should.equal(8, 'correctly return total_rows'); - return db.allDocs({startkey : '5'}); - }).then(function (res) { - res.rows.should.have.length(4, 'correctly return rows'); - res.total_rows.should.equal(8, 'correctly return total_rows'); - return db.allDocs({startkey : '5', skip : 2, limit : 10}); - }).then(function (res) { - res.rows.should.have.length(2, 'correctly return rows'); - res.total_rows.should.equal(8, 'correctly return total_rows'); - return db.allDocs({startkey : '5', limit : 0}); - }).then(function (res) { - res.rows.should.have - .length(0, 'correctly return rows, startkey w/ limit=0'); - res.total_rows.should.equal(8, 'correctly return total_rows'); - return db.allDocs({keys : ['5'], limit : 0}); - }).then(function (res) { - res.rows.should.have - .length(0, 'correctly return rows, keys w/ limit=0'); - res.total_rows.should.equal(8, 'correctly return total_rows'); - return db.allDocs({limit : 0}); - }).then(function (res) { - res.rows.should.have.length(0, 'correctly return rows, limit=0'); - res.total_rows.should.equal(8, 'correctly return total_rows'); - return db.allDocs({startkey : '5', descending : true, skip : 1}); - }).then(function (res) { - res.rows.should.have.length(4, 'correctly return rows'); - res.total_rows.should.equal(8, 'correctly return total_rows'); - return db.allDocs({startkey : '5', endkey : 'z'}); - }).then(function (res) { - res.rows.should.have.length(4, 'correctly return rows'); - res.total_rows.should.equal(8, 'correctly return total_rows'); - return db.allDocs({startkey : '5', endkey : '5'}); - }).then(function (res) { - res.rows.should.have.length(1, 'correctly return rows'); - res.total_rows.should.equal(8, 'correctly return total_rows'); - return db.allDocs({startkey : '5', endkey : '4'}); - }).then(function (res) { - res.rows.should.have.length(0, 'correctly return rows'); - res.total_rows.should.equal(8, 'correctly return total_rows'); - return db.allDocs({startkey : '5', endkey : '4', descending : true}); - }).then(function (res) { - res.rows.should.have.length(2, 'correctly return rows'); - res.total_rows.should.equal(8, 'correctly return total_rows'); - return db.allDocs({startkey : '3', endkey : '7', descending : false}); - }).then(function (res) { - res.rows.should.have.length(3, 'correctly return rows'); - res.total_rows.should.equal(8, 'correctly return total_rows'); - return db.allDocs({startkey : '7', endkey : '3', descending : true}); - }).then(function (res) { - res.rows.should.have.length(3, 'correctly return rows'); - res.total_rows.should.equal(8, 'correctly return total_rows'); - return db.allDocs({startkey : '', endkey : '0'}); - }).then(function (res) { - res.rows.should.have.length(1, 'correctly return rows'); - res.total_rows.should.equal(8, 'correctly return total_rows'); - return db.allDocs({keys : ['0', '1', '3']}); - }).then(function (res) { - res.rows.should.have.length(3, 'correctly return rows'); - res.total_rows.should.equal(8, 'correctly return total_rows'); - return db.allDocs({keys : ['0', '1', '0', '2', '1', '1']}); - }).then(function (res) { - res.rows.should.have.length(6, 'correctly return rows'); - res.rows.map(function (row) { return row.key; }).should.deep.equal( - ['0', '1', '0', '2', '1', '1']); - res.total_rows.should.equal(8, 'correctly return total_rows'); - return db.allDocs({keys : []}); - }).then(function (res) { - res.rows.should.have.length(0, 'correctly return rows'); - res.total_rows.should.equal(8, 'correctly return total_rows'); - return db.allDocs({keys : ['7']}); - }).then(function (res) { - res.rows.should.have.length(1, 'correctly return rows'); - res.total_rows.should.equal(8, 'correctly return total_rows'); - return db.allDocs({key : '3'}); - }).then(function (res) { - res.rows.should.have.length(0, 'correctly return rows'); - res.total_rows.should.equal(8, 'correctly return total_rows'); - return db.allDocs({key : '2'}); - }).then(function (res) { - res.rows.should.have.length(1, 'correctly return rows'); - res.total_rows.should.equal(8, 'correctly return total_rows'); - return db.allDocs({key : 'z'}); - }).then(function (res) { - res.rows.should.have.length(0, 'correctly return rows'); - res.total_rows.should.equal(8, 'correctly return total_rows'); - done(); - }, done); - - }); - - it('test total_rows with both skip and limit', function (done) { - var db = new PouchDB(dbs.name); - var docs = { - docs: [ - {_id: "w", foo: "w"}, - {_id: "x", foo: "x"}, - {_id: "y", foo: "y"}, - {_id: "z", foo: "z"} - ] - }; - db.bulkDocs(docs, function (err, res) { - db.allDocs({ startkey: 'x', limit: 1, skip : 1}, function (err, res) { - res.total_rows.should.equal(4, 'Accurately return total_rows count'); - res.rows.should.have.length(1, 'Correctly limit the returned rows'); - res.rows[0].id.should.equal('y', 'Correctly skip 1 doc'); - - db.get('x', function (err, xDoc) { - db.remove(xDoc, function (err, res) { - db.allDocs({ startkey: 'w', limit: 2, skip : 1}, - function (err, res) { - res.total_rows.should - .equal(3, 'Accurately return total_rows count after delete'); - res.rows.should.have - .length(2, 'Correctly limit the returned rows after delete'); - res.rows[0].id.should - .equal('y', 'Correctly skip 1 doc after delete'); - done(); - }); - }); - }); - }); - }); - }); - - it('test limit option and total_rows', function (done) { - var db = new PouchDB(dbs.name); - var docs = { - docs: [ - {_id: 'z', foo: 'z'}, - {_id: 'a', foo: 'a'} - ] - }; - db.bulkDocs(docs, function (err, res) { - db.allDocs({ - startkey: 'a', - limit: 1 - }, function (err, res) { - res.total_rows.should.equal(2, 'Accurately return total_rows count'); - res.rows.should.have.length(1, 'Correctly limit the returned rows.'); - done(); - }); - }); - }); - - it('test escaped startkey/endkey', function (done) { - var db = new PouchDB(dbs.name); - var id1 = '"crazy id!" a'; - var id2 = '"crazy id!" z'; - var docs = { - docs: [ - { - _id: id1, - foo: 'a' - }, - { - _id: id2, - foo: 'z' - } - ] - }; - db.bulkDocs(docs, function (err, res) { - db.allDocs({ - startkey: id1, - endkey: id2 - }, function (err, res) { - res.total_rows.should.equal(2, 'Accurately return total_rows count'); - done(); - }); - }); - }); - - it('test "key" option', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs({ - docs: [ - { _id: '0' }, - { _id: '1' }, - { _id: '2' } - ] - }, function (err) { - should.not.exist(err); - db.allDocs({ key: '1' }, function (err, res) { - res.rows.should.have.length(1, 'key option returned 1 doc'); - db.allDocs({ - key: '1', - keys: [ - '1', - '2' - ] - }, function (err) { - should.exist(err); - db.allDocs({ - key: '1', - startkey: '1' - }, function (err, res) { - should.not.exist(err); - db.allDocs({ - key: '1', - endkey: '1' - }, function (err, res) { - should.not.exist(err); - // when mixing key/startkey or key/endkey, the results - // are very weird and probably undefined, so don't go beyond - // verifying that there's no error - done(); - }); - }); - }); - }); - }); - }); - - it('test inclusive_end=false', function (done) { - new PouchDB(dbs.name).then(function (db) { - var docs = [ - { _id: '1' }, - { _id: '2' }, - { _id: '3' }, - { _id: '4' } - ]; - return db.bulkDocs({docs: docs}).then(function () { - return db.allDocs({inclusive_end: false, endkey: '2'}); - }).then(function (res) { - res.rows.should.have.length(1); - return db.allDocs({inclusive_end: false, endkey: '1'}); - }).then(function (res) { - res.rows.should.have.length(0); - return db.allDocs({inclusive_end: false, endkey: '1', - startkey: '0'}); - }).then(function (res) { - res.rows.should.have.length(0); - return db.allDocs({inclusive_end: false, endkey: '5'}); - }).then(function (res) { - res.rows.should.have.length(4); - return db.allDocs({inclusive_end: false, endkey: '4'}); - }).then(function (res) { - res.rows.should.have.length(3); - return db.allDocs({inclusive_end: false, endkey: '4', - startkey: '3'}); - }).then(function (res) { - res.rows.should.have.length(1); - return db.allDocs({inclusive_end: false, endkey: '1', - descending: true}); - }).then(function (res) { - res.rows.should.have.length(3); - return db.allDocs({inclusive_end: true, endkey: '4'}); - }).then(function (res) { - res.rows.should.have.length(4); - return db.allDocs({ - descending: true, - startkey: '3', - endkey: '2', - inclusive_end: false - }); - }); - }).then(function (res) { - res.rows.should.have.length(1); - }).then(function () { - done(); - }, function (err) { - done(err); - }); - }); - - it('test empty db', function (done) { - return new PouchDB(dbs.name).then(function (db) { - return db.allDocs().then(function (res) { - res.rows.should.have.length(0); - res.total_rows.should.equal(0); - done(); - }); - }); - }); - - it('test after db close', function (done) { - return new PouchDB(dbs.name).then(function (db) { - return db.close().then(function () { - return db.allDocs().catch(function (err) { - err.message.should.equal('database is closed'); - done(); - }); - }); - }); - }); - - if (adapter === 'local') { // chrome doesn't like \u0000 in URLs - it('test unicode ids and revs', function (done) { - var db = new PouchDB(dbs.name); - var id = 'baz\u0000'; - var rev; - return db.put({_id: id}).then(function (res) { - rev = res.rev; - }).then(function () { - return db.get(id); - }).then(function (doc) { - doc._id.should.equal(id); - doc._rev.should.equal(rev); - return db.allDocs({keys: [id]}); - }).then(function (res) { - res.rows.should.have.length(1); - res.rows[0].value.rev.should.equal(rev); - }).then(done, done); - }); - } - }); -});
diff --git a/tests/integration/test.attachments.js b/tests/integration/test.attachments.js deleted file mode 100644 index 3a60d73..0000000 --- a/tests/integration/test.attachments.js +++ /dev/null
@@ -1,2149 +0,0 @@ -'use strict'; - -var adapters = ['local', 'http']; -var repl_adapters = [ - ['local', 'http'], - ['http', 'http'], - ['http', 'local'], - ['local', 'local'] -]; - -/* jshint maxlen:false */ -var icons = [ - "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" -]; - -var iconDigests = [ - "md5-Mf8m9ehZnCXC717bPkqkCA==", - "md5-fdEZBYtnvr+nozYVDzzxpA==", - "md5-ImDARszfC+GA3Cv9TVW4HA==", - "md5-hBsgoz3ujHM4ioa72btwow==", - "md5-jDUyV6ySnTVANn2qq3332g==" -]; - -var iconLengths = [1047, 789, 967, 527, 1108]; - -adapters.forEach(function (adapter) { - describe('test.attachments.js-' + adapter, function () { - - var dbs = {}; - - beforeEach(function (done) { - dbs.name = testUtils.adapterUrl(adapter, 'testdb'); - testUtils.cleanup([dbs.name], done); - }); - - after(function (done) { - testUtils.cleanup([dbs.name], done); - }); - - var binAttDoc = { - _id: 'bin_doc', - _attachments: { - 'foo.txt': { - content_type: 'text/plain', - data: 'VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ=' - } - } - }; - // empty attachment - var binAttDoc2 = { - _id: 'bin_doc2', - _attachments: { - 'foo.txt': { - content_type: 'text/plain', - data: '' - } - } - }; - // json string doc - var jsonDoc = { - _id: 'json_doc', - _attachments: { - 'foo.json': { - content_type: 'application/json', - data: 'eyJIZWxsbyI6IndvcmxkIn0=' - } - } - }; - var pngAttDoc = { - _id: 'png_doc', - _attachments: { - 'foo.png': { - content_type: 'image/png', - data: 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAMFBMVEX+9+' + - 'j+9OD+7tL95rr93qT80YD7x2L6vkn6syz5qRT4ogT4nwD4ngD4nQD4nQD4' + - 'nQDT2nT/AAAAcElEQVQY002OUQLEQARDw1D14f7X3TCdbfPnhQTqI5UqvG' + - 'OWIz8gAIXFH9zmC63XRyTsOsCWk2A9Ga7wCXlA9m2S6G4JlVwQkpw/Ymxr' + - 'UgNoMoyxBwSMH/WnAzy5cnfLFu+dK2l5gMvuPGLGJd1/9AOiBQiEgkzOpg' + - 'AAAABJRU5ErkJggg==' - } - } - }; - - it('issue 2803 should throw 412', function () { - var db = new PouchDB(dbs.name); - return db.put(binAttDoc).then(function () { - return db.get(binAttDoc._id); - }).then(function (doc) { - doc._attachments['bar.txt'] = { - stub: true, - digest: 'md5-sorryIDoNotReallyExist==' - }; - return db.put(doc); - }).then(function (res) { - should.not.exist(res, 'should throw'); - }).catch(function (err) { - should.exist(err.status, 'got improper error: ' + err); - err.status.should.equal(412); - }); - }); - - it('issue 2803 should throw 412 part 2', function () { - var stubDoc = { - _id: 'stubby', - "_attachments": { - "foo.txt": { - "content_type": "text/plain", - "digest": "md5-aEI7pOYCRBLTRQvvqYrrJQ==", - "stub": true - }, - } - }; - var db = new PouchDB(dbs.name); - return db.put(stubDoc).then(function (res) { - should.not.exist(res, 'should throw'); - }).catch(function (err) { - should.exist(err.status, 'got improper error: ' + err); - err.status.should.equal(412, 'got improper error: ' + err); - }); - }); - - it('issue 2803 should throw 412 part 3', function () { - var db = new PouchDB(dbs.name); - return db.put(binAttDoc).then(function () { - return db.get(binAttDoc._id); - }).then(function (doc) { - doc._attachments['foo.json'] = jsonDoc._attachments['foo.json']; - }).then(function () { - return db.get(binAttDoc._id); - }).then(function (doc) { - doc._attachments['bar.txt'] = { - stub: true, - digest: 'md5-sorryIDoNotReallyExist==' - }; - return db.put(doc); - }).then(function (res) { - should.not.exist(res, 'should throw'); - }).catch(function (err) { - should.exist(err.status, 'got improper error: ' + err); - err.status.should.equal(412); - }); - }); - - it('issue 2803 should throw 412 part 4', function () { - var db = new PouchDB(dbs.name); - return db.put(binAttDoc).then(function () { - return db.get(binAttDoc._id); - }).then(function (doc) { - doc._attachments['foo.json'] = jsonDoc._attachments['foo.json']; - }).then(function () { - return db.get(binAttDoc._id); - }).then(function (doc) { - doc._attachments['bar.txt'] = { - stub: true, - digest: 'md5-sorryIDoNotReallyExist==' - }; - doc._attachments['baz.txt'] = { - stub: true, - digest: 'md5-yahNoIDoNotExistEither==' - }; - return db.put(doc); - }).then(function (res) { - should.not.exist(res, 'should throw'); - }).catch(function (err) { - should.exist(err.status, 'got improper error: ' + err); - err.status.should.equal(412); - }); - }); - - it('Measures length correctly after put()', function () { - var db = new PouchDB(dbs.name); - return db.put(binAttDoc).then(function () { - return db.get(binAttDoc._id); - }).then(function (doc) { - delete doc._attachments["foo.txt"].revpos; - - // because of libicu vs. ascii - var digest = doc._attachments["foo.txt"].digest; - var validDigests = [ - "md5-qUUYqS41RhwF0TrCsTAxFg==", - "md5-aEI7pOYCRBLTRQvvqYrrJQ==" - ]; - validDigests.indexOf(digest).should.not.equal(-1, - 'expected ' + digest + ' to be in: ' + - JSON.stringify(validDigests)); - delete doc._attachments["foo.txt"].digest; - doc._attachments.should.deep.equal({ - "foo.txt": { - "content_type": "text/plain", - "stub": true, - length: 29 - } - }); - }); - }); - - it('#3074 non-live changes()', function () { - var db = new PouchDB(dbs.name); - var docs = []; - for (var i = 0; i < 5; i++) { - docs.push({ - _id: i.toString(), - _attachments: { - 'foo.png': { - data: icons[i], - content_type: 'image/png' - } - } - }); - } - return db.bulkDocs(docs).then(function () { - return db.changes({include_docs: true, attachments: true}); - }).then(function (res) { - var attachments = res.results.sort(function (left, right) { - return left.id < right.id ? -1 : 1; - }).map(function (change) { - var doc = change.doc; - delete doc._attachments['foo.png'].revpos; - return doc._attachments; - }); - attachments.should.deep.equal(icons.map(function (icon, i) { - return { - "foo.png": { - "content_type": "image/png", - "data": icon, - "digest": iconDigests[i] - } - }; - }), 'when attachments=true'); - return db.changes({include_docs: true}); - }).then(function (res) { - var attachments = res.results.sort(function (left, right) { - return left.id < right.id ? -1 : 1; - }).map(function (change) { - var doc = change.doc; - delete doc._attachments['foo.png'].revpos; - return doc._attachments['foo.png']; - }); - attachments.should.deep.equal(icons.map(function (icon, i) { - return { - "content_type": "image/png", - stub: true, - "digest": iconDigests[i], - length: iconLengths[i] - }; - }), 'when attachments=false'); - return db.changes({attachments: true}); - }).then(function (res) { - res.results.should.have.length(5); - res.results.forEach(function (row) { - should.not.exist(row.doc, - 'no doc when attachments=true but include_docs=false'); - }); - return db.changes(); - }).then(function (res) { - res.results.should.have.length(5); - res.results.forEach(function (row) { - should.not.exist(row.doc, - 'no doc when attachments=false and include_docs=false'); - }); - }); - }); - - it('#3074 live changes()', function () { - - var db = new PouchDB(dbs.name); - - function liveChangesPromise(opts) { - opts.live = true; - return new PouchDB.utils.Promise(function (resolve, reject) { - var retChanges = {results: []}; - var changes = db.changes(opts) - .on('change', function (change) { - retChanges.results.push(change); - if (retChanges.results.length === 5) { - changes.cancel(); - resolve(retChanges); - } - }).on('error', reject); - }); - } - - var docs = []; - for (var i = 0; i < 5; i++) { - docs.push({ - _id: i.toString(), - _attachments: { - 'foo.png': { - data: icons[i], - content_type: 'image/png' - } - } - }); - } - return db.bulkDocs(docs).then(function () { - return liveChangesPromise({ - include_docs: true, - attachments: true - }); - }).then(function (res) { - var attachments = res.results.sort(function (left, right) { - return left.id < right.id ? -1 : 1; - }).map(function (change) { - var doc = change.doc; - delete doc._attachments['foo.png'].revpos; - return doc._attachments; - }); - attachments.should.deep.equal(icons.map(function (icon, i) { - return { - "foo.png": { - "content_type": "image/png", - "data": icon, - "digest": iconDigests[i] - } - }; - }), 'when attachments=true'); - return liveChangesPromise({include_docs: true}); - }).then(function (res) { - var attachments = res.results.sort(function (left, right) { - return left.id < right.id ? -1 : 1; - }).map(function (change) { - var doc = change.doc; - delete doc._attachments['foo.png'].revpos; - return doc._attachments['foo.png']; - }); - attachments.should.deep.equal(icons.map(function (icon, i) { - return { - "content_type": "image/png", - stub: true, - "digest": iconDigests[i], - length: iconLengths[i] - }; - }), 'when attachments=false'); - return liveChangesPromise({attachments: true}); - }).then(function (res) { - res.results.should.have.length(5); - res.results.forEach(function (row) { - should.not.exist(row.doc, - 'no doc when attachments=true but include_docs=false'); - }); - return liveChangesPromise({}); - }).then(function (res) { - res.results.should.have.length(5); - res.results.forEach(function (row) { - should.not.exist(row.doc, - 'no doc when attachments=false and include_docs=false'); - }); - }); - }); - - it('#3074 non-live changes(), no attachments', function () { - var db = new PouchDB(dbs.name); - var docs = []; - for (var i = 0; i < 5; i++) { - docs.push({ - _id: i.toString() - }); - } - return db.bulkDocs(docs).then(function () { - return db.changes({include_docs: true, attachments: true}); - }).then(function (res) { - var attachments = res.results.sort(function (left, right) { - return left.id < right.id ? -1 : 1; - }).map(function (change) { - var doc = change.doc; - return !!doc._attachments; - }); - attachments.should.deep.equal(icons.map(function (icon, i) { - return false; - }), 'when attachments=true'); - return db.changes({include_docs: true}); - }).then(function (res) { - var attachments = res.results.sort(function (left, right) { - return left.id < right.id ? -1 : 1; - }).map(function (change) { - var doc = change.doc; - return !!doc._attachments; - }); - attachments.should.deep.equal(icons.map(function (icon, i) { - return false; - }), 'when attachments=false'); - return db.changes({attachments: true}); - }).then(function (res) { - res.results.should.have.length(5); - res.results.forEach(function (row) { - should.not.exist(row.doc, - 'no doc when attachments=true but include_docs=false'); - }); - return db.changes(); - }).then(function (res) { - res.results.should.have.length(5); - res.results.forEach(function (row) { - should.not.exist(row.doc, - 'no doc when attachments=false and include_docs=false'); - }); - }); - }); - - it('#3074 live changes(), no attachments', function () { - - var db = new PouchDB(dbs.name); - - function liveChangesPromise(opts) { - opts.live = true; - return new PouchDB.utils.Promise(function (resolve, reject) { - var retChanges = {results: []}; - var changes = db.changes(opts) - .on('change', function (change) { - retChanges.results.push(change); - if (retChanges.results.length === 5) { - changes.cancel(); - resolve(retChanges); - } - }).on('error', reject); - }); - } - - var docs = []; - for (var i = 0; i < 5; i++) { - docs.push({ - _id: i.toString() - }); - } - return db.bulkDocs(docs).then(function () { - return liveChangesPromise({ - include_docs: true, - attachments: true - }); - }).then(function (res) { - var attachments = res.results.sort(function (left, right) { - return left.id < right.id ? -1 : 1; - }).map(function (change) { - var doc = change.doc; - return !!doc._attachments; - }); - attachments.should.deep.equal(icons.map(function (icon, i) { - return false; - }), 'when attachments=true'); - return liveChangesPromise({include_docs: true}); - }).then(function (res) { - var attachments = res.results.sort(function (left, right) { - return left.id < right.id ? -1 : 1; - }).map(function (change) { - var doc = change.doc; - return !!doc._attachments; - }); - attachments.should.deep.equal(icons.map(function (icon, i) { - return false; - }), 'when attachments=false'); - return liveChangesPromise({attachments: true}); - }).then(function (res) { - res.results.should.have.length(5); - res.results.forEach(function (row) { - should.not.exist(row.doc, - 'no doc when attachments=true but include_docs=false'); - }); - return liveChangesPromise({}); - }).then(function (res) { - res.results.should.have.length(5); - res.results.forEach(function (row) { - should.not.exist(row.doc, - 'no doc when attachments=false and include_docs=false'); - }); - }); - }); - - it('#2771 allDocs() 1, single attachment', function () { - var db = new PouchDB(dbs.name); - return db.put(binAttDoc).then(function () { - return db.allDocs({key: binAttDoc._id, include_docs: true}); - }).then(function (res) { - var doc = res.rows[0].doc; - delete doc._attachments["foo.txt"].revpos; - - // because of libicu vs. ascii - var digest = doc._attachments["foo.txt"].digest; - var validDigests = [ - "md5-qUUYqS41RhwF0TrCsTAxFg==", - "md5-aEI7pOYCRBLTRQvvqYrrJQ==" - ]; - validDigests.indexOf(digest).should.not.equal(-1, - 'expected ' + digest + ' to be in: ' + - JSON.stringify(validDigests)); - delete doc._attachments["foo.txt"].digest; - doc._attachments.should.deep.equal({ - "foo.txt": { - "content_type": "text/plain", - "stub": true, - length: 29 - } - }); - return db.allDocs({ - key: binAttDoc._id, - include_docs: true, - attachments: true - }); - }).then(function (res) { - var doc = res.rows[0].doc; - doc._attachments['foo.txt'].content_type.should.equal( - binAttDoc._attachments['foo.txt'].content_type); - doc._attachments['foo.txt'].data.should.equal( - binAttDoc._attachments['foo.txt'].data); - }); - }); - - it('#2771 allDocs() 2, many docs same att', function () { - var db = new PouchDB(dbs.name); - var docs = []; - for (var i = 0; i < 5; i++) { - docs.push({ - _id: i.toString(), - _attachments: { - 'foo.txt': { - data: 'VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ=', - content_type: 'text/plain' - } - } - }); - } - return db.bulkDocs(docs).then(function () { - return db.allDocs({include_docs: true, attachments: true}); - }).then(function (res) { - var attachments = res.rows.map(function (row) { - var doc = row.doc; - delete doc._attachments['foo.txt'].revpos; - should.exist(doc._attachments['foo.txt'].digest); - delete doc._attachments['foo.txt'].digest; - return doc._attachments; - }); - attachments.should.deep.equal([1, 2, 3, 4, 5].map(function () { - return { - "foo.txt": { - "content_type": "text/plain", - "data": "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ=" - } - }; - })); - }); - }); - - it('#2771 allDocs() 3, many docs diff atts', function () { - var db = new PouchDB(dbs.name); - var docs = []; - for (var i = 0; i < 5; i++) { - docs.push({ - _id: i.toString(), - _attachments: { - 'foo.png': { - data: icons[i], - content_type: 'image/png' - } - } - }); - } - return db.bulkDocs(docs).then(function () { - return db.allDocs({include_docs: true, attachments: true}); - }).then(function (res) { - var attachments = res.rows.map(function (row) { - var doc = row.doc; - delete doc._attachments['foo.png'].revpos; - return doc._attachments; - }); - attachments.should.deep.equal(icons.map(function (icon, i) { - return { - "foo.png": { - "content_type": "image/png", - "data": icon, - "digest": iconDigests[i] - } - }; - })); - return db.allDocs({include_docs: true}); - }).then(function (res) { - var attachments = res.rows.map(function (row) { - var doc = row.doc; - delete doc._attachments['foo.png'].revpos; - return doc._attachments['foo.png']; - }); - attachments.should.deep.equal(icons.map(function (icon, i) { - return { - "content_type": "image/png", - stub: true, - "digest": iconDigests[i], - length: iconLengths[i] - }; - })); - }); - }); - - it('#2771 allDocs() 4, mix of atts and no atts', function () { - var db = new PouchDB(dbs.name); - var docs = []; - for (var i = 0; i < 5; i++) { - var doc = { - _id: i.toString() - }; - if (i % 2 === 1) { - doc._attachments = { - 'foo.png': { - data: icons[i], - content_type: 'image/png' - } - }; - } - docs.push(doc); - } - return db.bulkDocs(docs).then(function () { - return db.allDocs({include_docs: true, attachments: true}); - }).then(function (res) { - var attachments = res.rows.map(function (row, i) { - var doc = row.doc; - if (i % 2 === 1) { - delete doc._attachments['foo.png'].revpos; - return doc._attachments; - } - return null; - }); - attachments.should.deep.equal(icons.map(function (icon, i) { - if (i % 2 === 0) { - return null; - } - return { - "foo.png": { - "content_type": "image/png", - "data": icon, - "digest": iconDigests[i] - } - }; - })); - return db.allDocs({include_docs: true}); - }).then(function (res) { - var attachments = res.rows.map(function (row, i) { - var doc = row.doc; - if (i % 2 === 1) { - delete doc._attachments['foo.png'].revpos; - return doc._attachments['foo.png']; - } - return null; - }); - attachments.should.deep.equal(icons.map(function (icon, i) { - if (i % 2 === 0) { - return null; - } - return { - "content_type": "image/png", - stub: true, - "digest": iconDigests[i], - length: iconLengths[i] - }; - })); - }); - }); - - it('#2771 allDocs() 5, no atts', function () { - var db = new PouchDB(dbs.name); - var docs = []; - for (var i = 0; i < 5; i++) { - var doc = { - _id: i.toString() - }; - docs.push(doc); - } - return db.bulkDocs(docs).then(function () { - return db.allDocs({include_docs: true, attachments: true}); - }).then(function (res) { - res.rows.should.have.length(5); - res.rows.forEach(function (row) { - should.exist(row.doc); - should.not.exist(row.doc._attachments); - }); - return db.allDocs({include_docs: true}); - }).then(function (res) { - res.rows.should.have.length(5); - res.rows.forEach(function (row) { - should.exist(row.doc); - should.not.exist(row.doc._attachments); - }); - }); - }); - - it('#2771 allDocs() 6, no docs', function () { - var db = new PouchDB(dbs.name); - var docs = []; - for (var i = 0; i < 5; i++) { - var doc = { - _id: i.toString() - }; - docs.push(doc); - } - return db.bulkDocs(docs).then(function () { - return db.allDocs({ - include_docs: true, - attachments: true, - keys: [] - }); - }).then(function (res) { - res.rows.should.have.length(0); - return db.allDocs({include_docs: true, keys: []}); - }).then(function (res) { - res.rows.should.have.length(0); - }); - }); - - it('#2771 allDocs() 7, revisions and deletions', function () { - var db = new PouchDB(dbs.name, {auto_compaction: false}); - var doc = { - _id: 'doc', - _attachments: { - 'foo.txt': { - content_type: 'text/plain', - data: 'Zm9vYmFy' // 'foobar' - } - } - }; - var rev; - return db.put(doc).then(function () { - return db.allDocs({keys: ['doc'], attachments: true, include_docs: true}); - }).then(function (res) { - var doc = res.rows[0].doc; - doc._attachments['foo.txt'].data.should.equal('Zm9vYmFy'); - rev = doc._rev; - doc._attachments['foo.txt'] = { - content_type: 'text/plain', - data: 'dG90bw==' - }; // 'toto' - return db.put(doc); - }).then(function () { - return db.allDocs({keys: ['doc'], attachments: true, include_docs: true}); - }).then(function (res) { - var doc = res.rows[0].doc; - doc._attachments['foo.txt'].data.should.equal('dG90bw=='); - return db.remove(doc); - }).then(function (res) { - rev = res.rev; - return db.allDocs({keys: ['doc'], attachments: true, include_docs: true}); - }).then(function (res) { - // technically CouchDB sets this to null, but we won't adhere strictly to that - should.not.exist(res.rows[0].doc); - delete res.rows[0].doc; - res.rows.should.deep.equal([ - { - id: "doc", - key: "doc", - value: { - rev: rev, - deleted: true - } - } - ]); - }); - }); - - it('#2771 allDocs() 8, empty attachment', function () { - var db = new PouchDB(dbs.name); - return db.put(binAttDoc2).then(function () { - return db.allDocs({key: binAttDoc2._id, include_docs: true}); - }).then(function (res) { - var doc = res.rows[0].doc; - delete doc._attachments["foo.txt"].revpos; - - // because of libicu vs. ascii - var digest = doc._attachments["foo.txt"].digest; - var validDigests = [ - 'md5-1B2M2Y8AsgTpgAmY7PhCfg==', - 'md5-cCkGbCesb17xjWYNV0GXmg==' - ]; - validDigests.indexOf(digest).should.not.equal(-1, - 'expected ' + digest + ' to be in: ' + - JSON.stringify(validDigests)); - delete doc._attachments["foo.txt"].digest; - delete doc._attachments["foo.txt"].digest; - doc._attachments.should.deep.equal({ - "foo.txt": { - "content_type": "text/plain", - "stub": true, - length: 0 - } - }); - return db.allDocs({ - key: binAttDoc2._id, - include_docs: true, - attachments: true - }); - }).then(function (res) { - var doc = res.rows[0].doc; - doc._attachments['foo.txt'].content_type.should.equal( - binAttDoc2._attachments['foo.txt'].content_type); - doc._attachments['foo.txt'].data.should.equal( - binAttDoc2._attachments['foo.txt'].data); - }); - }); - - it('No length for non-stubs', function () { - var db = new PouchDB(dbs.name); - return db.put(binAttDoc).then(function () { - return db.get(binAttDoc._id, {attachments: true}); - }).then(function (doc) { - should.not.exist(doc._attachments['foo.txt'].stub); - should.not.exist(doc._attachments['foo.txt'].length); - }); - }); - - it('Test some attachments', function (done) { - var db = new PouchDB(dbs.name); - db.put(binAttDoc, function (err, write) { - should.not.exist(err, 'saved doc with attachment'); - db.get('bin_doc', function (err, doc) { - should.exist(doc._attachments, 'doc has attachments field'); - should.exist(doc._attachments['foo.txt'], 'doc has attachment'); - doc._attachments['foo.txt'].content_type.should.equal('text/plain'); - db.getAttachment('bin_doc', 'foo.txt', function (err, res) { - testUtils.readBlob(res, function (data) { - data.should.equal('This is a base64 encoded text'); - db.put(binAttDoc2, function (err, rev) { - db.getAttachment('bin_doc2', 'foo.txt', - function (err, res, xhr) { - testUtils.readBlob(res, function (data) { - data.should.equal('', 'Correct data returned'); - moreTests(rev.rev); - }); - }); - }); - }); - }); - }); - }); - - function moreTests(rev) { - var blob = testUtils.makeBlob('This is no base64 encoded text'); - db.putAttachment('bin_doc2', 'foo2.txt', rev, blob, 'text/plain', - function (err, info) { - info.ok.should.equal(true); - db.getAttachment('bin_doc2', 'foo2.txt', function (err, res, xhr) { - testUtils.readBlob(res, function (data) { - should.exist(data); - db.get('bin_doc2', { attachments: true }, - function (err, res, xhr) { - should.exist(res._attachments, 'Result has attachments field'); - should.not - .exist(res._attachments['foo2.txt'].stub, 'stub is false'); - res._attachments['foo2.txt'].data.should - .equal('VGhpcyBpcyBubyBiYXNlNjQgZW5jb2RlZCB0ZXh0'); - res._attachments['foo2.txt'].content_type.should - .equal('text/plain'); - res._attachments['foo.txt'].data.should.equal(''); - done(); - }); - }); - }); - }); - } - }); - - it('Test getAttachment', function (done) { - var db = new PouchDB(dbs.name); - db.put(binAttDoc, function (err, res) { - db.getAttachment('bin_doc', 'foo.txt', function (err, res) { - if (err) { - return done(err); - } - testUtils.readBlob(res, function (data) { - data.should.equal('This is a base64 encoded text', 'correct data'); - done(); - }); - }); - }); - }); - - it('Test attachments in allDocs/changes', function (done) { - var db = new PouchDB(dbs.name); - var docs = [ - { _id: 'doc0' }, - { - _id: 'doc1', - _attachments: { - 'att0': { - data: 'YXR0YWNobWVudDA=', - content_type: 'text/plain' - } - } - }, - { - _id: 'doc2', - _attachments: { - 'att0': { - data: 'YXR0YWNobWVudDA=', - content_type: 'text/plain' - }, - 'att1': { - data: 'YXR0YWNobWVudDE=', - content_type: 'text/plain' - } - } - }, - { - _id: 'doc3', - _attachments: { - 'att0': { - data: 'YXR0YWNobWVudDA=', - content_type: 'text/plain' - } - } - } - ]; - function sort(a, b) { - return a.id.localeCompare(b.id); - } - db.bulkDocs({ docs: docs }, function (err, res) { - db.allDocs({ include_docs: true }, function (err, res) { - for (var i = 0; i < docs.length; i++) { - var attachmentsNb = typeof docs[i]._attachments !== 'undefined' ? - Object.keys(docs[i]._attachments).length : 0; - for (var j = 0; j < attachmentsNb; j++) { - res.rows[i].doc._attachments['att' + j].stub.should - .equal(true, '(allDocs) doc' + i + ' contains att' + j + - ' stub'); - } - } - should.not.exist(res.rows[0].doc._attachments, - '(allDocs) doc0 contains no attachments'); - db.changes({ - include_docs: true, - onChange: function (change) { - var i = +change.id.substr(3); - if (i === 0) { - should.not.exist(res.rows[0].doc._attachments, - '(onChange) doc0 contains no attachments'); - } else { - var attachmentsNb = - typeof docs[i]._attachments !== 'undefined' ? - Object.keys(docs[i]._attachments).length : 0; - for (var j = 0; j < attachmentsNb; j++) { - res.rows[i].doc._attachments['att' + j].stub.should - .equal(true, '(onChange) doc' + i + ' contains att' + j + - ' stub'); - } - } - }, - complete: function (err, res) { - var attachmentsNb = 0; - res.results.sort(sort); - for (var i = 0; i < 3; i++) { - attachmentsNb = typeof docs[i]._attachments !== 'undefined' ? - Object.keys(docs[i]._attachments).length : 0; - for (var j = 0; j < attachmentsNb; j++) { - res.results[i].doc._attachments['att' + j].stub.should - .equal(true, '(complete) doc' + i + ' contains att' + j + - ' stub'); - } - } - should.not.exist(res.results[0].doc._attachments, - '(complete) doc0 contains no attachments'); - done(); - } - }); - }); - }); - }); - - it('Test putAttachment with base64 plaintext', function () { - var db = new PouchDB(dbs.name); - return db.putAttachment('doc', 'att', null, 'Zm9v', 'text/plain').then(function () { - return db.getAttachment('doc', 'att'); - }).then(function (blob) { - return new PouchDB.utils.Promise(function (resolve) { - testUtils.base64Blob(blob, function (data) { - data.should.equal('Zm9v', 'should get the correct base64 back'); - resolve(); - }); - }); - }); - }); - - it('Test putAttachment with incorrect base64', function () { - var db = new PouchDB(dbs.name); - return db.putAttachment('doc', 'att', null, '\u65e5\u672c\u8a9e', 'text/plain').then(function () { - throw new Error('shouldnt have gotten here'); - }, function (err) { - should.exist(err); - }); - }); - - it('Test getAttachment with empty text', function (done) { - var db = new PouchDB(dbs.name); - db.put(binAttDoc2, function (err, res) { - if (err) { return done(err); } - db.getAttachment('bin_doc2', 'foo.txt', function (err, res) { - if (err) { return done(err); } - (typeof res).should.equal('object', 'res is object, ' + - 'not a string'); - testUtils.base64Blob(res, function (data) { - data.should.equal('', 'correct data'); - db.get(binAttDoc2._id, function (err, doc) { - var att = doc._attachments['foo.txt']; - att.stub.should.equal(true); - // both ascii and libicu - var validDigests = [ - 'md5-1B2M2Y8AsgTpgAmY7PhCfg==', - 'md5-cCkGbCesb17xjWYNV0GXmg==' - ]; - validDigests.indexOf(att.digest).should.be.above(-1); - att.content_type.should.equal('text/plain'); - att.length.should.equal(0); - done(); - }); - }); - }); - }); - }); - - it('Test getAttachment with normal text', function (done) { - var db = new PouchDB(dbs.name); - db.put(binAttDoc, function (err, res) { - if (err) { return done(err); } - db.getAttachment('bin_doc', 'foo.txt', function (err, res) { - if (err) { return done(err); } - (typeof res).should.equal('object', 'res is object, ' + - 'not a string'); - testUtils.base64Blob(res, function (data) { - data.should.equal( - binAttDoc._attachments['foo.txt'].data, 'correct data'); - done(); - }); - }); - }); - }); - - it('Test getAttachment with PNG', function (done) { - var db = new PouchDB(dbs.name); - db.put(pngAttDoc, function (err, res) { - if (err) { return done(err); } - db.getAttachment('png_doc', 'foo.png', function (err, res) { - if (err) { return done(err); } - (typeof res).should.equal('object', 'res is object, ' + - 'not a string'); - testUtils.base64Blob(res, function (data) { - data.should - .equal(pngAttDoc._attachments['foo.png'].data, 'correct data'); - done(); - }); - }); - }); - }); - - it('Test getAttachment with PNG using bulkDocs', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs([pngAttDoc], function (err, res) { - if (err) { return done(err); } - db.getAttachment('png_doc', 'foo.png', function (err, res) { - if (err) { return done(err); } - testUtils.base64Blob(res, function (data) { - data.should - .equal(pngAttDoc._attachments['foo.png'].data, 'correct data'); - done(); - }); - }); - }); - }); - - it('Test getAttachment with PNG using post', function (done) { - var db = new PouchDB(dbs.name); - db.post(pngAttDoc, function (err, res) { - if (err) { return done(err); } - db.getAttachment('png_doc', 'foo.png', function (err, res) { - if (err) { return done(err); } - testUtils.base64Blob(res, function (data) { - data.should - .equal(pngAttDoc._attachments['foo.png'].data, 'correct data'); - done(); - }); - }); - }); - }); - - it('Test postAttachment with PNG then bulkDocs', function (done) { - var db = new PouchDB(dbs.name); - db.put({ _id: 'foo' }, function (err, res) { - db.get('foo', function (err, doc) { - var data = pngAttDoc._attachments['foo.png'].data; - var blob = testUtils - .makeBlob(PouchDB.utils.fixBinary(PouchDB.utils.atob(data)), - 'image/png'); - db.putAttachment('foo', 'foo.png', doc._rev, blob, 'image/png', - function (err, info) { - should.not.exist(err, 'attachment inserted'); - db.bulkDocs([{}], function (err) { - should.not.exist(err, 'doc inserted'); - done(); - }); - }); - }); - }); - }); - - it('proper stub behavior', function () { - var db = new PouchDB(dbs.name); - return db.put(binAttDoc).then(function () { - return db.get(binAttDoc._id); - }).then(function (doc) { - return db.putAttachment(doc._id, 'foo.json', doc._rev, - jsonDoc._attachments['foo.json'].data, - jsonDoc._attachments['foo.json'].content_type); - }).then(function () { - return db.get(binAttDoc._id); - }).then(function (doc) { - Object.keys(doc._attachments).forEach(function (filename) { - var att = doc._attachments[filename]; - should.not.exist(att.data); - att.stub.should.equal(true); - should.exist(att.digest); - should.exist(att.content_type); - }); - return db.get(binAttDoc._id, {attachments: true}); - }).then(function (doc) { - Object.keys(doc._attachments).forEach(function (filename) { - var att = doc._attachments[filename]; - should.exist(att.data); - should.not.exist(att.stub); - should.exist(att.digest); - should.exist(att.content_type); - }); - }); - }); - - it('Testing with invalid docs', function (done) { - var db = new PouchDB(dbs.name); - var invalidDoc = { - '_id': '_invalid', - foo: 'bar' - }; - db.bulkDocs({ - docs: [ - invalidDoc, - binAttDoc - ] - }, function (err, info) { - should.exist(err, 'bad request'); - done(); - }); - }); - - it('Test create attachment and doc in one go', function (done) { - var db = new PouchDB(dbs.name); - var blob = testUtils.makeBlob('Mytext'); - db.putAttachment('anotherdoc', 'mytext', blob, 'text/plain', - function (err, res) { - should.exist(res.ok); - done(); - }); - }); - - it('Test create attachment and doc in one go without callback', - function (done) { - var db = new PouchDB(dbs.name); - var changes = db.changes({ - complete: function (err, result) { - result.status.should.equal('cancelled'); - done(); - }, - live: true, - onChange: function (change) { - if (change.seq === 1) { - change.id.should.equal('anotherdoc2', 'Doc has been created'); - db.get(change.id, { attachments: true }, function (err, doc) { - doc._attachments.should.be - .an('object', 'doc has attachments object'); - should.exist(doc._attachments.mytext, - 'doc has attachments attachment'); - doc._attachments.mytext.data.should - .equal('TXl0ZXh0', 'doc has attachments attachment'); - changes.cancel(); - }); - } - } - }); - var blob = testUtils.makeBlob('Mytext'); - db.putAttachment('anotherdoc2', 'mytext', blob, 'text/plain'); - }); - - it('Test create attachment without callback', function (done) { - var db = new PouchDB(dbs.name); - db.put({ _id: 'anotherdoc3' }, function (err, resp) { - should.not.exist(err, 'doc was saved'); - var changes = db.changes({ - complete: function (err, result) { - result.status.should.equal('cancelled'); - done(); - }, - live: true, - include_docs: true, - onChange: function (change) { - if (change.seq === 2) { - change.id.should.equal('anotherdoc3', 'Doc has been created'); - db.get(change.id, { attachments: true }, function (err, doc) { - doc._attachments.should.be.an('object', - 'doc has attachments object'); - should.exist(doc._attachments.mytext); - doc._attachments.mytext.data.should.equal('TXl0ZXh0'); - changes.cancel(); - }); - } - } - }); - var blob = testUtils.makeBlob('Mytext'); - db.putAttachment('anotherdoc3', 'mytext', resp.rev, blob, 'text/plain'); - }); - }); - - it('Test put attachment on a doc without attachments', function (done) { - var db = new PouchDB(dbs.name); - db.put({ _id: 'mydoc' }, function (err, resp) { - var blob = testUtils.makeBlob('Mytext'); - db.putAttachment('mydoc', 'mytext', resp.rev, blob, 'text/plain', - function (err, res) { - should.exist(res.ok); - done(); - }); - }); - }); - - it('Test put attachment with unencoded name', function (done) { - var db = new PouchDB(dbs.name); - db.put({ _id: 'mydoc' }, function (err, resp) { - var blob = testUtils.makeBlob('Mytext'); - db.putAttachment('mydoc', 'my/text?@', resp.rev, blob, 'text/plain', - function (err, res) { - should.exist(res.ok); - - db.get('mydoc', { attachments: true }, function (err, res) { - should.exist(res._attachments['my/text?@']); - - db.getAttachment('mydoc', 'my/text?@', function (err, attachment) { - testUtils.readBlob(attachment, function (data) { - data.should.eql('Mytext'); - - done(); - }); - }); - }); - }); - }); - }); - - it('Testing with invalid rev', function (done) { - var db = new PouchDB(dbs.name); - var doc = { _id: 'adoc' }; - db.put(doc, function (err, resp) { - should.not.exist(err, 'Doc has been saved'); - doc._rev = resp.rev; - doc.foo = 'bar'; - db.put(doc, function (err, resp) { - should.not.exist(err, 'Doc has been updated'); - var blob = testUtils.makeBlob('bar'); - db.putAttachment('adoc', 'foo.txt', doc._rev, blob, 'text/plain', - function (err) { - should.exist(err, 'Attachment has not been saved'); - err.name.should.equal('conflict', 'error is a conflict'); - done(); - }); - }); - }); - }); - - it('Test put another attachment on a doc with attachments', - function (done) { - var db = new PouchDB(dbs.name); - db.put({ _id: 'mydoc' }, function (err, res1) { - var blob = testUtils.makeBlob('Mytext'); - db.putAttachment('mydoc', 'mytext', res1.rev, blob, 'text/plain', - function (err, res2) { - db.putAttachment('mydoc', 'mytext2', res2.rev, blob, 'text/plain', - function (err, res3) { - should.exist(res3.ok); - done(); - }); - }); - }); - }); - - it('Test get with attachments: true if empty attachments', function (done) { - var db = new PouchDB(dbs.name); - db.put({ - _id: 'foo', - _attachments: {} - }, function (err, resp) { - db.get('foo', { attachments: true }, function (err, res) { - res._id.should.equal('foo'); - done(); - }); - }); - }); - - it('Test delete attachment from a doc', function (done) { - var db = new PouchDB(dbs.name); - db.put({ - _id: 'mydoc', - _attachments: { - 'mytext1': { - content_type: 'text/plain', - data: 'TXl0ZXh0MQ==' - }, - 'mytext2': { - content_type: 'text/plain', - data: 'TXl0ZXh0Mg==' - } - } - }, function (err, res) { - var rev = res.rev; - db.get('mydoc', { attachments: true }, function (err, res) { - res._attachments.should.include.keys('mytext1', 'mytext2'); - db.removeAttachment('mydoc', 'mytext1', 0, function (err, res) { - should.exist(err, 'removal should fail due to broken rev'); - db.removeAttachment('mydoc', 'mytext1', rev, function (err, res) { - db.get('mydoc', { attachments: true }, function (err, res) { - res._attachments.should.not.include.keys('mytext1'); - res._attachments.should.include.keys('mytext2'); - db.removeAttachment('mydoc', 'mytext2', res._rev, - function (err, res) { - should.not.exist(res._attachments); - done(); - }); - }); - }); - }); - }); - }); - }); - - it('Test a document with a json string attachment', function (done) { - var db = new PouchDB(dbs.name); - db.put(jsonDoc, function (err, results) { - should.not.exist(err, 'saved doc with attachment'); - db.get(results.id, function (err, doc) { - should.not.exist(err, 'fetched doc'); - should.exist(doc._attachments, 'doc has attachments field'); - doc._attachments.should.include.keys('foo.json'); - doc._attachments['foo.json'].content_type.should - .equal('application/json', 'doc has correct content type'); - db.getAttachment(results.id, 'foo.json', function (err, attachment) { - testUtils.readBlob(attachment, function (data) { - jsonDoc._attachments['foo.json'].data.should - .equal('eyJIZWxsbyI6IndvcmxkIn0=', 'correct data'); - done(); - }); - }); - }); - }); - }); - - it('Test remove doc with attachment', function (done) { - var db = new PouchDB(dbs.name); - db.put({ _id: 'mydoc' }, function (err, resp) { - var blob = testUtils.makeBlob('Mytext'); - db.putAttachment('mydoc', 'mytext', resp.rev, blob, 'text/plain', - function (err, res) { - db.get('mydoc', { attachments: false }, function (err, doc) { - db.remove(doc, function (err, resp) { - should.exist(res.ok); - done(); - }); - }); - }); - }); - }); - - it('Try to insert a doc with unencoded attachment', function (done) { - var db = new PouchDB(dbs.name); - var doc = { - _id: 'foo', - _attachments: { - 'foo.txt': { - content_type: 'text/plain', - data: 'this should have been encoded!' - } - } - }; - db.put(doc, function (err, res) { - should.exist(err); - err.status.should.equal(500, 'correct error'); - err.name.should.equal('badarg', 'correct error'); - done(); - }); - }); - - it('Try to get attachment of unexistent doc', function (done) { - var db = new PouchDB(dbs.name); - db.getAttachment('unexistent', 'attachment', function (err, res) { - should.exist(err, 'Correctly returned error'); - done(); - }); - }); - - it('Test synchronous getAttachment', function (done) { - var db = new PouchDB(dbs.name); - db.getAttachment('unexistent', 'attachment', function (err, res) { - should.exist(err, 'Correctly returned error'); - done(); - }); - }); - - it('Test synchronous putAttachment with text data', function (done) { - var db = new PouchDB(dbs.name); - var blob = testUtils.makeBlob('foobaz', 'text/plain'); - db.putAttachment('a', 'foo2.txt', '', blob, 'text/plain', function (err) { - should.not.exist(err, 'Correctly wrote attachment'); - db.get('a', { attachments: true }, function (err, doc) { - should.not.exist(err, 'Correctly got attachment'); - doc._attachments['foo2.txt'].data.should.equal('Zm9vYmF6'); - doc._attachments['foo2.txt'].content_type.should.equal('text/plain'); - done(); - }); - }); - }); - - it('Test synchronous putAttachment with no text data', function (done) { - var db = new PouchDB(dbs.name); - db.putAttachment('a', 'foo2.txt', '', '', 'text/plain', function (err) { - should.not.exist(err, 'Correctly wrote attachment'); - db.get('a', { attachments: true }, function (err, doc) { - should.not.exist(err, 'Correctly got attachment'); - doc._attachments['foo2.txt'].data.should.equal(''); - // firefox 3 appends charset=utf8 - // see http://forums.mozillazine.org/viewtopic.php?p=6318215#p6318215 - doc._attachments['foo2.txt'].content_type.indexOf('text/plain') - .should.equal(0, 'expected content-type to start with text/plain'); - done(); - }); - }); - }); - - it('Test put with partial stubs', function () { - var db = new PouchDB(dbs.name); - var doc = { - _id: 'doc', - _attachments: { - 'foo.txt': { - content_type: 'text/plain', - data: 'Zm9v' - }, - 'bar.txt': { - content_type: 'text/plain', - data: 'Zm9v' - } - } - }; - return db.put(doc).then(function () { - return db.get(doc._id); - }).then(function (doc) { - doc._attachments['baz.txt'] = { - content_type: 'text/plain', - data: 'Zm9v' - }; - // at this point, foo and bar are stubs, but baz is not - return db.put(doc); - }).then(function () { - return db.get(doc._id, {attachments: true}); - }).then(function (doc) { - doc._rev.should.not.equal('2-x'); - Object.keys(doc._attachments).should.have.length(3); - Object.keys(doc._attachments).forEach(function (key) { - var att = doc._attachments[key]; - att.data.should.equal('Zm9v'); - att.content_type.should.equal('text/plain'); - }); - }); - }); - - it('Test put with attachments and new_edits=false', function () { - var db = new PouchDB(dbs.name); - var doc = { - _id: 'doc', - _rev: '2-x', - _attachments: { - 'foo.txt': { - content_type: 'text/plain', - data: 'Zm9v' - }, - 'bar.txt': { - content_type: 'text/plain', - data: 'Zm9v' - }, - 'baz.txt': { - content_type: 'text/plain', - data: 'Zm9v' - } - }, - _revisions: { - 'start': 2, - 'ids': ['x', 'a'] - } - }; - return db.bulkDocs([doc], {new_edits: false}).then(function () { - return db.get(doc._id); - }).then(function () { - // at this point, foo and bar are stubs, but baz is not - return db.bulkDocs([doc], {new_edits: false}); - }).then(function () { - return db.get(doc._id, {attachments: true}); - }).then(function (doc) { - doc._rev.should.equal('2-x'); - Object.keys(doc._attachments).should.have.length(3); - Object.keys(doc._attachments).forEach(function (key) { - var att = doc._attachments[key]; - att.data.should.equal('Zm9v'); - att.content_type.should.equal('text/plain'); - }); - }); - }); - - it('Test stubs', function (done) { - var db = new PouchDB(dbs.name); - db.putAttachment('a', 'foo2.txt', '', '', 'text/plain', function (err) { - db.allDocs({ include_docs: true }, function (err, docs) { - should.not.exist(docs.rows[0].stub, 'no stub'); - done(); - }); - }); - }); - - it('Try to get unexistent attachment of some doc', function (done) { - var db = new PouchDB(dbs.name); - db.put({ _id: 'foo' }, function (err, res) { - should.not.exist(err, 'doc inserted'); - db.getAttachment('foo', 'unexistentAttachment', function (err, res) { - should.exist(err, 'Correctly returned error'); - done(); - }); - }); - }); - - it('putAttachment and getAttachment with plaintext', function (done) { - var db = new PouchDB(dbs.name); - db.put({ _id: 'foo' }, function (err, res) { - db.get('foo', function (err, doc) { - var data = binAttDoc._attachments['foo.txt'].data; - var blob = testUtils - .makeBlob(PouchDB.utils.fixBinary(PouchDB.utils.atob(data)), - 'text/plain'); - db.putAttachment('foo', 'foo.txt', doc._rev, blob, 'text/plain', - function (err, info) { - should.not.exist(err, 'attachment inserted'); - db.getAttachment('foo', 'foo.txt', function (err, blob) { - should.not.exist(err, 'attachment gotten'); - testUtils.readBlob(blob, function (returnedData) { - PouchDB.utils.btoa(returnedData).should.equal(data); - db.get('foo', function (err, doc) { - should.not.exist(err, 'err on get'); - delete doc._attachments["foo.txt"].revpos; - - // couchdb encodes plaintext strings differently from us - // because of libicu vs. ascii. that's okay - var digest = doc._attachments["foo.txt"].digest; - var validDigests = [ - "md5-qUUYqS41RhwF0TrCsTAxFg==", - "md5-aEI7pOYCRBLTRQvvqYrrJQ==" - ]; - validDigests.indexOf(digest).should.not.equal(-1, - 'expected ' + digest + ' to be in: ' + - JSON.stringify(validDigests)); - delete doc._attachments["foo.txt"].digest; - doc._attachments.should.deep.equal({ - "foo.txt": { - "content_type": "text/plain", - "stub": true, - length: 29 - } - }); - done(); - }); - }); - }); - }); - }); - }); - }); - - it('putAttachment and getAttachment with png data', function (done) { - var db = new PouchDB(dbs.name); - db.put({ _id: 'foo' }, function (err, res) { - db.get('foo', function (err, doc) { - var data = pngAttDoc._attachments['foo.png'].data; - var blob = testUtils - .makeBlob(PouchDB.utils.fixBinary(PouchDB.utils.atob(data)), - 'image/png'); - db.putAttachment('foo', 'foo.png', doc._rev, blob, 'image/png', - function (err, info) { - should.not.exist(err, 'attachment inserted'); - db.getAttachment('foo', 'foo.png', function (err, blob) { - should.not.exist(err, 'attachment gotten'); - testUtils.readBlob(blob, function (returnedData) { - PouchDB.utils.btoa(returnedData).should.equal(data); - db.get('foo', function (err, doc) { - should.not.exist(err, 'err on get'); - delete doc._attachments["foo.png"].revpos; - doc._attachments.should.deep.equal({ - "foo.png": { - "content_type": "image/png", - "digest": "md5-c6eA+rofKUsstTNQBKUc8A==", - "stub": true, - length: 229 - } - }); - done(); - }); - }); - }); - }); - }); - }); - }); - - it('#2818 - save same attachment in different revs', function () { - var db = new PouchDB(dbs.name, {auto_compaction: false}); - - return db.put({_id: 'foo'}).then(function (res) { - return db.putAttachment('foo', 'att', res.rev, 'Zm9v', 'text/plain'); - }).then(function () { - return db.get('foo', {attachments: true}); - }).then(function (doc) { - doc._attachments['att'].content_type.should.match(/^text\/plain/); - should.exist(doc._attachments['att'].data); - return db.get('foo'); - }).then(function (doc) { - return db.put(doc); - }).then(function () { - return db.compact(); - }).then(function () { - return db.get('foo', {attachments: true}); - }).then(function (doc) { - doc._attachments['att'].content_type.should.match(/^text\/plain/); - doc._attachments['att'].data.length.should.be.above(0, 'attachment exists'); - }); - }); - - it('#2818 - save same attachment many times in parallel', function () { - var db = new PouchDB(dbs.name); - var docs = []; - - for (var i = 0; i < 50; i++) { - docs.push({ - _id: 'doc' + i, - _attachments: { - 'foo.txt': { - content_type: 'text/plain', - data: 'Zm9vYmFy' // 'foobar' - } - } - }); - } - return db.bulkDocs(docs); - }); - - it('#2818 - revisions keep attachments (no compaction)', function () { - var db = new PouchDB(dbs.name, {auto_compaction: false}); - var doc = { - _id: 'doc', - _attachments: { - 'foo.txt': { - content_type: 'text/plain', - data: 'Zm9vYmFy' // 'foobar' - } - } - }; - var rev; - return db.put(doc).then(function () { - return db.get('doc'); - }).then(function (doc) { - rev = doc._rev; - //delete doc._attachments['foo.txt']; - doc._attachments['foo.txt'] = { - content_type: 'text/plain', - data: 'dG90bw==' - }; // 'toto' - return db.put(doc); - }).then(function () { - return db.get('doc', {attachments: true}); - }).then(function (doc) { - doc._attachments['foo.txt'].data.should.equal('dG90bw=='); - return db.get('doc', {rev: rev, attachments: true}); - }).then(function (doc) { - doc._attachments['foo.txt'].data.should.equal('Zm9vYmFy'); - }); - }); - - it('#2818 - doesn\'t throw 409 if same filename', function () { - var db = new PouchDB(dbs.name, {auto_compaction: false}); - var doc = { - _id: 'doc', - _attachments: { - 'foo.txt': { - content_type: 'text/plain', - data: 'Zm9vYmFy' // 'foobar' - } - } - }; - var rev; - return db.put(doc).then(function (res) { - rev = doc._rev = res.rev; - doc._attachments['foo.txt'].data = 'dG90bw=='; // 'toto' - return db.put(doc); - }); - }); - - if (typeof process === 'undefined' || process.browser) { - it('test stored URL content type of png data', function (done) { - var db = new PouchDB(dbs.name); - db.put({ _id: 'foo' }, function (err, res) { - db.get('foo', function (err, doc) { - var data = pngAttDoc._attachments['foo.png'].data; - var blob = testUtils - .makeBlob(PouchDB.utils.fixBinary(PouchDB.utils.atob(data)), - 'image/png'); - if (typeof URL === 'undefined') { - // phantomjs doesn't have this, give up on this test - return done(); - } - var checkedOnce = false; - function checkBlobType(blob, cb) { - var url = URL.createObjectURL(blob); - PouchDB.utils.ajax({ - url: url, - cache: true, - binary: true - }, function (err, res) { - if (err && err.status === 405) { - // firefox won't let us use ajax to get the blob. - // too bad, but firefox wasn't the problem anyway - return done(); - } - should.not.exist(err, 'ajax gotten'); - if (!checkedOnce) { - checkedOnce = true; - if (res.type !== 'image/png') { - // in Safari/iOS 7, blob URLs are missing - // the content type even without storing them. - // so just give up. - return done(); - } - } else { - res.type.should.equal('image/png'); - } - cb(); - }); - } - checkBlobType(blob, function () { - db.putAttachment('foo', 'foo.png', doc._rev, blob, 'image/png', - function (err, info) { - should.not.exist(err, 'attachment inserted'); - db.getAttachment('foo', 'foo.png', function (err, blob) { - should.not.exist(err, 'attachment gotten'); - checkBlobType(blob, done); - }); - }); - }); - }); - }); - }); - } - - it('#3008 test correct encoding/decoding of \\u0000 etc.', function () { - - var base64 = - 'iVBORw0KGgoAAAANSUhEUgAAAhgAAAJLCAYAAAClnu9J' + - 'AAAgAElEQVR4Xuy9B7ylZXUu/p62T5nOMAPM0BVJICQi' + - 'ogjEJN5ohEgQ'; - - var db = new PouchDB(dbs.name); - return db.putAttachment('foo', 'foo.bin', base64, 'image/png').then(function () { - return db.getAttachment('foo', 'foo.bin'); - }).then(function (blob) { - return new PouchDB.utils.Promise(function (resolve) { - testUtils.readBlob(blob, resolve); - }); - }).then(function (bin) { - PouchDB.utils.btoa(bin).should.equal(base64); - }); - }); - - - var isSafari = (typeof process === 'undefined' || process.browser) && - /Safari/.test(window.navigator.userAgent) && - !/Chrome/.test(window.navigator.userAgent); - if (!isSafari) { - // skip in safari/ios because of size limit popup - it('putAttachment and getAttachment with big png data', function (done) { - - function getData(cb) { - if (typeof process !== 'undefined' && !process.browser) { - var bigimage = require('./deps/bigimage.js'); - cb(null, bigimage); - } else { // browser - var script = document.createElement('script'); - script.src = 'deps/bigimage.js'; - document.body.appendChild(script); - var timeout = setInterval(function () { - if (!!window.bigimage) { - clearInterval(timeout); - cb(null, window.bigimage); - } - }, 500); - } - } - - var db = new PouchDB(dbs.name); - db.put({ _id: 'foo' }, function (err, res) { - db.get('foo', function (err, doc) { - - getData(function (err, data) { - var blob = testUtils - .makeBlob(PouchDB.utils.fixBinary(PouchDB.utils.atob(data)), - 'image/png'); - db.putAttachment('foo', 'foo.png', doc._rev, blob, 'image/png', - function (err, info) { - should.not.exist(err, 'attachment inserted'); - db.getAttachment('foo', 'foo.png', function (err, blob) { - should.not.exist(err, 'attachment gotten'); - testUtils.readBlob(blob, function (returnedData) { - PouchDB.utils.btoa(returnedData).should.equal(data); - db.get('foo', function (err, doc) { - should.not.exist(err, 'err on get'); - delete doc._attachments["foo.png"].revpos; - doc._attachments.should.deep.equal({ - "foo.png": { - "content_type": "image/png", - "digest": "md5-kqr2YcdElgDs3RkMn1Ygbw==", - "stub": true, - length: 678010 - } - }); - done(); - }); - }); - }); - }); - }); - }); - }); - }); - } - }); -}); - -repl_adapters.forEach(function (adapters) { - describe('test.attachments.js- ' + adapters[0] + ':' + adapters[1], - function () { - - var dbs = {}; - - beforeEach(function (done) { - dbs.name = testUtils.adapterUrl(adapters[0], 'testdb'); - dbs.remote = testUtils.adapterUrl(adapters[1], 'test_attach_remote'); - testUtils.cleanup([dbs.name, dbs.remote], done); - }); - - afterEach(function (done) { - testUtils.cleanup([dbs.name, dbs.remote], done); - }); - - it('Attachments replicate', function (done) { - var binAttDoc = { - _id: 'bin_doc', - _attachments: { - 'foo.txt': { - content_type: 'text/plain', - data: 'VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ=' - } - } - }; - var docs1 = [ - binAttDoc, - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - {_id: '2', integer: 2}, - {_id: '3', integer: 3} - ]; - - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - - remote.bulkDocs({ docs: docs1 }, function (err, info) { - db.replicate.from(remote, function () { - db.get('bin_doc', { attachments: true }, function (err, doc) { - binAttDoc._attachments['foo.txt'].data.should - .equal(doc._attachments['foo.txt'].data); - done(); - }); - }); - }); - }); - - it('Many many attachments replicate', function () { - var doc = {_id: 'foo'}; - - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var rev; - - var data = PouchDB.utils.btoa('foobar'); - var blob = testUtils - .makeBlob(PouchDB.utils.fixBinary(PouchDB.utils.atob(data)), - 'text/plain'); - - doc._attachments = {}; - var expectedKeys = []; - for (var i = 0; i < 50; i++) { - doc._attachments[i + '.txt'] = { - content_type: 'text/plain', - data: blob - }; - expectedKeys.push(i + '.txt'); - } - return db.put(doc).then(function (info) { - rev = info.rev; - return db.replicate.to(remote); - }).then(function () { - return remote.get('foo', {attachments: true}); - }).then(function (doc) { - var keys = Object.keys(doc._attachments); - keys.sort(); - keys.should.deep.equal(expectedKeys.sort()); - doc._attachments[keys[0]].data.should.equal(data); - }); - }); - - it('Many many png attachments replicate', function () { - var doc = {_id: 'foo'}; - - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var rev; - - var data = 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAMFBMVEX+9+' + - 'j+9OD+7tL95rr93qT80YD7x2L6vkn6syz5qRT4ogT4nwD4ngD4nQD4nQD4' + - 'nQDT2nT/AAAAcElEQVQY002OUQLEQARDw1D14f7X3TCdbfPnhQTqI5UqvG' + - 'OWIz8gAIXFH9zmC63XRyTsOsCWk2A9Ga7wCXlA9m2S6G4JlVwQkpw/Ymxr' + - 'UgNoMoyxBwSMH/WnAzy5cnfLFu+dK2l5gMvuPGLGJd1/9AOiBQiEgkzOpg' + - 'AAAABJRU5ErkJggg=='; - var blob = testUtils - .makeBlob(PouchDB.utils.fixBinary(PouchDB.utils.atob(data)), - 'image/png'); - - doc._attachments = {}; - var expectedKeys = []; - for (var i = 0; i < 50; i++) { - doc._attachments[i + '.txt'] = { - content_type: 'image/png', - data: blob - }; - expectedKeys.push(i + '.txt'); - } - return db.put(doc).then(function (info) { - rev = info.rev; - return db.replicate.to(remote); - }).then(function () { - return remote.get('foo', {attachments: true}); - }).then(function (doc) { - var keys = Object.keys(doc._attachments); - keys.sort(); - keys.should.deep.equal(expectedKeys.sort()); - doc._attachments[keys[0]].data.should.equal(data); - }); - }); - - it('Multiple attachments replicate', function () { - var doc = {_id: 'foo'}; - - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - - var data = 'VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ='; - var rev; - return db.put(doc).then(function (info) { - rev = info.rev; - return db.replicate.to(remote); - }).then(function () { - return db.putAttachment(doc._id, 'foo1.txt', rev, data, 'text/plain'); - }).then(function (info) { - rev = info.rev; - return db.putAttachment(doc._id, 'foo2.txt', rev, data, 'text/plain'); - }).then(function (info) { - rev = info.rev; - return db.putAttachment(doc._id, 'foo3.txt', rev, data, 'text/plain'); - }).then(function () { - return db.replicate.to(remote); - }).then(function () { - return remote.get('foo', {attachments: true}); - }).then(function (doc) { - var keys = Object.keys(doc._attachments); - keys.sort(); - keys.should.deep.equal(['foo1.txt', 'foo2.txt', 'foo3.txt']); - }); - }); - - it('Multiple attachments replicate, different docs (#2698)', function () { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var docs = []; - for (var i = 0; i < 5; i++) { - docs.push({ - _id: i.toString(), - _attachments: { - 'foo.txt': { - data: 'VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ=', - content_type: 'text/plain' - } - } - }); - } - return remote.bulkDocs(docs).then(function (info) { - return remote.replicate.to(db); - }).then(function () { - return db.allDocs(); - }).then(function (res) { - return PouchDB.utils.Promise.all(res.rows.map(function (row) { - return db.get(row.id, {attachments: true}); - })); - }).then(function (docs) { - var attachments = docs.map(function (doc) { - delete doc._attachments['foo.txt'].revpos; - delete doc._attachments['foo.txt'].digest; - return doc._attachments; - }); - attachments.should.deep.equal([1, 2, 3, 4, 5].map(function () { - return { - "foo.txt": { - "content_type": "text/plain", - "data": "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ=" - } - }; - })); - }); - }); - - it('Multiple attachments replicate, different docs png (#2698)', function () { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var docs = []; - for (var i = 0; i < 5; i++) { - docs.push({ - _id: i.toString(), - _attachments: { - 'foo.png': { - data: icons[i], - content_type: 'image/png' - } - } - }); - } - return remote.bulkDocs(docs).then(function (info) { - return remote.replicate.to(db); - }).then(function () { - return db.allDocs(); - }).then(function (res) { - return PouchDB.utils.Promise.all(res.rows.map(function (row) { - return db.get(row.id, {attachments: true}); - })); - }).then(function (docs) { - var attachments = docs.map(function (doc) { - delete doc._attachments['foo.png'].revpos; - return doc._attachments; - }); - attachments.should.deep.equal(icons.map(function (icon, i) { - return { - "foo.png": { - "content_type": "image/png", - "data": icon, - "digest": iconDigests[i] - } - }; - })); - - return PouchDB.utils.Promise.all(docs.map(function (doc) { - return db.get(doc._id); - })); - }).then(function (docs) { - var attachments = docs.map(function (doc) { - delete doc._attachments['foo.png'].revpos; - return doc._attachments['foo.png']; - }); - attachments.should.deep.equal(icons.map(function (icon, i) { - return { - "content_type": "image/png", - stub: true, - "digest": iconDigests[i], - length: iconLengths[i] - }; - })); - }); - }); - - it('replication with changing attachments', function () { - var attachment = { - content_type: 'text/plain', - data: 'VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ=' - }; - var attachment2 = { - content_type: 'text/plain', - data: '' - }; - var binAttDoc = { - _id: 'bin_doc', - _attachments: { - 'foo.txt': attachment - } - }; - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - return db.put(binAttDoc).then(function () { - return db.get(binAttDoc._id); - }).then(function (doc) { - should.exist(doc); - return db.get(binAttDoc._id); - }).then(function (doc) { - doc._attachments['bar.txt'] = attachment2; - return db.put(doc); - }).then(function () { - return db.get(binAttDoc._id); - }).then(function (doc) { - should.exist(doc); - return db.get(binAttDoc._id, {attachments: true}); - }).then(function (doc) { - should.not.exist(doc._attachments['foo.txt'].stub); - should.not.exist(doc._attachments['bar.txt'].stub); - return db.replicate.to(remote); - }).then(function () { - return remote.get(binAttDoc._id, {attachments: true}); - }).then(function (doc) { - should.not.exist(doc._attachments['foo.txt'].stub); - doc._attachments['baz.txt'] = doc._attachments['foo.txt']; - return remote.put(doc); - }).then(function () { - return remote.replicate.to(db); - }).then(function () { - return db.get(binAttDoc._id, {attachments: true}); - }).then(function (doc) { - should.not.exist(doc._attachments['foo.txt'].stub); - should.not.exist(doc._attachments['bar.txt'].stub); - should.not.exist(doc._attachments['baz.txt'].stub); - return db.get(binAttDoc._id); - }).then(function (doc) { - should.exist(doc); - }); - }); - }); -});
diff --git a/tests/integration/test.basics.js b/tests/integration/test.basics.js deleted file mode 100644 index 6149070..0000000 --- a/tests/integration/test.basics.js +++ /dev/null
@@ -1,977 +0,0 @@ -'use strict'; - -var adapters = ['http', 'local']; - -adapters.forEach(function (adapter) { - describe('test.basics.js-' + adapter, function () { - - var dbs = {}; - - beforeEach(function (done) { - dbs.name = testUtils.adapterUrl(adapter, 'testdb'); - testUtils.cleanup([dbs.name], done); - }); - - after(function (done) { - testUtils.cleanup([dbs.name], done); - }); - - - it('Create a pouch', function (done) { - new PouchDB(dbs.name, function (err, db) { - should.not.exist(err); - db.should.be.an.instanceof(PouchDB); - done(); - }); - }); - - it('Create a pouch with a promise', function (done) { - new PouchDB(dbs.name).then(function (db) { - db.should.be.an.instanceof(PouchDB); - done(); - }, done); - }); - - it('Catch an error when creating a pouch with a promise', function (done) { - new PouchDB().catch(function (err) { - should.exist(err); - done(); - }); - }); - - it('Remove a pouch', function (done) { - new PouchDB(dbs.name, function (err, db) { - PouchDB.destroy(dbs, function (err, info) { - should.not.exist(err); - should.exist(info); - info.ok.should.equal(true); - done(); - }); - }); - }); - - it('Remove a pouch, with a promise', function (done) { - new PouchDB(dbs.name, function (err, db) { - PouchDB.destroy(dbs).then(function (info) { - should.exist(info); - info.ok.should.equal(true); - done(); - }, done); - }); - }); - - it('destroy a pouch', function (done) { - new PouchDB(dbs.name, function (err, db) { - db.destroy(function (err, info) { - should.not.exist(err); - should.exist(info); - info.ok.should.equal(true); - done(); - }); - }); - }); - - it('destroy a pouch, with a promise', function (done) { - new PouchDB(dbs.name, function (err, db) { - db.destroy().then(function (info) { - should.exist(info); - info.ok.should.equal(true); - done(); - }, done); - }); - }); - - it('Add a doc', function (done) { - var db = new PouchDB(dbs.name); - db.post({test: 'somestuff'}, function (err, info) { - should.not.exist(err); - done(); - }); - }); - - it('Add a doc with a promise', function (done) { - var db = new PouchDB(dbs.name); - db.post({test: 'somestuff'}).then(function (info) { - done(); - }, done); - }); - - it('Modify a doc', function (done) { - var db = new PouchDB(dbs.name); - db.post({test: 'somestuff'}, function (err, info) { - db.put({ - _id: info.id, - _rev: info.rev, - another: 'test' - }, function (err, info2) { - should.not.exist(err); - info.rev.should.not.equal(info2.rev); - done(); - }); - }); - }); - - it('Modify a doc with sugar syntax', function (done) { - var db = new PouchDB(dbs.name); - db.post({test: 'somestuff'}, function (err, info) { - db.put({another: 'test'}, info.id, info.rev, function (err, info2) { - info.rev.should.not.equal(info2.rev); - db.put({yet_another: 'test'}, 'yet_another', function (err, info3) { - info3.id.should.equal('yet_another'); - info.rev.should.not.equal(info2.rev); - done(); - }); - }); - }); - }); - - it('Modify a doc with sugar syntax and omit the _id', function (done) { - var db = new PouchDB(dbs.name); - db.post({test: 'somestuff'}, function (err, info) { - db.put({another: 'test', _id: info.id}, info.rev, - function (err, info2) { - info.rev.should.not.equal(info2.rev); - db.put({yet_another: 'test'}, 'yet_another', function (err, info3) { - info3.id.should.equal('yet_another'); - info.rev.should.not.equal(info2.rev); - done(); - }); - }); - }); - }); - - it('Modify a doc with a promise', function (done) { - var db = new PouchDB(dbs.name); - db.post({test: 'promisestuff'}).then(function (info) { - return db.put({ - _id: info.id, - _rev: info.rev, - another: 'test' - }).then(function (info2) { - info.rev.should.not.equal(info2.rev); - }); - }).catch(done).then(function () { - done(); - }); - }); - - it('Read db id', function (done) { - var db = new PouchDB(dbs.name); - db.id(function (err, id) { - id.should.be.a('string'); - done(err); - }); - }); - - it('Read db id with promise', function (done) { - var db = new PouchDB(dbs.name); - db.id().then(function (id) { - id.should.be.a('string'); - done(); - }); - }); - - it('Close db', function (done) { - new PouchDB(dbs.name, function (err, db) { - db.close(done); - }); - }); - - it('Close db with a promise', function (done) { - new PouchDB(dbs.name, function (err, db) { - db.close().then(done, done); - }); - }); - - it('Read db id after closing Close', function (done) { - new PouchDB(dbs.name, function (err, db) { - db.close(function (error) { - db = new PouchDB(dbs.name); - db.id(function (err, id) { - id.should.be.a('string'); - done(); - }); - }); - }); - }); - - it('Modify a doc with incorrect rev', function (done) { - var db = new PouchDB(dbs.name); - db.post({ test: 'somestuff' }, function (err, info) { - var nDoc = { - _id: info.id, - _rev: info.rev + 'broken', - another: 'test' - }; - db.put(nDoc, function (err, info2) { - should.exist(err); - done(); - }); - }); - }); - - it('Remove doc', function (done) { - var db = new PouchDB(dbs.name); - db.post({ test: 'somestuff' }, function (err, info) { - db.remove({ - test: 'somestuff', - _id: info.id, - _rev: info.rev - }, function (doc) { - db.get(info.id, function (err) { - should.exist(err.error); - done(); - }); - }); - }); - }); - - it('Remove doc with a promise', function (done) { - var db = new PouchDB(dbs.name); - db.post({test: 'someotherstuff'}).then(function (info) { - return db.remove({ - test: 'someotherstuff', - _id: info.id, - _rev: info.rev - }).then(function () { - return db.get(info.id).then(function (doc) { - done(true); - }, function (err) { - should.exist(err.error); - done(); - }); - }); - }); - }); - - it('Remove doc with new syntax', function (done) { - var db = new PouchDB(dbs.name); - db.post({ test: 'somestuff' }, function (err, info) { - db.remove(info.id, info.rev, function (err) { - should.not.exist(err); - db.get(info.id, function (err) { - should.exist(err); - done(); - }); - }); - }); - }); - - it('Remove doc with new syntax and a promise', function (done) { - var db = new PouchDB(dbs.name); - var id; - db.post({test: 'someotherstuff'}).then(function (info) { - id = info.id; - return db.remove(info.id, info.rev); - }).then(function () { - return db.get(id); - }).then(function (doc) { - done(true); - }, function (err) { - should.exist(err.error); - done(); - }); - }); - - it('Doc removal leaves only stub', function (done) { - var db = new PouchDB(dbs.name); - db.put({_id: 'foo', value: 'test'}, function (err, res) { - db.get('foo', function (err, doc) { - db.remove(doc, function (err, res) { - db.get('foo', { rev: res.rev }, function (err, doc) { - doc.should.deep.equal({ - _id: res.id, - _rev: res.rev, - _deleted: true - }); - done(); - }); - }); - }); - }); - }); - - it('Remove doc twice with specified id', function () { - var db = new PouchDB(dbs.name); - return db.put({_id: 'specifiedId', test: 'somestuff'}).then(function () { - return db.get('specifiedId'); - }).then(function (doc) { - return db.remove(doc); - }).then(function () { - return db.put({ - _id: 'specifiedId', - test: 'somestuff2' - }); - }).then(function () { - return db.get('specifiedId'); - }).then(function (doc) { - return db.remove(doc); - }); - }); - - it('Remove doc, no callback', function (done) { - var db = new PouchDB(dbs.name); - var changes = db.changes({ - live: true, - include_docs: true, - onChange: function (change) { - if (change.doc._deleted) { - changes.cancel(); - } - }, - complete: function (err, result) { - result.status.should.equal('cancelled'); - done(); - } - }); - db.post({ _id: 'somestuff' }, function (err, res) { - db.remove({ - _id: res.id, - _rev: res.rev - }); - }); - }); - - it('Delete document without id', function (done) { - var db = new PouchDB(dbs.name); - db.remove({test: 'ing'}, function (err) { - should.exist(err); - done(); - }); - }); - - it('Delete document with many args', function () { - var db = new PouchDB(dbs.name); - var doc = {_id: 'foo'}; - return db.put(doc).then(function (info) { - return db.remove(doc._id, info.rev, {}); - }); - }); - - it('Delete document with many args, callback style', function (done) { - var db = new PouchDB(dbs.name); - var doc = {_id: 'foo'}; - db.put(doc, function (err, info) { - should.not.exist(err); - db.remove(doc._id, info.rev, {}, function (err) { - should.not.exist(err); - done(); - }); - }); - }); - - it('Delete doc with id + rev + no opts', function () { - var db = new PouchDB(dbs.name); - var doc = {_id: 'foo'}; - return db.put(doc).then(function (info) { - return db.remove(doc._id, info.rev); - }); - }); - - it('Delete doc with id + rev + no opts, callback style', function (done) { - var db = new PouchDB(dbs.name); - var doc = {_id: 'foo'}; - db.put(doc, function (err, info) { - should.not.exist(err); - db.remove(doc._id, info.rev, function (err) { - should.not.exist(err); - done(); - }); - }); - }); - - it('Delete doc with doc + opts', function () { - var db = new PouchDB(dbs.name); - var doc = {_id: 'foo'}; - return db.put(doc).then(function (info) { - doc._rev = info.rev; - return db.remove(doc, {}); - }); - }); - - it('Delete doc with doc + opts, callback style', function (done) { - var db = new PouchDB(dbs.name); - var doc = {_id: 'foo'}; - db.put(doc, function (err, info) { - should.not.exist(err); - doc._rev = info.rev; - db.remove(doc, {}, function (err) { - should.not.exist(err); - done(); - }); - }); - }); - - it('Delete doc with rev in opts', function () { - var db = new PouchDB(dbs.name); - var doc = {_id: 'foo'}; - return db.put(doc).then(function (info) { - return db.remove(doc, {rev: info.rev}); - }); - }); - - it('Bulk docs', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs({ - docs: [ - { test: 'somestuff' }, - { test: 'another' } - ] - }, function (err, infos) { - infos.length.should.equal(2); - infos[0].ok.should.equal(true); - infos[1].ok.should.equal(true); - done(); - }); - }); - - it('Bulk docs with a promise', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs({ - docs: [ - { test: 'somestuff' }, - { test: 'another' } - ] - }).then(function (infos) { - infos.length.should.equal(2); - infos[0].ok.should.equal(true); - infos[1].ok.should.equal(true); - done(); - }).catch(done); - }); - - it('Basic checks', function (done) { - var db = new PouchDB(dbs.name); - db.info(function (err, info) { - var updateSeq = info.update_seq; - var doc = {_id: '0', a: 1, b: 1}; - info.doc_count.should.equal(0); - db.put(doc, function (err, res) { - res.ok.should.equal(true); - res.should.have.property('id'); - res.should.have.property('rev'); - db.info(function (err, info) { - info.doc_count.should.equal(1); - info.update_seq.should.not.equal(updateSeq); - db.get(doc._id, function (err, doc) { - doc._id.should.equal(res.id); - doc._rev.should.equal(res.rev); - db.get(doc._id, { revs_info: true }, function (err, doc) { - doc._revs_info[0].status.should.equal('available'); - done(); - }); - }); - }); - }); - }); - }); - - it('update with invalid rev', function (done) { - var db = new PouchDB(dbs.name); - db.post({test: 'somestuff'}, function (err, info) { - db.put({ - _id: info.id, - _rev: 'undefined', - another: 'test' - }, function (err, info2) { - should.exist(err); - err.message.should.equal('Invalid rev format'); - done(); - }); - }); - }); - - it('Doc validation', function (done) { - var bad_docs = [ - {'_zing': 4}, - {'_zoom': 'hello'}, - {'zane': 'goldfish', - '_fan': 'something smells delicious'}, - {'_bing': {'wha?': 'soda can'}} - ]; - var db = new PouchDB(dbs.name); - db.bulkDocs({ docs: bad_docs }, function (err, res) { - err.status.should.equal(500); - done(); - }); - }); - - it('Replication fields (#2442)', function (done) { - var doc = { - '_replication_id': 'test', - '_replication_state': 'triggered', - '_replication_state_time': 1, - '_replication_stats': {} - }; - var db = new PouchDB(dbs.name); - db.post(doc, function (err, resp) { - should.not.exist(err); - - db.get(resp.id, function (err, doc2) { - should.not.exist(err); - - doc2._replication_id.should.equal('test'); - doc2._replication_state.should.equal('triggered'); - doc2._replication_state_time.should.equal(1); - doc2._replication_stats.should.eql({}); - - done(); - }); - }); - }); - - it('Testing issue #48', function (done) { - var docs = [ - {'id': '0'}, {'id': '1'}, {'id': '2'}, - {'id': '3'}, {'id': '4'}, {'id': '5'} - ]; - var TO_SEND = 5; - var sent = 0; - var complete = 0; - var timer; - - var db = new PouchDB(dbs.name); - - var bulkCallback = function (err, res) { - should.not.exist(err); - if (++complete === TO_SEND) { - done(); - } - }; - - var save = function () { - if (++sent === TO_SEND) { - clearInterval(timer); - } - db.bulkDocs({docs: docs}, bulkCallback); - }; - - timer = setInterval(save, 10); - }); - - it('Testing valid id', function (done) { - var db = new PouchDB(dbs.name); - db.post({ - '_id': 123, - test: 'somestuff' - }, function (err, info) { - should.exist(err); - done(); - }); - }); - - it('Put doc without _id should fail', function (done) { - var db = new PouchDB(dbs.name); - db.put({test: 'somestuff' }, function (err, info) { - should.exist(err); - done(); - }); - }); - - it('Put doc with bad reserved id should fail', function (done) { - var db = new PouchDB(dbs.name); - db.put({ - _id: '_i_test', - test: 'somestuff' - }, function (err, info) { - should.exist(err); - err.name.should.equal('TypeError'); - err.status.should.equal(400); - done(); - }); - }); - - it('update_seq persists', function (done) { - var db = new PouchDB(dbs.name); - db.post({ test: 'somestuff' }, function (err, info) { - new PouchDB(dbs.name, function (err, db) { - db.info(function (err, info) { - info.update_seq.should.not.equal(0); - info.doc_count.should.equal(1); - done(); - }); - }); - }); - }); - - it('deletions persists', function (done) { - - var db = new PouchDB(dbs.name); - var doc = {_id: 'staticId', contents: 'stuff'}; - - function writeAndDelete(cb) { - db.put(doc, function (err, info) { - db.remove({ - _id: info.id, - _rev: info.rev - }, function (doc) { - cb(); - }); - }); - } - - writeAndDelete(function () { - writeAndDelete(function () { - db.put(doc, function () { - db.get(doc._id, { conflicts: true }, function (err, details) { - details.should.not.have.property('_conflicts'); - done(); - }); - }); - }); - }); - }); - - it('Error when document is not an object', function (done) { - var db = new PouchDB(dbs.name); - var doc1 = [{ _id: 'foo' }, { _id: 'bar' }]; - var doc2 = 'this is not an object'; - var count = 5; - var callback = function (err, resp) { - should.exist(err); - count--; - if (count === 0) { - done(); - } - }; - db.post(doc1, callback); - db.post(doc2, callback); - db.put(doc1, callback); - db.put(doc2, callback); - db.bulkDocs({docs: [doc1, doc2]}, callback); - }); - - it('Test instance update_seq updates correctly', function (done) { - new PouchDB(dbs.name, function (err, db1) { - var db2 = new PouchDB(dbs.name); - db1.post({ a: 'doc' }, function () { - db1.info(function (err, db1Info) { - db2.info(function (err, db2Info) { - db1Info.update_seq.should.not.equal(0); - db2Info.update_seq.should.not.equal(0); - done(); - }); - }); - }); - }); - }); - - it('Error works', function () { - var newError = PouchDB.Errors - .error(PouchDB.Errors.BAD_REQUEST, 'love needs no message'); - newError.status.should.equal(400); - newError.name.should.equal('bad_request'); - newError.message.should.equal('love needs no message'); - }); - - it('Fail to fetch a doc after db was deleted', function (done) { - new PouchDB(dbs.name, function (err, db) { - var db2 = new PouchDB(dbs.name); - var doc = { _id: 'foodoc' }; - var doc2 = { _id: 'foodoc2' }; - db.put(doc, function () { - db2.put(doc2, function () { - db.allDocs(function (err, docs) { - docs.total_rows.should.equal(2); - PouchDB.destroy(dbs.name, function (err) { - should.not.exist(err); - db2 = new PouchDB(dbs.name); - db2.get(doc._id, function (err, doc) { - err.status.should.equal(404); - done(); - }); - }); - }); - }); - }); - }); - }); - - it('Fail to fetch a doc after db was deleted', function (done) { - new PouchDB(dbs.name, function (err, db) { - var db2 = new PouchDB(dbs.name); - var doc = { _id: 'foodoc' }; - var doc2 = { _id: 'foodoc2' }; - db.put(doc, function () { - db2.put(doc2, function () { - db.allDocs(function (err, docs) { - docs.total_rows.should.equal(2); - db.destroy().then(function () { - db2 = new PouchDB(dbs.name); - db2.get(doc._id, function (err, doc) { - should.not.exist(doc); - err.status.should.equal(404); - done(); - }); - }); - }); - }); - }); - }); - }); - - it('Cant add docs with empty ids', function (done) { - var docs = [ - {}, - { _id: null }, - { _id: undefined }, - { _id: '' }, - { _id: {} }, - { _id: '_underscored_id' } - ]; - var num = docs.length; - var db = new PouchDB(dbs.name); - docs.forEach(function (doc) { - db.put(doc, function (err, info) { - should.exist(err); - if (!--num) { - done(); - } - }); - }); - }); - - it('Test doc with percent in ID', function () { - var db = new PouchDB(dbs.name); - var doc = { - foo: 'bar', - _id: 'foo%bar' - }; - return db.put(doc).then(function (res) { - res.id.should.equal('foo%bar'); - return db.get('foo%bar'); - }).then(function (doc) { - doc._id.should.equal('foo%bar'); - var queryFun = { - map: function (doc) { - emit(doc.foo, doc); - } - }; - return db.query(queryFun, { - include_docs: true, - reduce: false - }); - }).then(function (res) { - var x = res.rows[0]; - x.id.should.equal('foo%bar'); - should.exist(x.key); - should.exist(x.value._rev); - should.exist(x.doc._rev); - }); - }); - - it('db.info should give correct name', function (done) { - var db = new PouchDB(dbs.name); - db.info().then(function (info) { - info.db_name.should.equal('testdb'); - done(); - }); - }); - - it('db.info should give auto_compaction = false (#2744)', function (done) { - var db = new PouchDB(dbs.name, { auto_compaction: false}); - db.info().then(function (info) { - info.auto_compaction.should.equal(false); - done(); - }); - }); - - it('db.info should give auto_compaction = true (#2744)', function (done) { - if (dbs.name === 'test.basics.js-local') { - var db = new PouchDB(dbs.name, { auto_compaction: true}); - db.info().then(function (info) { - info.auto_compaction.should.equal(true); - done(); - }); - } else { - done(); - } - }); - - it('db.info should give correct doc_count', function (done) { - new PouchDB(dbs.name).then(function (db) { - db.info().then(function (info) { - info.doc_count.should.equal(0); - return db.bulkDocs({docs : [{_id : '1'}, {_id : '2'}, {_id : '3'}]}); - }).then(function () { - return db.info(); - }).then(function (info) { - info.doc_count.should.equal(3); - return db.get('1'); - }).then(function (doc) { - return db.remove(doc); - }).then(function () { - return db.info(); - }).then(function (info) { - info.doc_count.should.equal(2); - done(); - }, done); - }, done); - }); - - it('putting returns {ok: true}', function () { - // in couch, it's {ok: true} and in cloudant it's {}, - // but the http adapter smooths this out - return new PouchDB(dbs.name).then(function (db) { - return db.put({_id: '_local/foo'}).then(function (info) { - true.should.equal(info.ok, 'putting local returns ok=true'); - return db.put({_id: 'quux'}); - }).then(function (info) { - true.should.equal(info.ok, 'putting returns ok=true'); - return db.bulkDocs([ {_id: '_local/bar'}, {_id: 'baz'} ]); - }).then(function (info) { - info.should.have.length(2, 'correct num bulk docs'); - true.should.equal(info[0].ok, 'bulk docs says ok=true #1'); - true.should.equal(info[1].ok, 'bulk docs says ok=true #2'); - return db.post({}); - }).then(function (info) { - true.should.equal(info.ok, 'posting returns ok=true'); - }); - }); - }); - it('putting is override-able', function (done) { - var db = new PouchDB(dbs.name); - var called = 0; - var plugin = { - initPull: function () { - this.oldPut = this.put; - this.put = function () { - if (typeof arguments[arguments.length - 1] === 'function') { - called++; - } - return this.oldPut.apply(this, arguments); - }; - }, - cleanupPut: function () { - this.put = this.oldPut; - } - }; - PouchDB.plugin(plugin); - db.initPull(); - return db.put({foo: 'bar'}, 'anid').then(function (resp) { - called.should.be.above(0, 'put was called'); - return db.get('anid'); - }).then(function (doc) { - doc.foo.should.equal('bar', 'correct doc'); - }).then(function () { - done(); - }, done); - }); - - it('issue 2779, deleted docs, old revs COUCHDB-292', function (done) { - var db = new PouchDB(dbs.name); - var rev; - - db.put({_id: 'foo'}).then(function (resp) { - rev = resp.rev; - return db.remove('foo', rev); - }).then(function () { - return db.get('foo'); - }).catch(function (err) { - return db.put({_id: 'foo', _rev: rev}); - }).then(function () { - done(new Error('should never have got here')); - }, function (err) { - should.exist(err); - done(); - }); - }); - - it('issue 2779, correct behavior for undeleting', function () { - - if (testUtils.isCouchMaster()) { - return true; - } - - var db = new PouchDB(dbs.name); - var rev; - - function checkNumRevisions(num) { - return db.get('foo', { - open_revs: 'all', - revs: true - }).then(function (fullDocs) { - fullDocs[0].ok._revisions.ids.should.have.length(num); - }); - } - - return db.put({_id: 'foo'}).then(function (resp) { - rev = resp.rev; - return checkNumRevisions(1); - }).then(function () { - return db.remove('foo', rev); - }).then(function () { - return checkNumRevisions(2); - }).then(function () { - return db.allDocs({keys: ['foo']}); - }).then(function (res) { - rev = res.rows[0].value.rev; - return db.put({_id: 'foo', _rev: rev}); - }).then(function () { - return checkNumRevisions(3); - }); - }); - - it('issue 2888, successive deletes and writes', function () { - var db = new PouchDB(dbs.name); - var rev; - - function checkNumRevisions(num) { - return db.get('foo', { - open_revs: 'all', - revs: true - }).then(function (fullDocs) { - fullDocs[0].ok._revisions.ids.should.have.length(num); - }); - } - return db.put({ _id: 'foo' }).then(function (resp) { - rev = resp.rev; - return checkNumRevisions(1); - }).then(function () { - return db.remove('foo', rev); - }).then(function () { - return checkNumRevisions(2); - }).then(function () { - return db.put({ _id: 'foo' }); - }).then(function (res) { - rev = res.rev; - return checkNumRevisions(3); - }).then(function () { - return db.remove('foo', rev); - }).then(function () { - return checkNumRevisions(4); - }); - }); - - if (adapter === 'local') { - // TODO: this test fails in the http adapter in Chrome - it('should allow unicode doc ids', function (done) { - var db = new PouchDB(dbs.name); - var ids = [ - // "PouchDB is awesome" in Japanese, contains 1-3 byte chars - '\u30d1\u30a6\u30c1\u30e5DB\u306f\u6700\u9ad8\u3060', - '\u03B2', // 2-byte utf-8 char: 3b2 - '\uD843\uDF2D', // exotic 4-byte utf-8 char: 20f2d - '\u0000foo\u0000bar\u0001baz\u0002quux', // like mapreduce - '\u0000', - '\u30d1' - ]; - var numDone = 0; - ids.forEach(function (id) { - var doc = {_id : id, foo : 'bar'}; - db.put(doc).then(function (info) { - doc._rev = info.rev; - return db.put(doc); - }).then(function () { - return db.get(id); - }).then(function (resp) { - resp._id.should.equal(id); - if (++numDone === ids.length) { - done(); - } - }, done); - }); - }); - } - }); -});
diff --git a/tests/integration/test.bulk_docs.js b/tests/integration/test.bulk_docs.js deleted file mode 100644 index b0ddb53..0000000 --- a/tests/integration/test.bulk_docs.js +++ /dev/null
@@ -1,767 +0,0 @@ -'use strict'; - -var adapters = ['local', 'http']; - -function makeDocs(start, end, templateDoc) { - var templateDocSrc = templateDoc ? JSON.stringify(templateDoc) : '{}'; - if (end === undefined) { - end = start; - start = 0; - } - var docs = []; - for (var i = start; i < end; i++) { - /*jshint evil:true */ - var newDoc = eval('(' + templateDocSrc + ')'); - newDoc._id = i.toString(); - newDoc.integer = i; - newDoc.string = i.toString(); - docs.push(newDoc); - } - return docs; -} - -adapters.forEach(function (adapter) { - describe('test.bulk_docs.js-' + adapter, function () { - - var dbs = {}; - - beforeEach(function (done) { - dbs.name = testUtils.adapterUrl(adapter, 'testdb'); - testUtils.cleanup([dbs.name], done); - }); - - after(function (done) { - testUtils.cleanup([dbs.name], done); - }); - - - var authors = [ - {name: 'Dale Harvey', commits: 253}, - {name: 'Mikeal Rogers', commits: 42}, - {name: 'Johannes J. Schmidt', commits: 13}, - {name: 'Randall Leeds', commits: 9} - ]; - - it('Testing bulk docs', function (done) { - var db = new PouchDB(dbs.name); - var docs = makeDocs(5); - db.bulkDocs({ docs: docs }, function (err, results) { - results.should.have.length(5, 'results length matches'); - for (var i = 0; i < 5; i++) { - results[i].id.should.equal(docs[i]._id, 'id matches'); - should.exist(results[i].rev, 'rev is set'); - // Update the doc - docs[i]._rev = results[i].rev; - docs[i].string = docs[i].string + '.00'; - } - db.bulkDocs({ docs: docs }, function (err, results) { - results.should.have.length(5, 'results length matches'); - for (i = 0; i < 5; i++) { - results[i].id.should.equal(i.toString(), 'id matches again'); - // set the delete flag to delete the docs in the next step - docs[i]._rev = results[i].rev; - docs[i]._deleted = true; - } - db.put(docs[0], function (err, doc) { - db.bulkDocs({ docs: docs }, function (err, results) { - results[0].name.should.equal( - 'conflict', 'First doc should be in conflict'); - should.not.exist(results[0].rev, 'no rev in conflict'); - for (i = 1; i < 5; i++) { - results[i].id.should.equal(i.toString()); - should.exist(results[i].rev); - } - done(); - }); - }); - }); - }); - }); - - it('No id in bulk docs', function (done) { - var db = new PouchDB(dbs.name); - var newdoc = { - '_id': 'foobar', - 'body': 'baz' - }; - db.put(newdoc, function (err, doc) { - should.exist(doc.ok); - var docs = [ - { - '_id': newdoc._id, - '_rev': newdoc._rev, - 'body': 'blam' - }, - { - '_id': newdoc._id, - '_rev': newdoc._rev, - '_deleted': true - } - ]; - db.bulkDocs({ docs: docs }, function (err, results) { - results[0].should.have.property('name', 'conflict'); - results[1].should.have.property('name', 'conflict'); - done(); - }); - }); - }); - - it('No _rev and new_edits=false', function (done) { - var db = new PouchDB(dbs.name); - var docs = [{ - _id: 'foo', - integer: 1 - }]; - db.bulkDocs({ docs: docs }, { new_edits: false }, function (err, res) { - should.exist(err, 'error reported'); - done(); - }); - }); - - it('Test empty bulkDocs', function () { - var db = new PouchDB(dbs.name); - return db.bulkDocs([]); - }); - - it('Test many bulkDocs', function () { - var db = new PouchDB(dbs.name); - var docs = []; - for (var i = 0; i < 201; i++) { - docs.push({_id: i.toString()}); - } - return db.bulkDocs(docs); - }); - - it('Test errors on invalid doc id', function (done) { - var db = new PouchDB(dbs.name); - var docs = [{ - '_id': '_invalid', - foo: 'bar' - }]; - db.bulkDocs({ docs: docs }, function (err, info) { - err.status.should.equal(400, 'correct error status returned'); - should.not.exist(info, 'info is empty'); - done(); - }); - }); - - it('Test two errors on invalid doc id', function (done) { - var docs = [ - {'_id': '_invalid', foo: 'bar'}, - {'_id': 123, foo: 'bar'} - ]; - - var db = new PouchDB(dbs.name); - db.bulkDocs({ docs: docs }, function (err, info) { - err.status.should.equal(400, 'correct error returned'); - err.message.should.equal(PouchDB.Errors.RESERVED_ID.message, - 'correct error message returned'); - should.not.exist(info, 'info is empty'); - done(); - }); - }); - - it('No docs', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs({ 'doc': [{ 'foo': 'bar' }] }, function (err, result) { - err.status.should.equal(400); - err.message.should.equal('Missing JSON list of \'docs\''); - done(); - }); - }); - - it('Jira 911', function (done) { - var db = new PouchDB(dbs.name); - var docs = [ - {'_id': '0', 'a': 0}, - {'_id': '1', 'a': 1}, - {'_id': '1', 'a': 1}, - {'_id': '3', 'a': 3} - ]; - db.bulkDocs({ docs: docs }, function (err, results) { - results[1].id.should.equal('1', 'check ordering'); - should.not.exist(results[1].name, 'first id succeded'); - results[2].name.should.equal('conflict', 'second conflicted'); - results.should.have.length(4, 'got right amount of results'); - done(); - }); - }); - - it('Test multiple bulkdocs', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs({ docs: authors }, function (err, res) { - db.bulkDocs({ docs: authors }, function (err, res) { - db.allDocs(function (err, result) { - result.total_rows.should.equal(8, 'correct number of results'); - done(); - }); - }); - }); - }); - - it('#2935 new_edits=false correct number', function () { - var docs = [ - { - "_id": "EE35E", - "_rev": "4-70b26", - "_deleted": true, - "_revisions": { - "start": 4, - "ids": ["70b26", "9f454", "914bf", "7fdf8"] - } - }, { - "_id": "EE35E", - "_rev": "3-f6d28", - "_revisions": {"start": 3, "ids": ["f6d28", "914bf", "7fdf8"]} - } - ]; - - var db = new PouchDB(dbs.name); - - return db.bulkDocs({docs: docs, new_edits: false}).then(function (res) { - res.should.deep.equal([]); - return db.allDocs(); - }).then(function (res) { - res.total_rows.should.equal(1); - return db.info(); - }).then(function (info) { - info.doc_count.should.equal(1); - }); - }); - - it('#2935 new_edits=false correct number 2', function () { - var docs = [ - { - "_id": "EE35E", - "_rev": "3-f6d28", - "_revisions": {"start": 3, "ids": ["f6d28", "914bf", "7fdf8"]} - }, { - "_id": "EE35E", - "_rev": "4-70b26", - "_deleted": true, - "_revisions": { - "start": 4, - "ids": ["70b26", "9f454", "914bf", "7fdf8"] - } - } - ]; - - var db = new PouchDB(dbs.name); - - return db.bulkDocs({docs: docs, new_edits: false}).then(function (res) { - res.should.deep.equal([]); - return db.allDocs(); - }).then(function (res) { - res.total_rows.should.equal(1); - return db.info(); - }).then(function (info) { - info.doc_count.should.equal(1); - }); - }); - - it('#2935 new_edits=false with single unauthorized', function (done) { - - testUtils.isCouchDB(function (isCouchDB) { - if (adapter !== 'http' || !isCouchDB) { - return done(); - } - - var ddoc = { - "_id": "_design/validate", - "validate_doc_update": function (newDoc) { - if (newDoc.foo === undefined) { - throw {unauthorized: 'Document must have a foo.'}; - } - }.toString() - }; - - var db = new PouchDB(dbs.name); - - db.put(ddoc).then(function () { - return db.bulkDocs({ - docs: [ - { - '_id': 'doc0', - '_rev': '1-x', - 'foo': 'bar', - '_revisions': { - 'start': 1, - 'ids': ['x'] - } - }, { - '_id': 'doc1', - '_rev': '1-x', - '_revisions': { - 'start': 1, - 'ids': ['x'] - } - }, { - '_id': 'doc2', - '_rev': '1-x', - 'foo': 'bar', - '_revisions': { - 'start': 1, - 'ids': ['x'] - } - } - ] - }, {new_edits: false}); - }).then(function (res) { - res.should.have.length(1); - should.exist(res[0].error); - res[0].id.should.equal('doc1'); - }).then(done); - }); - }); - - it('Bulk with new_edits=false', function (done) { - var db = new PouchDB(dbs.name); - var docs = [{ - '_id': 'foo', - '_rev': '2-x', - '_revisions': { - 'start': 2, - 'ids': ['x', 'a'] - } - }, { - '_id': 'foo', - '_rev': '2-y', - '_revisions': { - 'start': 2, - 'ids': ['y', 'a'] - } - }]; - db.bulkDocs({docs: docs}, {new_edits: false}, function (err, res) { - db.get('foo', {open_revs: 'all'}, function (err, res) { - res.sort(function (a, b) { - return a.ok._rev < b.ok._rev ? -1 : - a.ok._rev > b.ok._rev ? 1 : 0; - }); - res.length.should.equal(2); - res[0].ok._rev.should.equal('2-x', 'doc1 ok'); - res[1].ok._rev.should.equal('2-y', 'doc2 ok'); - done(); - }); - }); - }); - - it('Testing successive new_edits to the same doc', function (done) { - - var db = new PouchDB(dbs.name); - var docs = [{ - '_id': 'foo', - '_rev': '1-x', - '_revisions': { - 'start': 1, - 'ids': ['x'] - } - }]; - - db.bulkDocs({docs: docs, new_edits: false}, function (err, result) { - should.not.exist(err); - db.bulkDocs({docs: docs, new_edits: false}, function (err, result) { - should.not.exist(err); - db.get('foo', function (err, res) { - res._rev.should.equal('1-x'); - done(); - }); - }); - }); - }); - - it('#3062 bulkDocs with staggered seqs', function () { - return new PouchDB(dbs.name).then(function (db) { - var docs = []; - for (var i = 10; i <= 20; i++) { - docs.push({ _id: 'doc-' + i}); - } - return db.bulkDocs({docs: docs}).then(function (infos) { - docs.forEach(function (doc, i) { - doc._rev = infos[i].rev; - }); - var docsToUpdate = docs.filter(function (doc, i) { - return i % 2 === 1; - }); - docsToUpdate.reverse(); - return db.bulkDocs({docs: docsToUpdate}); - }).then(function (infos) { - infos.map(function (x) { - return {id: x.id, error: !!x.error, rev: (typeof x.rev)}; - }).should.deep.equal([ - { error: false, id: 'doc-19', rev: 'string'}, - { error: false, id: 'doc-17', rev: 'string'}, - { error: false, id: 'doc-15', rev: 'string'}, - { error: false, id: 'doc-13', rev: 'string'}, - { error: false, id: 'doc-11', rev: 'string'} - ]); - }); - }); - }); - - it('Testing successive new_edits to the same doc, different content', - function (done) { - - var db = new PouchDB(dbs.name); - var docsA = [{ - '_id': 'foo', - '_rev': '1-x', - 'bar' : 'baz', - '_revisions': { - 'start': 1, - 'ids': ['x'] - } - }, { - '_id' : 'fee', - '_rev': '1-x', - '_revisions': { - 'start': 1, - 'ids': ['x'] - } - }]; - - var docsB = [{ - '_id': 'foo', - '_rev': '1-x', - 'bar' : 'zam', // this update should be rejected - '_revisions': { - 'start': 1, - 'ids': ['x'] - } - }, { - '_id' : 'faa', - '_rev': '1-x', - '_revisions': { - 'start': 1, - 'ids': ['x'] - } - }]; - - db.bulkDocs({docs: docsA, new_edits: false}, function (err, result) { - should.not.exist(err); - db.changes({complete: function (err, result) { - var ids = result.results.map(function (row) { - return row.id; - }); - ids.should.include("foo"); - ids.should.include("fee"); - ids.should.not.include("faa"); - result.last_seq.should.equal(2); - db.bulkDocs({docs: docsB, new_edits: false}, function (err, result) { - should.not.exist(err); - db.changes({ - since : 2, - complete: function (err, result) { - var ids = result.results.map(function (row) { - return row.id; - }); - ids.should.not.include("foo"); - ids.should.not.include("fee"); - ids.should.include("faa"); - result.last_seq.should.equal(3); - db.get('foo', function (err, res) { - res._rev.should.equal('1-x'); - res.bar.should.equal("baz"); - db.info(function (err, info) { - info.doc_count.should.equal(3); - info.update_seq.should.equal(3); - done(); - }); - }); - } - }); - }); - }}); - }); - }); - - it('Testing successive new_edits to two doc', function () { - - var db = new PouchDB(dbs.name); - var doc1 = { - '_id': 'foo', - '_rev': '1-x', - '_revisions': { - 'start': 1, - 'ids': ['x'] - } - }; - var doc2 = { - '_id': 'bar', - '_rev': '1-x', - '_revisions': { - 'start': 1, - 'ids': ['x'] - } - }; - - return db.put(doc1, {new_edits: false}).then(function () { - return db.put(doc2, {new_edits: false}); - }).then(function () { - return db.put(doc1, {new_edits: false}); - }).then(function () { - return db.get('foo'); - }).then(function () { - return db.get('bar'); - }); - }); - - it('Deletion with new_edits=false', function () { - - var db = new PouchDB(dbs.name); - var doc1 = { - '_id': 'foo', - '_rev': '1-x', - '_revisions': { - 'start': 1, - 'ids': ['x'] - } - }; - var doc2 = { - '_deleted': true, - '_id': 'foo', - '_rev': '2-y', - '_revisions': { - 'start': 2, - 'ids': ['y', 'x'] - } - }; - - return db.put(doc1, {new_edits: false}).then(function () { - return db.put(doc2, {new_edits: false}); - }).then(function () { - return db.allDocs({keys: ['foo']}); - }).then(function (res) { - res.rows[0].value.rev.should.equal('2-y'); - res.rows[0].value.deleted.should.equal(true); - }); - }); - - it('Deletion with new_edits=false, no history', function () { - - var db = new PouchDB(dbs.name); - var doc1 = { - '_id': 'foo', - '_rev': '1-x', - '_revisions': { - 'start': 1, - 'ids': ['x'] - } - }; - var doc2 = { - '_deleted': true, - '_id': 'foo', - '_rev': '2-y' - }; - - return db.put(doc1, {new_edits: false}).then(function () { - return db.put(doc2, {new_edits: false}); - }).then(function () { - return db.allDocs({keys: ['foo']}); - }).then(function (res) { - res.rows[0].value.rev.should.equal('1-x'); - should.equal(!!res.rows[0].value.deleted, false); - }); - }); - - it('Modification with new_edits=false, no history', function () { - - var db = new PouchDB(dbs.name); - var doc1 = { - '_id': 'foo', - '_rev': '1-x', - '_revisions': { - 'start': 1, - 'ids': ['x'] - } - }; - var doc2 = { - '_id': 'foo', - '_rev': '2-y' - }; - - return db.put(doc1, {new_edits: false}).then(function () { - return db.put(doc2, {new_edits: false}); - }).then(function () { - return db.allDocs({keys: ['foo']}); - }).then(function (res) { - res.rows[0].value.rev.should.equal('2-y'); - }); - }); - - it('Deletion with new_edits=false, no history, no revisions', function () { - - var db = new PouchDB(dbs.name); - var doc = { - '_deleted': true, - '_id': 'foo', - '_rev': '2-y' - }; - - return db.put(doc, {new_edits: false}).then(function () { - return db.allDocs({keys: ['foo']}); - }).then(function (res) { - res.rows[0].value.rev.should.equal('2-y'); - res.rows[0].value.deleted.should.equal(true); - }); - }); - - it('Testing new_edits=false in req body', function (done) { - var db = new PouchDB(dbs.name); - var docs = [{ - '_id': 'foo', - '_rev': '2-x', - '_revisions': { - 'start': 2, - 'ids': ['x', 'a'] - } - }, { - '_id': 'foo', - '_rev': '2-y', - '_revisions': { - 'start': 2, - 'ids': ['y', 'a'] - } - }]; - db.bulkDocs({docs: docs, new_edits: false}, function (err, res) { - db.get('foo', {open_revs: 'all'}, function (err, res) { - res.sort(function (a, b) { - return a.ok._rev < b.ok._rev ? -1 : - a.ok._rev > b.ok._rev ? 1 : 0; - }); - res.length.should.equal(2); - res[0].ok._rev.should.equal('2-x', 'doc1 ok'); - res[1].ok._rev.should.equal('2-y', 'doc2 ok'); - done(); - }); - }); - }); - - it('656 regression in handling deleted docs', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs({ - docs: [{ - _id: 'foo', - _rev: '1-a', - _deleted: true - }] - }, { new_edits: false }, function (err, res) { - db.get('foo', function (err, res) { - should.exist(err, 'deleted'); - done(); - }); - }); - }); - - it('Test quotes in doc ids', function (done) { - var db = new PouchDB(dbs.name); - var docs = [{ _id: '\'your_sql_injection_script_here\'' }]; - db.bulkDocs({docs: docs}, function (err, res) { - should.not.exist(err, 'got error: ' + JSON.stringify(err)); - db.get('foo', function (err, res) { - should.exist(err, 'deleted'); - done(); - }); - }); - }); - - it('Bulk docs empty list', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs({ docs: [] }, function (err, res) { - done(err); - }); - }); - - it('handles simultaneous writes', function (done) { - var db1 = new PouchDB(dbs.name); - var db2 = new PouchDB(dbs.name); - var id = 'fooId'; - var errorNames = []; - var ids = []; - var numDone = 0; - function callback(err, res) { - should.not.exist(err); - if (res[0].error) { - errorNames.push(res[0].name); - } else { - ids.push(res[0].id); - } - if (++numDone === 2) { - errorNames.should.deep.equal(['conflict']); - ids.should.deep.equal([id]); - done(); - } - } - db1.bulkDocs({docs : [{_id : id}]}, callback); - db2.bulkDocs({docs : [{_id : id}]}, callback); - }); - - it('bulk docs input by array', function (done) { - var db = new PouchDB(dbs.name); - var docs = makeDocs(5); - db.bulkDocs(docs, function (err, results) { - results.should.have.length(5, 'results length matches'); - for (var i = 0; i < 5; i++) { - results[i].id.should.equal(docs[i]._id, 'id matches'); - should.exist(results[i].rev, 'rev is set'); - // Update the doc - docs[i]._rev = results[i].rev; - docs[i].string = docs[i].string + '.00'; - } - db.bulkDocs(docs, function (err, results) { - results.should.have.length(5, 'results length matches'); - for (i = 0; i < 5; i++) { - results[i].id.should.equal(i.toString(), 'id matches again'); - // set the delete flag to delete the docs in the next step - docs[i]._rev = results[i].rev; - docs[i]._deleted = true; - } - db.put(docs[0], function (err, doc) { - db.bulkDocs(docs, function (err, results) { - results[0].name.should.equal( - 'conflict', 'First doc should be in conflict'); - should.not.exist(results[0].rev, 'no rev in conflict'); - for (i = 1; i < 5; i++) { - results[i].id.should.equal(i.toString()); - should.exist(results[i].rev); - } - done(); - }); - }); - }); - }); - }); - - it('Bulk empty list', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs([], function (err, res) { - done(err); - }); - }); - - it('Bulk docs not an array', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs({ docs: 'foo' }, function (err, res) { - should.exist(err, 'error reported'); - err.status.should.equal(400); - err.message.should.equal('Missing JSON list of \'docs\''); - done(); - }); - }); - - it('Bulk docs not an object', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs({ docs: ['foo'] }, function (err, res) { - should.exist(err, 'error reported'); - err.status.should.equal(400); - err.message.should.equal('Document must be a JSON object'); - }); - db.bulkDocs({ docs: [[]] }, function (err, res) { - should.exist(err, 'error reported'); - err.status.should.equal(400); - err.message.should.equal('Document must be a JSON object'); - done(); - }); - }); - - }); -});
diff --git a/tests/integration/test.changes.js b/tests/integration/test.changes.js deleted file mode 100644 index 22e6a2e..0000000 --- a/tests/integration/test.changes.js +++ /dev/null
@@ -1,1746 +0,0 @@ - -'use strict'; - -var adapters = ['http', 'local']; - -adapters.forEach(function (adapter) { - - describe('test.changes.js-' + adapter, function () { - - var dbs = {}; - - beforeEach(function (done) { - dbs.name = testUtils.adapterUrl(adapter, 'testdb'); - dbs.remote = testUtils.adapterUrl(adapter, 'test_repl_remote'); - testUtils.cleanup([dbs.name, dbs.remote], done); - }); - - after(function (done) { - testUtils.cleanup([dbs.name, dbs.remote], done); - }); - - it('All changes', function (done) { - var db = new PouchDB(dbs.name); - db.post({ test: 'somestuff' }, function (err, info) { - var promise = db.changes({ - onChange: function (change) { - change.should.not.have.property('doc'); - change.should.have.property('seq'); - done(); - } - }); - should.exist(promise); - promise.cancel.should.be.a('function'); - }); - }); - - it('Promise resolved when changes cancelled', function (done) { - var docs = [ - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - {_id: '2', integer: 2}, - {_id: '3', integer: 3}, - {_id: '4', integer: 4}, - {_id: '5', integer: 5}, - {_id: '6', integer: 6}, - {_id: '7', integer: 7}, - {_id: '8', integer: 9}, - {_id: '9', integer: 9}, - {_id: '10', integer: 10}, - ]; - var db = new PouchDB(dbs.name); - db.bulkDocs({ docs: docs }, function (err, info) { - var changeCount = 0; - var promise = db.changes({ - onChange: function (change) { - changeCount++; - if (changeCount === 5) { - promise.cancel(); - } - } - }); - should.exist(promise); - should.exist(promise.then); - promise.then.should.be.a('function'); - promise.then( - function (result) { - changeCount.should.equal(5, 'changeCount'); - should.exist(result); - result.should.deep.equal({status: 'cancelled'}); - done(); - }, function (err) { - changeCount.should.equal(5, 'changeCount'); - should.exist(err); - done(); - }); - }); - }); - - it('Changes Since Old Style', function (done) { - var docs = [ - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - {_id: '2', integer: 2}, - {_id: '3', integer: 3}, - {_id: '4', integer: 4}, - {_id: '5', integer: 5}, - {_id: '6', integer: 6}, - {_id: '7', integer: 7}, - {_id: '8', integer: 9}, - {_id: '9', integer: 9}, - {_id: '10', integer: 10}, - {_id: '11', integer: 11}, - {_id: '12', integer: 12}, - {_id: '13', integer: 13} - ]; - var db = new PouchDB(dbs.name); - db.bulkDocs({ docs: docs }, function (err, info) { - var promise = db.changes({ - since: 12, - complete: function (err, results) { - results.results.length.should.equal(2); - done(); - } - }); - should.exist(promise); - promise.cancel.should.be.a('function'); - }); - }); - - it('Changes Since New Style', function (done) { - var docs = [ - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - {_id: '2', integer: 2}, - {_id: '3', integer: 3}, - {_id: '4', integer: 4}, - {_id: '5', integer: 5}, - {_id: '6', integer: 6}, - {_id: '7', integer: 7}, - {_id: '8', integer: 9}, - {_id: '9', integer: 9}, - {_id: '10', integer: 10}, - {_id: '11', integer: 11}, - {_id: '12', integer: 12}, - {_id: '13', integer: 13} - ]; - var db = new PouchDB(dbs.name); - db.bulkDocs({ docs: docs }, function (err, info) { - var promise = db.changes({ - since: 12 - }).on('complete', function (results) { - results.results.length.should.equal(2); - done(); - }); - should.exist(promise); - promise.cancel.should.be.a('function'); - }); - }); - - it('Changes Since and limit Old Style limit 1', function (done) { - var docs = [ - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - {_id: '2', integer: 2}, - {_id: '3', integer: 3}, - ]; - var db = new PouchDB(dbs.name); - db.bulkDocs({ docs: docs }, function (err, info) { - db.changes({ - since: 2, - limit: 1, - complete: function (err, results) { - results.results.length.should.equal(1); - done(); - } - }); - }); - }); - - it('Changes Since and limit New Style limit 1', function (done) { - var docs = [ - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - {_id: '2', integer: 2}, - {_id: '3', integer: 3}, - ]; - var db = new PouchDB(dbs.name); - db.bulkDocs({ docs: docs }, function (err, info) { - db.changes({ - since: 2, - limit: 1 - }).on('complete', function (results) { - results.results.length.should.equal(1); - done(); - }); - }); - }); - - it('Changes Since and limit Old Style limit 0', function (done) { - var docs = [ - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - {_id: '2', integer: 2}, - {_id: '3', integer: 3}, - ]; - var db = new PouchDB(dbs.name); - db.bulkDocs({ docs: docs }, function (err, info) { - db.changes({ - since: 2, - limit: 0, - complete: function (err, results) { - results.results.length.should.equal(1); - done(); - } - }); - }); - }); - - it('Changes Since and limit New Style limit 0', function (done) { - var docs = [ - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - {_id: '2', integer: 2}, - {_id: '3', integer: 3}, - ]; - var db = new PouchDB(dbs.name); - db.bulkDocs({ docs: docs }, function (err, info) { - db.changes({ - since: 2, - limit: 0 - }).on('complete', function (results) { - results.results.length.should.equal(1); - done(); - }); - }); - }); - - it('Changes limit Old Style', function (done) { - var docs1 = [ - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - {_id: '2', integer: 2}, - {_id: '3', integer: 3}, - ]; - var docs2 = [ - {_id: '2', integer: 11}, - {_id: '3', integer: 12}, - ]; - var db = new PouchDB(dbs.name); - // we use writeDocs since bulkDocs looks to have undefined - // order of doing insertions - testUtils.writeDocs(db, docs1, function (err, info) { - docs2[0]._rev = info[2].rev; - docs2[1]._rev = info[3].rev; - db.put(docs2[0], function (err, info) { - db.put(docs2[1], function (err, info) { - db.changes({ - limit: 2, - since: 2, - include_docs: true, - complete: function (err, results) { - results.last_seq.should.equal(6); - results = results.results; - results.length.should.equal(2); - results[0].id.should.equal('2'); - results[0].seq.should.equal(5); - results[0].doc.integer.should.equal(11); - results[1].id.should.equal('3'); - results[1].seq.should.equal(6); - results[1].doc.integer.should.equal(12); - done(); - } - }); - }); - }); - }); - }); - - it('Changes limit New Style', function (done) { - var docs1 = [ - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - {_id: '2', integer: 2}, - {_id: '3', integer: 3}, - ]; - var docs2 = [ - {_id: '2', integer: 11}, - {_id: '3', integer: 12}, - ]; - var db = new PouchDB(dbs.name); - // we use writeDocs since bulkDocs looks to have undefined - // order of doing insertions - testUtils.writeDocs(db, docs1, function (err, info) { - docs2[0]._rev = info[2].rev; - docs2[1]._rev = info[3].rev; - db.put(docs2[0], function (err, info) { - db.put(docs2[1], function (err, info) { - db.changes({ - limit: 2, - since: 2, - include_docs: true - }).on('complete', function (results) { - results.last_seq.should.equal(6); - results = results.results; - results.length.should.equal(2); - results[0].id.should.equal('2'); - results[0].seq.should.equal(5); - results[0].doc.integer.should.equal(11); - results[1].id.should.equal('3'); - results[1].seq.should.equal(6); - results[1].doc.integer.should.equal(12); - done(); - }); - }); - }); - }); - }); - - it('Changes with filter not present in ddoc', function (done) { - this.timeout(15000); - var docs = [ - {_id: '1', integer: 1}, - { _id: '_design/foo', - integer: 4, - filters: { even: 'function (doc) { return doc.integer % 2 === 1; }' } - } - ]; - var db = new PouchDB(dbs.name); - testUtils.writeDocs(db, docs, function (err, info) { - db.changes({ - filter: 'foo/odd', - limit: 2, - include_docs: true, - complete: function (err, results) { - err.status.should.equal(404); - err.message.should.equal('missing json key: odd'); - should.not.exist(results); - done(); - } - }); - }); - }); - - it('Changes with `filters` key not present in ddoc', function (done) { - var docs = [ - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - { - _id: '_design/foo', - integer: 4, - views: { - even: { - map: 'function (doc) { if (doc.integer % 2 === 1)' + - ' { emit(doc._id, null) }; }' - } - } - } - ]; - var db = new PouchDB(dbs.name); - testUtils.writeDocs(db, docs, function (err, info) { - db.changes({ - filter: 'foo/even', - limit: 2, - include_docs: true, - complete: function (err, results) { - err.status.should.equal(404); - err.message.should.equal('missing json key: filters'); - should.not.exist(results); - done(); - } - }); - }); - }); - - it('Changes limit and filter', function (done) { - var docs = [ - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - {_id: '2', integer: 2}, - {_id: '3', integer: 3}, - {_id: '4', integer: 4}, - {_id: '5', integer: 5}, - { - _id: '_design/foo', - integer: 4, - filters: { even: 'function (doc) { return doc.integer % 2 === 1; }' } - } - ]; - var db = new PouchDB(dbs.name); - testUtils.writeDocs(db, docs, function (err, info) { - var promise = db.changes({ - filter: 'foo/even', - limit: 2, - since: 2, - include_docs: true, - complete: function (err, results) { - results.results.length.should.equal(2); - results.results[0].id.should.equal('3'); - results.results[0].seq.should.equal(4); - results.results[0].doc.integer.should.equal(3); - results.results[1].id.should.equal('5'); - results.results[1].seq.should.equal(6); - results.results[1].doc.integer.should.equal(5); - done(); - } - }); - should.exist(promise); - promise.cancel.should.be.a('function'); - }); - }); - - it('Changes with filter from nonexistent ddoc', function (done) { - var docs = [ - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - ]; - var db = new PouchDB(dbs.name); - testUtils.writeDocs(db, docs, function (err, info) { - db.changes({ - filter: 'foobar/odd', - complete: function (err, results) { - err.status.should.equal(404); - err.message.should.equal('missing'); - should.not.exist(results); - done(); - } - }); - }); - }); - - it('Changes with view not present in ddoc', function (done) { - var docs = [ - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - { - _id: '_design/foo', - integer: 4, - views: - { even: - { map: 'function (doc) { if (doc.integer % 2 === 1) { ' + - 'emit(doc._id, null) }; }' } } - } - ]; - var db = new PouchDB(dbs.name); - testUtils.writeDocs(db, docs, function (err, info) { - db.changes({ - filter: '_view', - view: 'foo/odd', - complete: function (err, results) { - err.status.should.equal(404); - err.message.should.equal('missing json key: odd'); - should.not.exist(results); - done(); - } - }); - }); - }); - - it('Changes with `views` key not present in ddoc', function (done) { - var docs = [ - {_id: '1', integer: 1}, - { - _id: '_design/foo', - integer: 4, - filters: { even: 'function (doc) { return doc.integer % 2 === 1; }' } - } - ]; - var db = new PouchDB(dbs.name); - testUtils.writeDocs(db, docs, function (err, info) { - db.changes({ - filter: '_view', - view: 'foo/even', - complete: function (err, results) { - err.status.should.equal(404); - err.message.should.equal('missing json key: views'); - should.not.exist(results); - done(); - } - }); - }); - }); - - it('Changes with missing param `view` in request', function (done) { - var docs = [ - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - { - _id: '_design/foo', - integer: 4, - views: { even: { map: 'function (doc) { if (doc.integer % 2 === 1) ' + - '{ emit(doc._id, null) }; }' } } - } - ]; - var db = new PouchDB(dbs.name); - testUtils.writeDocs(db, docs, function (err, info) { - db.changes({ - filter: '_view', - complete: function (err, results) { - err.status.should.equal(400); - err.message.should - .equal('`view` filter parameter is not provided.'); - should.not.exist(results); - done(); - } - }); - }); - }); - - it('Changes limit and view instead of filter', function (done) { - var docs = [ - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - {_id: '2', integer: 2}, - {_id: '3', integer: 3}, - {_id: '4', integer: 4}, - {_id: '5', integer: 5}, - { - _id: '_design/foo', - integer: 4, - views: { even: { map: 'function (doc) { if (doc.integer % 2 === 1) ' + - '{ emit(doc._id, null) }; }' } } - } - ]; - var db = new PouchDB(dbs.name); - testUtils.writeDocs(db, docs, function (err, info) { - db.changes({ - filter: '_view', - view: 'foo/even', - limit: 2, - since: 2, - include_docs: true, - complete: function (err, results) { - results.results.length.should.equal(2); - results.results[0].id.should.equal('3'); - results.results[0].seq.should.equal(4); - results.results[0].doc.integer.should.equal(3); - results.results[1].id.should.equal('5'); - results.results[1].seq.should.equal(6); - results.results[1].doc.integer.should.equal(5); - done(); - } - }); - }); - }); - - - it('Changes last_seq', function (done) { - var docs = [ - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - {_id: '2', integer: 2}, - {_id: '3', integer: 3}, - { - _id: '_design/foo', - integer: 4, - filters: { even: 'function (doc) { return doc.integer % 2 === 1; }' } - } - ]; - var db = new PouchDB(dbs.name); - db.changes({ - complete: function (err, results) { - results.last_seq.should.equal(0); - db.bulkDocs({ docs: docs }, function (err, info) { - db.changes({ - complete: function (err, results) { - results.last_seq.should.equal(5); - db.changes({ - filter: 'foo/even', - complete: function (err, results) { - results.last_seq.should.equal(5); - results.results.length.should.equal(2); - done(); - } - }); - } - }); - }); - } - }); - }); - - it('Changes last_seq with view instead of filter', function (done) { - var docs = [ - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - {_id: '2', integer: 2}, - {_id: '3', integer: 3}, - { - _id: '_design/foo', - integer: 4, - views: - { even: - { map: 'function (doc) { if (doc.integer % 2 === 1) { ' + - 'emit(doc._id, null) }; }' } } - } - ]; - var db = new PouchDB(dbs.name); - db.changes({ - complete: function (err, results) { - results.last_seq.should.equal(0); - db.bulkDocs({ docs: docs }, function (err, info) { - db.changes({ - complete: function (err, results) { - results.last_seq.should.equal(5); - db.changes({ - filter: '_view', - view: 'foo/even', - complete: function (err, results) { - results.last_seq.should.equal(5); - results.results.length.should.equal(2); - done(); - } - }); - } - }); - }); - } - }); - }); - - it('Changes with style = all_docs', function (done) { - var simpleTree = [ - [{_id: 'foo', _rev: '1-a', value: 'foo a'}, - {_id: 'foo', _rev: '2-b', value: 'foo b'}, - {_id: 'foo', _rev: '3-c', value: 'foo c'}], - [{_id: 'foo', _rev: '1-a', value: 'foo a'}, - {_id: 'foo', _rev: '2-d', value: 'foo d'}, - {_id: 'foo', _rev: '3-e', value: 'foo e'}, - {_id: 'foo', _rev: '4-f', value: 'foo f'}], - [{_id: 'foo', _rev: '1-a', value: 'foo a'}, - {_id: 'foo', _rev: '2-g', value: 'foo g', _deleted: true}] - ]; - var db = new PouchDB(dbs.name); - testUtils.putTree(db, simpleTree, function () { - db.changes({ - complete: function (err, res) { - res.results[0].changes.length.should.equal(1); - res.results[0].changes[0].rev.should.equal('4-f'); - db.changes({ - style: 'all_docs', - complete: function (err, res) { - res.results[0].changes.length.should.equal(3); - var changes = res.results[0].changes; - changes.sort(function (a, b) { - return a.rev < b.rev; - }); - changes[0].rev.should.equal('4-f'); - changes[1].rev.should.equal('3-c'); - changes[2].rev.should.equal('2-g'); - done(); - } - }); - } - }); - }); - }); - - it('Changes with style = all_docs and a callback for complete', - function (done) { - var simpleTree = [ - [{_id: 'foo', _rev: '1-a', value: 'foo a'}, - {_id: 'foo', _rev: '2-b', value: 'foo b'}, - {_id: 'foo', _rev: '3-c', value: 'foo c'}], - [{_id: 'foo', _rev: '1-a', value: 'foo a'}, - {_id: 'foo', _rev: '2-d', value: 'foo d'}, - {_id: 'foo', _rev: '3-e', value: 'foo e'}, - {_id: 'foo', _rev: '4-f', value: 'foo f'}], - [{_id: 'foo', _rev: '1-a', value: 'foo a'}, - {_id: 'foo', _rev: '2-g', value: 'foo g', _deleted: true}] - ]; - var db = new PouchDB(dbs.name); - testUtils.putTree(db, simpleTree, function () { - db.changes(function (err, res) { - res.results[0].changes.length.should.equal(1); - res.results[0].changes[0].rev.should.equal('4-f'); - db.changes({ - style: 'all_docs', - complete: function () { - done(new Error('this should never be called')); - } - }, function (err, res) { - res.results[0].changes.length.should.equal(3); - var changes = res.results[0].changes; - changes.sort(function (a, b) { - return a.rev < b.rev; - }); - changes[0].rev.should.equal('4-f'); - changes[1].rev.should.equal('3-c'); - changes[2].rev.should.equal('2-g'); - done(); - }); - }); - }); - }); - - it('Changes limit = 0', function (done) { - var docs = [ - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - {_id: '2', integer: 2}, - {_id: '3', integer: 3}, - ]; - var db = new PouchDB(dbs.name); - db.bulkDocs({ docs: docs }, function (err, info) { - db.changes({ - limit: 0, - complete: function (err, results) { - results.results.length.should.equal(1); - done(); - } - }); - }); - }); - - // Note for the following test that CouchDB's implementation of /_changes - // with `descending=true` ignores any `since` parameter. - it('Descending changes', function (done) { - var db = new PouchDB(dbs.name); - db.post({_id: '0', test: 'ing'}, function (err, res) { - db.post({_id: '1', test: 'ing'}, function (err, res) { - db.post({_id: '2', test: 'ing'}, function (err, res) { - db.changes({ - descending: true, - since: 1, - complete: function (err, results) { - results.results.length.should.equal(3); - var ids = ['2', '1', '0']; - results.results.forEach(function (row, i) { - row.id.should.equal(ids[i]); - }); - done(); - } - }); - }); - }); - }); - }); - - it('Changes doc Old Style', function (done) { - var db = new PouchDB(dbs.name); - db.post({ test: 'somestuff' }, function (err, info) { - db.changes({ - include_docs: true, - onChange: function (change) { - change.doc._id.should.equal(change.id); - change.doc._rev.should - .equal(change.changes[change.changes.length - 1].rev); - done(); - } - }); - }); - }); - - it('Changes doc New Style', function (done) { - var db = new PouchDB(dbs.name); - db.post({ test: 'somestuff' }, function (err, info) { - db.changes({ - include_docs: true - }).on('change', function (change) { - change.doc._id.should.equal(change.id); - change.doc._rev.should - .equal(change.changes[change.changes.length - 1].rev); - done(); - }); - }); - }); - - // Note for the following test that CouchDB's implementation of /_changes - // with `descending=true` ignores any `since` parameter. - it('Descending many changes Old Style', function (done) { - var db = new PouchDB(dbs.name); - var docs = []; - var num = 100; - for (var i = 0; i < num; i++) { - docs.push({ - _id: 'doc_' + i, - foo: 'bar_' + i - }); - } - var changes = 0; - db.bulkDocs({ docs: docs }, function (err, info) { - if (err) { - return done(err); - } - db.changes({ - descending: true, - onChange: function (change) { - changes++; - }, - complete: function (err, results) { - if (err) { - return done(err); - } - changes.should.equal(num, 'correct number of changes'); - done(); - } - }); - }); - }); - - it('Descending many changes New Style', function (done) { - var db = new PouchDB(dbs.name); - var docs = []; - var num = 100; - for (var i = 0; i < num; i++) { - docs.push({ - _id: 'doc_' + i, - foo: 'bar_' + i - }); - } - var changes = 0; - db.bulkDocs({ docs: docs }, function (err, info) { - if (err) { - return done(err); - } - db.changes({ - descending: true - }).on('change', function (change) { - changes++; - }).on('complete', function (results) { - changes.should.equal(num, 'correct number of changes'); - done(); - }).on('error', function (err) { - done(err); - }); - }); - }); - - it('live-changes Old Style', function (done) { - var db = new PouchDB(dbs.name); - var count = 0; - var changes = db.changes({ - live: true, - complete: function () { - count.should.equal(1); - done(); - }, - onChange: function (change) { - count += 1; - change.should.not.have.property('doc'); - count.should.equal(1); - changes.cancel(); - }, - }); - db.post({ test: 'adoc' }); - }); - - it('live-changes New Style', function (done) { - var db = new PouchDB(dbs.name); - var count = 0; - var changes = db.changes({ - live: true - }).on('complete', function () { - count.should.equal(1); - done(); - }).on('change', function (change) { - count += 1; - change.should.not.have.property('doc'); - count.should.equal(1); - changes.cancel(); - }); - db.post({ test: 'adoc' }); - }); - - it('Multiple watchers Old Style', function (done) { - var db = new PouchDB(dbs.name); - var count = 0; - var changes1Complete = false; - var changes2Complete = false; - function checkCount() { - if (changes1Complete && changes2Complete) { - count.should.equal(2); - done(); - } - } - var changes1 = db.changes({ - complete: function () { - changes1Complete = true; - checkCount(); - }, - onChange: function (change) { - count += 1; - changes1.cancel(); - changes1 = null; - }, - live: true - }); - var changes2 = db.changes({ - complete: function () { - changes2Complete = true; - checkCount(); - }, - onChange: function (change) { - count += 1; - changes2.cancel(); - changes2 = null; - }, - live: true - }); - db.post({test: 'adoc'}); - }); - - it('Multiple watchers New Style', function (done) { - var db = new PouchDB(dbs.name); - var count = 0; - var changes1Complete = false; - var changes2Complete = false; - function checkCount() { - if (changes1Complete && changes2Complete) { - count.should.equal(2); - done(); - } - } - var changes1 = db.changes({ - live: true - }).on('complete', function () { - changes1Complete = true; - checkCount(); - }).on('change', function (change) { - count += 1; - changes1.cancel(); - changes1 = null; - }); - var changes2 = db.changes({ - live: true - }).on('complete', function () { - changes2Complete = true; - checkCount(); - }).on('change', function (change) { - count += 1; - changes2.cancel(); - changes2 = null; - }); - db.post({test: 'adoc'}); - }); - - it('Continuous changes doc', function (done) { - var db = new PouchDB(dbs.name); - var changes = db.changes({ - complete: function (err, result) { - result.status.should.equal('cancelled'); - done(); - }, - onChange: function (change) { - change.should.have.property('doc'); - change.doc.should.have.property('_rev'); - changes.cancel(); - }, - live: true, - include_docs: true - }); - db.post({ test: 'adoc' }); - }); - - it('Cancel changes Old Style', function (done) { - var db = new PouchDB(dbs.name); - var count = 0; - var interval; - var docPosted = false; - - // We want to wait for a period of time after the final - // document was posted to ensure we didnt see another - // change - function waitForDocPosted() { - if (!docPosted) { - return; - } - clearInterval(interval); - setTimeout(function () { - count.should.equal(1); - done(); - }, 200); - } - - var changes = db.changes({ - complete: function (err, result) { - result.status.should.equal('cancelled'); - // This setTimeout ensures that once we cancel a change we dont - // recieve subsequent callbacks, so it is needed - interval = setInterval(waitForDocPosted, 100); - }, - onChange: function (change) { - count += 1; - if (count === 1) { - changes.cancel(); - db.post({ test: 'another doc' }, function (err, res) { - if (err) { - return done(err); - } - docPosted = true; - }); - } - }, - live: true - }); - db.post({ test: 'adoc' }); - }); - - it('Cancel changes New Style', function (done) { - var db = new PouchDB(dbs.name); - var count = 0; - var interval; - var docPosted = false; - - // We want to wait for a period of time after the final - // document was posted to ensure we didnt see another - // change - function waitForDocPosted() { - if (!docPosted) { - return; - } - clearInterval(interval); - setTimeout(function () { - count.should.equal(1); - done(); - }, 200); - } - - var changes = db.changes({ - live: true - }).on('complete', function (result) { - result.status.should.equal('cancelled'); - // This setTimeout ensures that once we cancel a change we dont recieve - // subsequent callbacks, so it is needed - interval = setInterval(waitForDocPosted, 100); - }).on('change', function (change) { - count += 1; - if (count === 1) { - changes.cancel(); - db.post({ test: 'another doc' }, function (err, res) { - if (err) { - return done(err); - } - docPosted = true; - }); - } - }); - db.post({ test: 'adoc' }); - }); - - // TODO: https://github.com/daleharvey/pouchdb/issues/1460 - it('Kill database while listening to live changes', function (done) { - var db = new PouchDB(dbs.name); - var count = 0; - db.changes({ - complete: function (err, result) { - done(); - }, - onChange: function (change) { - count++; - if (count === 1) { - PouchDB.destroy(dbs.name); - } - }, - live: true - }); - db.post({ test: 'adoc' }); - }); - - it('changes-filter', function (done) { - var docs1 = [ - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - {_id: '2', integer: 2}, - {_id: '3', integer: 3}, - ]; - var docs2 = [ - {_id: '4', integer: 4}, - {_id: '5', integer: 5}, - {_id: '6', integer: 6}, - {_id: '7', integer: 7}, - ]; - var db = new PouchDB(dbs.name); - var count = 0; - db.bulkDocs({ docs: docs1 }, function (err, info) { - var changes = db.changes({ - complete: function (err, result) { - result.status.should.equal('cancelled'); - done(); - }, - filter: function (doc) { - return doc.integer % 2 === 0; - }, - onChange: function (change) { - count += 1; - if (count === 4) { - changes.cancel(); - } - }, - live: true - }); - db.bulkDocs({ docs: docs2 }); - }); - }); - - it('changes-filter with query params', function (done) { - var docs1 = [ - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - {_id: '2', integer: 2}, - {_id: '3', integer: 3}, - ]; - var docs2 = [ - {_id: '4', integer: 4}, - {_id: '5', integer: 5}, - {_id: '6', integer: 6}, - {_id: '7', integer: 7}, - ]; - var params = { 'abc': true }; - var db = new PouchDB(dbs.name); - var count = 0; - db.bulkDocs({ docs: docs1 }, function (err, info) { - var changes = db.changes({ - complete: function (err, result) { - result.status.should.equal('cancelled'); - done(); - }, - filter: function (doc, req) { - if (req.query.abc) { - return doc.integer % 2 === 0; - } - }, - query_params: params, - onChange: function (change) { - count += 1; - if (count === 4) { - changes.cancel(); - } - }, - live: true - }); - db.bulkDocs({ docs: docs2 }); - }); - }); - - it('Non-live changes filter', function (done) { - var docs1 = [ - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - {_id: '2', integer: 2}, - {_id: '3', integer: 3}, - ]; - var db = new PouchDB(dbs.name); - db.bulkDocs({ docs: docs1 }, function (err, info) { - db.changes({ - filter: function (doc) { - return doc.integer % 2 === 0; - }, - complete: function (err, changes) { - // Should get docs 0 and 2 if the filter has been applied correctly. - changes.results.length.should.equal(2); - done(); - } - }); - }); - }); - - it('#2569 Non-live doc_ids filter', function () { - var docs = [ - {_id: '0'}, - {_id: '1'}, - {_id: '2'}, - {_id: '3'} - ]; - var db = new PouchDB(dbs.name); - return db.bulkDocs(docs).then(function () { - return db.changes({ - doc_ids: ['1', '3'] - }); - }).then(function (changes) { - var ids = changes.results.map(function (x) { - return x.id; - }); - ids.sort().should.deep.equal(['1', '3']); - }); - }); - - it('#2569 Big non-live doc_ids filter', function () { - var docs = []; - for (var i = 0; i < 5; i++) { - var id = ''; - for (var j = 0; j < 50; j++) { - // make a huge id - id += PouchDB.utils.btoa(Math.random().toString()); - } - docs.push({_id: id}); - } - var db = new PouchDB(dbs.name); - return db.bulkDocs(docs).then(function () { - return db.changes({ - doc_ids: [docs[1]._id, docs[3]._id] - }); - }).then(function (changes) { - var ids = changes.results.map(function (x) { - return x.id; - }); - var expectedIds = [docs[1]._id, docs[3]._id]; - ids.sort().should.deep.equal(expectedIds.sort()); - }); - }); - - it('#2569 Live doc_ids filter', function () { - var docs = [ - {_id: '0'}, - {_id: '1'}, - {_id: '2'}, - {_id: '3'} - ]; - var db = new PouchDB(dbs.name); - return db.bulkDocs(docs).then(function () { - return new PouchDB.utils.Promise(function (resolve, reject) { - var retChanges = []; - var changes = db.changes({ - doc_ids: ['1', '3'], - live: true - }).on('change', function (change) { - retChanges.push(change); - if (retChanges.length === 2) { - changes.cancel(); - resolve(retChanges); - } - }).on('error', reject); - }); - }).then(function (changes) { - var ids = changes.map(function (x) { - return x.id; - }); - var expectedIds = ['1', '3']; - ids.sort().should.deep.equal(expectedIds); - }); - }); - - it('#2569 Big live doc_ids filter', function () { - var docs = []; - for (var i = 0; i < 5; i++) { - var id = ''; - for (var j = 0; j < 50; j++) { - // make a huge id - id += PouchDB.utils.btoa(Math.random().toString()); - } - docs.push({_id: id}); - } - var db = new PouchDB(dbs.name); - return db.bulkDocs(docs).then(function () { - return new PouchDB.utils.Promise(function (resolve, reject) { - var retChanges = []; - var changes = db.changes({ - doc_ids: [docs[1]._id, docs[3]._id], - live: true - }).on('change', function (change) { - retChanges.push(change); - if (retChanges.length === 2) { - changes.cancel(); - resolve(retChanges); - } - }).on('error', reject); - }); - }).then(function (changes) { - var ids = changes.map(function (x) { - return x.id; - }); - var expectedIds = [docs[1]._id, docs[3]._id]; - ids.sort().should.deep.equal(expectedIds.sort()); - }); - }); - - it('#2569 Non-live doc_ids filter with filter=_doc_ids', function () { - var docs = [ - {_id: '0'}, - {_id: '1'}, - {_id: '2'}, - {_id: '3'} - ]; - var db = new PouchDB(dbs.name); - return db.bulkDocs(docs).then(function () { - return db.changes({ - filter: '_doc_ids', - doc_ids: ['1', '3'] - }); - }).then(function (changes) { - var ids = changes.results.map(function (x) { - return x.id; - }); - ids.sort().should.deep.equal(['1', '3']); - }); - }); - - it('#2569 Live doc_ids filter with filter=_doc_ids', function () { - var docs = [ - {_id: '0'}, - {_id: '1'}, - {_id: '2'}, - {_id: '3'} - ]; - var db = new PouchDB(dbs.name); - return db.bulkDocs(docs).then(function () { - return db.changes({ - filter: '_doc_ids', - doc_ids: ['1', '3'] - }); - }).then(function (changes) { - var ids = changes.results.map(function (x) { - return x.id; - }); - ids.sort().should.deep.equal(['1', '3']); - }); - }); - - it('Changes to same doc are grouped', function (done) { - var docs1 = [ - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - {_id: '2', integer: 2}, - {_id: '3', integer: 3}, - ]; - var docs2 = [ - {_id: '2', integer: 11}, - {_id: '3', integer: 12}, - ]; - var db = new PouchDB(dbs.name); - db.bulkDocs({ docs: docs1 }, function (err, info) { - docs2[0]._rev = info[2].rev; - docs2[1]._rev = info[3].rev; - db.put(docs2[0], function (err, info) { - db.put(docs2[1], function (err, info) { - db.changes({ - include_docs: true, - complete: function (err, changes) { - changes.results.length.should.equal(4); - changes.results[2].seq.should.equal(5); - changes.results[2].id.should.equal('2'); - changes.results[2].changes.length.should.equal(1); - changes.results[2].doc.integer.should.equal(11); - done(); - } - }); - }); - }); - }); - }); - - it('Changes with conflicts are handled correctly', function (testDone) { - var docs1 = [ - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - {_id: '2', integer: 2}, - {_id: '3', integer: 3}, - ]; - var docs2 = [ - {_id: '2', integer: 11}, - {_id: '3', integer: 12}, - ]; - new PouchDB(dbs.name).then(function (localdb) { - var remotedb = new PouchDB(dbs.remote); - return localdb.bulkDocs({ docs: docs1 }).then(function (info) { - docs2[0]._rev = info[2].rev; - docs2[1]._rev = info[3].rev; - return localdb.put(docs2[0]).then(function (info) { - return localdb.put(docs2[1]).then(function (info) { - var rev2 = info.rev; - return PouchDB.replicate(localdb, remotedb).then(function (done) { - // update remote once, local twice, then replicate from - // remote to local so the remote losing conflict is later in - // the tree - return localdb.put({ - _id: '3', - _rev: rev2, - integer: 20 - }).then(function (resp) { - var rev3Doc = { - _id: '3', - _rev: resp.rev, - integer: 30 - }; - return localdb.put(rev3Doc).then(function (resp) { - var rev4local = resp.rev; - var rev4Doc = { - _id: '3', - _rev: rev2, - integer: 100 - }; - return remotedb.put(rev4Doc).then(function (resp) { - var remoterev = resp.rev; - return PouchDB.replicate(remotedb, localdb).then( - function (done) { - return localdb.changes({ - include_docs: true, - style: 'all_docs', - conflicts: true - }).on('error', testDone) - .then(function (changes) { - changes.results.length.should.equal(4); - var ch = changes.results[3]; - ch.id.should.equal('3'); - ch.changes.length.should.equal(2); - ch.doc.integer.should.equal(30); - ch.doc._rev.should.equal(rev4local); - ch.changes.should.deep.equal([ - { rev: rev4local }, - { rev: remoterev } - ]); - ch.doc.should.have.property('_conflicts'); - ch.doc._conflicts.length.should.equal(1); - ch.doc._conflicts[0].should.equal(remoterev); - }); - }); - }); - }); - }); - }); - }); - }); - }).then(function () { - testDone(); - }, testDone); - }); - }); - - it('Change entry for a deleted doc', function (done) { - var docs1 = [ - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - {_id: '2', integer: 2}, - {_id: '3', integer: 3} - ]; - var db = new PouchDB(dbs.name); - db.bulkDocs({ docs: docs1 }, function (err, info) { - var rev = info[3].rev; - db.remove({ - _id: '3', - _rev: rev - }, function (err, info) { - db.changes({ - include_docs: true, - complete: function (err, changes) { - changes.results.length.should.equal(4); - var ch = changes.results[3]; - ch.id.should.equal('3'); - ch.seq.should.equal(5); - ch.deleted.should.equal(true); - done(); - } - }); - }); - }); - }); - - it('changes large number of docs', function (done) { - var docs = []; - var num = 30; - for (var i = 0; i < num; i++) { - docs.push({ - _id: 'doc_' + i, - foo: 'bar_' + i - }); - } - var db = new PouchDB(dbs.name); - db.bulkDocs({ docs: docs }, function (err, info) { - db.changes({ - complete: function (err, res) { - res.results.length.should.equal(num); - done(); - } - }); - }); - }); - - it('Calling db.changes({since: \'now\'})', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs({ docs: [{ foo: 'bar' }] }, function (err, data) { - db.info(function (err, info) { - var api = db.changes({ - since: 'now', - complete: function (err, res) { - should.not.exist(err); - res.last_seq.should.equal(info.update_seq); - done(); - } - }); - api.should.be.an('object'); - api.cancel.should.be.an('function'); - }); - }); - }); - - //Duplicate to make sure both api options work. - it('Calling db.changes({since: \'latest\'})', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs({ docs: [{ foo: 'bar' }] }, function (err, data) { - db.info(function (err, info) { - var api = db.changes({ - since: 'latest', - complete: function (err, res) { - should.not.exist(err); - res.last_seq.should.equal(info.update_seq); - done(); - } - }); - api.should.be.an('object'); - api.cancel.should.be.an('function'); - }); - }); - }); - - it('Closing db does not cause a crash if changes cancelled', - function (done) { - var db = new PouchDB(dbs.name); - var called = 0; - function checkDone() { - called++; - if (called === 2) { - done(); - } - } - db.bulkDocs({ docs: [{ foo: 'bar' }] }, function (err, data) { - var changes = db.changes({ - live: true, - onChange: function () { }, - complete: function (err, result) { - result.status.should.equal('cancelled'); - checkDone(); - } - }); - should.exist(changes); - changes.cancel.should.be.a('function'); - changes.cancel(); - db.close(function (error) { - should.not.exist(error); - checkDone(); - }); - }); - }); - - it('fire-complete-on-cancel', function (done) { - var db = new PouchDB(dbs.name); - var cancelled = false; - var changes = db.changes({ - live: true, - complete: function (err, result) { - cancelled.should.equal(true); - should.not.exist(err); - should.exist(result); - if (result) { - result.status.should.equal('cancelled'); - } - done(); - } - }); - should.exist(changes); - changes.cancel.should.be.a('function'); - setTimeout(function () { - cancelled = true; - changes.cancel(); - }, 100); - }); - - it('changes are not duplicated', function (done) { - var db = new PouchDB(dbs.name); - var called = 0; - var changes = db.changes({ - live: true, - onChange: function () { - called++; - if (called === 1) { - setTimeout(function () { - changes.cancel(); - }, 1000); - } - }, - complete: function (err) { - called.should.equal(1); - done(); - } - }); - db.post({key: 'value'}); - }); - function waitASec(fun, time) { - return new PouchDB.utils.Promise(function (fulfill) { - setTimeout(function () { - fulfill(fun()); - }, time); - }); - } - it('CRUD events are handled correclty', function (done) { - var db = new PouchDB(dbs.name); - var changes = db.changes({ - live: true, - style: 'all_docs' - }); - var deleted = 0; - var updated = 0; - var created = 0; - function chuckDone() { - if ((deleted + updated + created) === 6) { - changes.cancel(); - } - } - changes.on('cancel', function () { - setTimeout(function () { - deleted.should.equal(1, 'correct number of deleted'); - created.should.equal(2, 'create number of created'); - updated.should.equal(3, 'correct number of updates'); - done(); - }, 100); - }).on('delete', function (change) { - deleted++; - chuckDone(); - }).on('create', function (change) { - created++; - chuckDone(); - }).on('update', function (change) { - updated++; - chuckDone(); - }).on('error', function (err) { - done(err); - }); - var rev1, rev2; - db.put({ - title: 'Holding On For Life' - }, 'currentSong').then(function (resp) { - rev1 = resp.rev; - return waitASec(function () { - return db.put({ - title: 'Sushi' - }, 'nextSong'); - }, 100); - }).then(function (resp) { - rev2 = resp.rev; - return waitASec(function () { - return db.put({ - title: 'Holding On For Life', - artist: 'Broken Bells' - }, 'currentSong', rev1); - }, 100); - }).then(function (resp) { - rev1 = resp.rev; - return waitASec(function () { - return db.put({ - title: 'Sushi', - artist: 'Kyle Andrews' - }, 'nextSong', rev2); - }, 100); - }).then(function (resp) { - rev2 = resp.rev; - return waitASec(function () { - return db.remove({ - _id: 'currentSong', - _rev: rev1 - }); - }, 100); - }).then(function (resp) { - return db.put({ - title: 'Sushi', - artist: 'Kyle Andrews', - album: 'Real Blasty' - }, 'nextSong', rev2); - }); - }); - - it('supports returnDocs=false', function (done) { - var db = new PouchDB(dbs.name); - var docs = []; - var num = 10; - for (var i = 0; i < num; i++) { - docs.push({ _id: 'doc_' + i, }); - } - var changes = 0; - db.bulkDocs({ docs: docs }, function (err, info) { - if (err) { - return done(err); - } - db.changes({ - descending: true, - returnDocs : false - }).on('change', function (change) { - changes++; - }).on('complete', function (results) { - results.results.should.have.length(0, '0 results returned'); - changes.should.equal(num, 'correct number of changes'); - done(); - }).on('error', function (err) { - done(err); - }); - }); - }); - - it('should respects limit', function (done) { - var docs1 = [ - {_id: '_local/foo'}, - {_id: 'a', integer: 0}, - {_id: 'b', integer: 1}, - {_id: 'c', integer: 2}, - {_id: 'd', integer: 3} - ]; - var called = 0; - var db = new PouchDB(dbs.name); - db.bulkDocs({ docs: docs1 }, function (err, info) { - db.changes({ - limit: 1 - }).on('change', function (ch) { - (called++).should.equal(0); - }).on('complete', function () { - setTimeout(function () { - done(); - }, 50); - }); - }); - }); - - it.skip('should respects limit with live replication', function (done) { - var docs1 = [ - {_id: '_local/foo'}, - {_id: 'a', integer: 0}, - {_id: 'b', integer: 1}, - {_id: 'c', integer: 2}, - {_id: 'd', integer: 3} - ]; - var called = 0; - var doneCalled = 0; - function calldone() { - doneCalled++; - if (doneCalled === 2) { - done(); - } - } - var db = new PouchDB(dbs.name); - db.changes({ - limit: 1, - live: true - }).on('change', function (ch) { - ch.id.should.equal('a'); - (called++).should.equal(0); - }).on('complete', function () { - calldone(); - }); - db.bulkDocs({ docs: docs1 }).then(calldone); - }); - - it('doesn\'t throw if opts.complete is undefined', function (done) { - var db = new PouchDB(dbs.name); - db.put({_id: 'foo'}).then(function () { - db.changes().on('change', function () { - done(); - }).on('error', function (err) { - done(err); - }); - }, done); - }); - }); -}); - -describe('changes-standalone', function () { - - it('Changes reports errors', function (done) { - this.timeout(2000); - var db = new PouchDB('http://infiniterequest.com', { skipSetup: true }); - db.changes({ - timeout: 1000, - complete: function (err, changes) { - should.exist(err); - done(); - } - }); - }); - -});
diff --git a/tests/integration/test.compaction.js b/tests/integration/test.compaction.js deleted file mode 100644 index eb01d02..0000000 --- a/tests/integration/test.compaction.js +++ /dev/null
@@ -1,1353 +0,0 @@ -'use strict'; - -var adapters = ['http', 'local']; -var autoCompactionAdapters = ['local']; - -adapters.forEach(function (adapter) { - describe('test.compaction.js-' + adapter, function () { - - var dbs = {}; - - beforeEach(function (done) { - dbs.name = testUtils.adapterUrl(adapter, 'testdb'); - testUtils.cleanup([dbs.name], done); - }); - - after(function (done) { - testUtils.cleanup([dbs.name], done); - }); - - it('#2913 massively parallel compaction', function () { - var db = new PouchDB(dbs.name); - var tasks = []; - for (var i = 0; i < 30; i++) { - tasks.push(i); - } - - return PouchDB.utils.Promise.all(tasks.map(function (i) { - var doc = {_id: 'doc_' + i}; - return db.put(doc).then(function () { - return db.compact(); - }).then(function () { - return db.get('doc_' + i); - }).then(function (doc) { - return db.put(doc); - }).then(function () { - return db.compact(); - }); - })); - }); - - it('Compaction document with no revisions to remove', function (done) { - var db = new PouchDB(dbs.name); - var doc = {_id: 'foo', value: 'bar'}; - db.put(doc, function (err, res) { - db.compact(function () { - db.get('foo', function (err, doc) { - done(err); - }); - }); - }); - }); - - it('Compation on empty db', function (done) { - var db = new PouchDB(dbs.name); - db.compact(function () { - done(); - }); - }); - - it('Compation on empty db with interval option', function (done) { - var db = new PouchDB(dbs.name); - db.compact({ interval: 199 }, function () { - done(); - }); - }); - - it('Simple compation test', function (done) { - var db = new PouchDB(dbs.name); - var doc = { - _id: 'foo', - value: 'bar' - }; - db.post(doc, function (err, res) { - var rev1 = res.rev; - doc._rev = rev1; - doc.value = 'baz'; - db.post(doc, function (err, res) { - var rev2 = res.rev; - db.compact(function () { - db.get('foo', { rev: rev1 }, function (err, doc) { - err.status.should.equal(404); - err.name.should.equal( - 'not_found', 'compacted document is missing' - ); - db.get('foo', { rev: rev2 }, function (err, doc) { - done(err); - }); - }); - }); - }); - }); - }); - - var checkBranch = function (db, docs, callback) { - function check(i) { - var doc = docs[i]; - db.get(doc._id, { rev: doc._rev }, function (err) { - if (i < docs.length - 1) { - should.exist(err, 'should be compacted: ' + doc._rev); - err.status.should.equal(404, 'compacted!'); - check(i + 1); - } else { - should.not.exist(err, 'should not be compacted: ' + doc._rev); - callback(); - } - }); - } - check(0); - }; - - var checkTree = function (db, tree, callback) { - function check(i) { - checkBranch(db, tree[i], function () { - if (i < tree.length - 1) { - check(i + 1); - } else { - callback(); - } - }); - } - check(0); - }; - - var exampleTree = [ - [{_id: 'foo', _rev: '1-a', value: 'foo a'}, - {_id: 'foo', _rev: '2-b', value: 'foo b'}, - {_id: 'foo', _rev: '3-c', value: 'foo c'} - ], - [{_id: 'foo', _rev: '1-a', value: 'foo a'}, - {_id: 'foo', _rev: '2-d', value: 'foo d'}, - {_id: 'foo', _rev: '3-e', value: 'foo e'}, - {_id: 'foo', _rev: '4-f', value: 'foo f'} - ], - [{_id: 'foo', _rev: '1-a', value: 'foo a'}, - {_id: 'foo', _rev: '2-g', value: 'foo g'}, - {_id: 'foo', _rev: '3-h', value: 'foo h'}, - {_id: 'foo', _rev: '4-i', value: 'foo i'}, - {_id: 'foo', _rev: '5-j', _deleted: true, value: 'foo j'} - ] - ]; - - var exampleTree2 = [ - [{_id: 'bar', _rev: '1-m', value: 'bar m'}, - {_id: 'bar', _rev: '2-n', value: 'bar n'}, - {_id: 'bar', _rev: '3-o', _deleted: true, value: 'foo o'} - ], - [{_id: 'bar', _rev: '2-n', value: 'bar n'}, - {_id: 'bar', _rev: '3-p', value: 'bar p'}, - {_id: 'bar', _rev: '4-r', value: 'bar r'}, - {_id: 'bar', _rev: '5-s', value: 'bar s'} - ], - [{_id: 'bar', _rev: '3-p', value: 'bar p'}, - {_id: 'bar', _rev: '4-t', value: 'bar t'}, - {_id: 'bar', _rev: '5-u', value: 'bar u'} - ] - ]; - - it('Compact more complicated tree', function (done) { - new PouchDB(dbs.name, function (err, db) { - testUtils.putTree(db, exampleTree, function () { - db.compact(function () { - checkTree(db, exampleTree, function () { - done(); - }); - }); - }); - }); - }); - - it('Compact two times more complicated tree', function (done) { - var db = new PouchDB(dbs.name); - testUtils.putTree(db, exampleTree, function () { - db.compact(function () { - db.compact(function () { - checkTree(db, exampleTree, function () { - done(); - }); - }); - }); - }); - }); - - it('Compact database with at least two documents', function (done) { - var db = new PouchDB(dbs.name); - testUtils.putTree(db, exampleTree, function () { - testUtils.putTree(db, exampleTree2, function () { - db.compact(function () { - checkTree(db, exampleTree, function () { - checkTree(db, exampleTree2, function () { - done(); - }); - }); - }); - }); - }); - }); - - it('Compact deleted document', function (done) { - var db = new PouchDB(dbs.name); - db.put({ _id: 'foo' }, function (err, res) { - var firstRev = res.rev; - db.remove({ - _id: 'foo', - _rev: firstRev - }, function (err, res) { - db.compact(function () { - db.get('foo', { rev: firstRev }, function (err, res) { - should.exist(err, 'got error'); - err.message.should.equal('missing', 'correct reason'); - done(); - }); - }); - }); - }); - }); - - it('Compact db with sql-injecty doc id', function (done) { - var db = new PouchDB(dbs.name); - var id = '\'sql_injection_here'; - db.put({ _id: id }, function (err, res) { - var firstRev = res.rev; - db.remove({ - _id: id, - _rev: firstRev - }, function (err, res) { - db.compact(function () { - db.get(id, { rev: firstRev }, function (err, res) { - should.exist(err, 'got error'); - err.message.should.equal('missing', 'correct reason'); - done(); - }); - }); - }); - }); - }); - - - function getRevisions(db, docId) { - return db.get(docId, { - revs: true, - open_revs: 'all' - }).then(function (docs) { - var combinedResult = []; - return PouchDB.utils.Promise.all(docs.map(function (doc) { - doc = doc.ok; - // convert revision IDs into full _rev hashes - var start = doc._revisions.start; - return PouchDB.utils.Promise.all( - doc._revisions.ids.map(function (id, i) { - var rev = (start - i) + '-' + id; - return db.get(docId, {rev: rev}).then(function (doc) { - return { rev: rev, doc: doc }; - }).catch(function (err) { - if (err.status !== 404) { - throw err; - } - return { rev: rev }; - }); - })).then(function (docsAndRevs) { - combinedResult = combinedResult.concat(docsAndRevs); - }); - })).then(function () { - return combinedResult; - }); - }); - } - - it('Compaction removes non-leaf revs (#2807)', function () { - var db = new PouchDB(dbs.name, {auto_compaction: false}); - var doc = {_id: 'foo'}; - return db.put(doc).then(function (res) { - doc._rev = res.rev; - return getRevisions(db, 'foo'); - }).then(function (docsAndRevs) { - docsAndRevs.should.have.length(1); - return db.put(doc); - }).then(function (res) { - doc._rev = res.rev; - return getRevisions(db, 'foo'); - }).then(function (docsAndRevs) { - docsAndRevs.should.have.length(2); - should.exist(docsAndRevs[0].doc); - should.exist(docsAndRevs[1].doc); - return db.compact(); - }).then(function () { - return getRevisions(db, 'foo'); - }).then(function (docsAndRevs) { - docsAndRevs.should.have.length(2); - should.exist(docsAndRevs[0].doc); - should.not.exist(docsAndRevs[1].doc); - }); - }); - - it('Compaction removes non-leaf revs pt 2 (#2807)', function () { - var db = new PouchDB(dbs.name, {auto_compaction: false}); - var doc = {_id: 'foo'}; - return db.put(doc).then(function (res) { - doc._rev = res.rev; - return db.put(doc); - }).then(function (res) { - doc._rev = res.rev; - return db.put(doc); - }).then(function () { - return db.compact(); - }).then(function () { - return getRevisions(db, 'foo'); - }).then(function (docsAndRevs) { - docsAndRevs.should.have.length(3); - should.exist(docsAndRevs[0].doc); - should.not.exist(docsAndRevs[1].doc); - should.not.exist(docsAndRevs[2].doc); - }); - }); - - it('Compaction removes non-leaf revs pt 3 (#2807)', function () { - var db = new PouchDB(dbs.name, {auto_compaction: false}); - - var docs = [ - { - _id: 'foo', - _rev: '1-a1', - _revisions: { start: 1, ids: [ 'a1' ] } - }, { - _id: 'foo', - _rev: '2-a2', - _revisions: { start: 2, ids: [ 'a2', 'a1' ] } - }, { - _id: 'foo', - _deleted: true, - _rev: '3-a3', - _revisions: { start: 3, ids: [ 'a3', 'a2', 'a1' ] } - }, { - _id: 'foo', - _rev: '1-b1', - _revisions: { start: 1, ids: [ 'b1' ] } - } - ]; - - return db.bulkDocs(docs, {new_edits: false}).then(function () { - return getRevisions(db, 'foo'); - }).then(function (docsAndRevs) { - docsAndRevs.should.have.length(4); - should.exist(docsAndRevs[0].doc); - should.exist(docsAndRevs[1].doc); - should.exist(docsAndRevs[2].doc); - should.exist(docsAndRevs[3].doc); - return db.compact(); - }).then(function () { - return getRevisions(db, 'foo'); - }).then(function (docsAndRevs) { - docsAndRevs.should.have.length(4); - var asMap = {}; - docsAndRevs.forEach(function (docAndRev) { - asMap[docAndRev.rev] = docAndRev.doc; - }); - // only leafs remain - should.not.exist(asMap['1-a1']); - should.not.exist(asMap['2-a2']); - should.exist(asMap['3-a3']); - should.exist(asMap['1-b1']); - }); - }); - - it('Compaction removes non-leaf revs pt 4 (#2807)', function () { - if (testUtils.isCouchMaster()) { - return true; - } - var db = new PouchDB(dbs.name, {auto_compaction: false}); - var doc = {_id: 'foo'}; - return db.put(doc).then(function (res) { - doc._rev = res.rev; - doc._deleted = true; - return db.put(doc); - }).then(function (res) { - doc._rev = res.rev; - delete doc._deleted; - return db.put(doc); - }).then(function () { - return db.compact(); - }).then(function () { - return getRevisions(db, 'foo'); - }).then(function (docsAndRevs) { - docsAndRevs.should.have.length(3); - should.exist(docsAndRevs[0].doc); - should.not.exist(docsAndRevs[1].doc); - should.not.exist(docsAndRevs[2].doc); - }); - }); - - it('Compaction removes non-leaf revs pt 5 (#2807)', function () { - var db = new PouchDB(dbs.name, {auto_compaction: false}); - var doc = {_id: 'foo'}; - return db.put(doc).then(function (res) { - doc._rev = res.rev; - return db.put(doc); - }).then(function (res) { - doc._rev = res.rev; - doc._deleted = true; - return db.put(doc); - }).then(function () { - return db.compact(); - }).then(function () { - return getRevisions(db, 'foo'); - }).then(function (docsAndRevs) { - docsAndRevs.should.have.length(3); - should.exist(docsAndRevs[0].doc); - should.not.exist(docsAndRevs[1].doc); - should.not.exist(docsAndRevs[2].doc); - }); - }); - - it('#2931 - synchronous putAttachment + compact', function () { - - var db = new PouchDB(dbs.name); - var queue = db.put({_id: 'doc'}); - - var otherPromises = []; - - for (var i = 0; i < 50; i++) { - /* jshint loopfunc:true */ - queue = queue.then(function () { - return db.get('doc').then(function (doc) { - doc._attachments = doc._attachments || {}; - var blob = testUtils.makeBlob( - PouchDB.utils.btoa(Math.random().toString()), - 'text/plain'); - return db.putAttachment(doc._id, 'att.txt', doc._rev, blob, - 'text/plain'); - }); - }); - queue.then(function () { - var promise = PouchDB.utils.Promise.all([ - db.compact(), - db.compact(), - db.compact(), - db.compact(), - db.compact() - ]); - otherPromises.push(promise); - return promise; - }); - } - return queue.then(function () { - return PouchDB.utils.Promise.all(otherPromises); - }); - }); - - it('#2931 - synchronous putAttachment + compact 2', function () { - - var db = new PouchDB(dbs.name); - var queue = db.put({_id: 'doc'}); - - var compactQueue = PouchDB.utils.Promise.resolve(); - - for (var i = 0; i < 50; i++) { - /* jshint loopfunc:true */ - queue = queue.then(function () { - return db.get('doc').then(function (doc) { - doc._attachments = doc._attachments || {}; - var blob = testUtils.makeBlob( - PouchDB.utils.btoa(Math.random().toString()), - 'text/plain'); - return db.putAttachment(doc._id, 'att.txt', doc._rev, blob, - 'text/plain'); - }); - }); - queue.then(function () { - compactQueue = compactQueue.then(function () { - return PouchDB.utils.Promise.all([ - db.compact(), - db.compact(), - db.compact(), - db.compact(), - db.compact() - ]); - }); - }); - } - return queue.then(function () { - return compactQueue; - }); - }); - - // - // NO MORE HTTP TESTS AFTER THIS POINT! - // - // We're testing some very local-specific functionality - // - - - if (autoCompactionAdapters.indexOf(adapter) === -1) { - return; - } - - // - // Tests for issue #2818 follow, which make some assumptions - // about how binary data is stored, so they don't pass in - // CouchDB. Namely, PouchDB dedups attachments based on - // md5sum, whereas CouchDB does not. - // - - // per https://en.wikipedia.org/wiki/MD5, - // these two should have colliding md5sums - var att1 = '0THdAsXm7sRpPZoGmK/5XC/KtQcSRn6r' + - 'QARYPrj7f4lVrTQGCfSzAoPkiIMl8UFaCFEl6PfNyZ/Z' + - 'Hb1ygDc8W9iCPjFWNI9brm2s1DbJGcbdU+I0h9oD/' + - 'QI5YwbSSM2g6Z8zQg9XfujOVLZwgCgNHsaY' + - 'Iby2qIOTlvllq2/3KnA='; - var att2 = '0THdAsXm7sRpPZoGmK/5XC/KtYcSRn6r' + - 'QARYPrj7f4lVrTQGCfSzAoPkiIMlcUFaCFEl6PfNyZ/Z' + - 'Hb3ygDc8W9iCPjFWNI9brm2s1DbJGcbdU+K0h9oD/' + - 'QI5YwbSSM2g6Z8zQg9XfujOVLZwgKgNHsaY' + - 'Iby2qIOTlvllK2/3KnA='; - - it('#2818 md5 collision (sanity check)', function () { - // - // CouchDB will throw! - // - var db = new PouchDB(dbs.name, {auto_compaction: false}); - var doc1 = { - _id: 'doc1', - _attachments: { - 'att.txt': { - data: att1, - content_type: 'application/octet-stream' - } - } - }; - var doc2 = { - _id: 'doc2', - _attachments: { - 'att.txt': { - data: att2, - content_type: 'application/octet-stream' - } - } - }; - var doc3 = { - _id: 'doc3', - _attachments: { - 'att.txt': { - data: '1' + att2.substring(1), // distractor - content_type: 'application/octet-stream' - } - } - }; - return db.put(doc1).then(function () { - return db.put(doc2); - }).then(function () { - return db.put(doc3); - }).then(function () { - return db.allDocs({include_docs: true}); - }).then(function (res) { - var md1 = res.rows[0].doc._attachments['att.txt'].digest; - var md2 = res.rows[1].doc._attachments['att.txt'].digest; - var md3 = res.rows[2].doc._attachments['att.txt'].digest; - md1.should.not.equal(md3, 'md5 sums should not collide'); - md2.should.not.equal(md3, 'md5 sums should not collide'); - md1.should.equal(md2, - 'md5 sums should collide. if not, other #2818 tests will fail'); - }).then(function () { - return PouchDB.utils.Promise.all(['doc1', 'doc2'].map(function (id) { - return db.get(id, {attachments: true}); - })).then(function (docs) { - var data1 = docs[0]._attachments['att.txt'].data; - var data2 = docs[1]._attachments['att.txt'].data; - data1.should.equal(data2, - 'yay, we are vulnerable to md5sum collision (1)'); - att1.should.equal(data2, - 'att1 is the final one, not att2'); - }); - }); - }); - - it('#2818 md5 collision between revs (sanity check)', function () { - // - // CouchDB will throw! - // - var db = new PouchDB(dbs.name, {auto_compaction: false}); - var doc1 = { - _id: 'doc1', - _attachments: { - 'att.txt': { - data: att1, - content_type: 'application/octet-stream' - } - } - }; - var rev1; - var rev2; - return db.put(doc1).then(function (res) { - rev1 = doc1._rev = res.rev; - doc1._attachments['att.txt'].data = att2; - return db.put(doc1); - }).then(function (res) { - rev2 = res.rev; - return PouchDB.utils.Promise.all([rev1, rev2].map(function (rev) { - return db.get('doc1', {rev: rev, attachments: true}); - })); - }).then(function (docs) { - var data1 = docs[0]._attachments['att.txt'].data; - var data2 = docs[1]._attachments['att.txt'].data; - data1.should.equal(data2, - 'yay, we are vulnerable to md5sum collision'); - }); - }); - - it('#2818 doesn\'t throw 412, thanks to digest', function () { - // - // CouchDB will throw! - // - var db = new PouchDB(dbs.name, {auto_compaction: false}); - var doc1 = { - _id: 'doc1', - _attachments: { - 'att.txt': { - data: 'Zm9vYmFy', // 'foobar' - content_type: 'text/plain' - } - } - }; - - return db.put(doc1).then(function (res) { - return db.get('doc1'); - }).then(function (doc1) { - var doc2 = { - _id: 'doc2', - _attachments: { - 'att.txt': { - stub: true, - digest: doc1._attachments['att.txt'].digest, - content_type: 'text/plain' - } - } - }; - return db.put(doc2); - }); - }); - - it('#2818 Compaction removes attachments', function () { - // now that we've established no 412s thanks to digests, - // we can use that to detect true attachment deletion - var db = new PouchDB(dbs.name, {auto_compaction: false}); - var doc = { - _id: 'doc1', - _attachments: { - 'deleteme.txt': { - data: 'Zm9vYmFy', // 'foobar' - content_type: 'text/plain' - } - } - }; - var digest; - return db.put(doc).then(function () { - return db.get('doc1'); - }).then(function (doc) { - digest = doc._attachments['deleteme.txt'].digest; - delete doc._attachments['deleteme.txt']; - doc._attachments['retainme.txt'] = { - data: 'dG90bw==', // 'toto' - content_type: 'text/plain' - }; - return db.put(doc); - }).then(function () { - return db.compact(); - }).then(function () { - return db.get('doc1'); - }).then(function (doc) { - doc._attachments['newatt.txt'] = { - content_type: "text/plain", - digest: digest, - stub: true - }; - return db.put(doc).then(function () { - throw new Error('shouldn\'t have gotten here'); - }, function (err) { - err.status.should.equal(412); - }); - }); - }); - - it('#2818 Compaction removes attachments given conflicts', function () { - var db = new PouchDB(dbs.name, {auto_compaction: false}); - - var docs = [ - { - _id: 'fubar', - _rev: '1-a1', - _revisions: { start: 1, ids: [ 'a1' ] }, - _attachments: { - 'att.txt': { - data: 'Zm9vYmFy', // 'foobar' - content_type: 'text/plain' - } - } - }, { - _id: 'fubar', - _rev: '2-a2', - _revisions: { start: 2, ids: [ 'a2', 'a1' ] }, - _attachments: { - 'att.txt': { - data: 'dG90bw==', // 'toto' - content_type: 'text/plain' - } - } - }, { - _id: 'fubar', - _rev: '3-a3', - _revisions: { start: 3, ids: [ 'a3', 'a2', 'a1' ] }, - _attachments: { - 'att.txt': { - data: 'Ym9uZ28=', // 'bongo' - content_type: 'text/plain' - } - } - }, { - _id: 'fubar', - _rev: '1-b1', - _revisions: { start: 1, ids: [ 'b1' ] }, - _attachments: { - 'att.txt': { - data: 'enV6dQ==', // 'zuzu' - content_type: 'text/plain' - } - } - } - ]; - - var allDigests = []; - var digestsToForget = []; - var digestsToRemember = []; - return db.bulkDocs({ - docs: docs, - new_edits: false - }).then(function () { - return PouchDB.utils.Promise.all([ - '1-a1', '2-a2', '3-a3', '1-b1' - ].map(function (rev) { - return db.get('fubar', {rev: rev, attachments: true}); - })); - }).then(function (docs) { - digestsToForget.push(docs[0]._attachments['att.txt'].digest); - digestsToForget.push(docs[1]._attachments['att.txt'].digest); - digestsToRemember.push(docs[2]._attachments['att.txt'].digest); - digestsToRemember.push(docs[3]._attachments['att.txt'].digest); - - allDigests = allDigests.concat(digestsToForget).concat( - digestsToRemember); - - return PouchDB.utils.Promise.all(allDigests.map(function (digest) { - var doc = { - _attachments: { - 'newatt.txt': { - content_type: "text/plain", - digest: digest, - stub: true - } - } - }; - return db.post(doc).then(function (res) { - return db.remove(res.id, res.rev); - }); - })); - }).then(function () { - return db.compact(); - }).then(function () { - return PouchDB.utils.Promise.all(digestsToForget.map( - function (digest) { - var doc = { - _attachments: { - 'newatt.txt': { - content_type: "text/plain", - digest: digest, - stub: true - } - } - }; - return db.post(doc).then(function () { - throw new Error('shouldn\'t have gotten here'); - }, function (err) { - err.status.should.equal(412); - }); - })); - }).then(function () { - return PouchDB.utils.Promise.all(digestsToRemember.map( - function (digest) { - var doc = { - _attachments: { - 'newatt.txt': { - content_type: "text/plain", - digest: digest, - stub: true - } - } - }; - return db.post(doc); - })); - }); - }); - - it('#2818 Compaction retains attachments if unorphaned', function () { - var db = new PouchDB(dbs.name, {auto_compaction: false}); - var doc = { - _id: 'doc1', - _attachments: { - 'deleteme.txt': { - data: 'Zm9vYmFy', // 'foobar' - content_type: 'text/plain' - } - } - }; - var digest; - return db.put(doc).then(function () { - return db.get('doc1'); - }).then(function (doc) { - digest = doc._attachments['deleteme.txt'].digest; - delete doc._attachments['deleteme.txt']; - doc._attachments['retainme.txt'] = { - data: 'dG90bw==', // 'toto' - content_type: 'text/plain' - }; - return db.put(doc); - }).then(function () { - return db.put({ - _id: 'doc2', - _attachments: { - 'nodontdeleteme.txt': { - data: 'Zm9vYmFy', // 'foobar' - content_type: 'text/plain' - } - } - }); - }).then(function () { - return db.compact(); - }).then(function () { - return db.get('doc1'); - }).then(function (doc) { - doc._attachments['newatt.txt'] = { - content_type: "text/plain", - digest: digest, - stub: true - }; - return db.put(doc); - }).then(function () { - return db.allDocs(); - }).then(function (res) { - // ok, now let's really delete them - var docs = [ - { - _id: 'doc1', - _rev: res.rows[0].value.rev - }, - { - _id: 'doc2', - _rev: res.rows[1].value.rev - } - ]; - return db.bulkDocs(docs); - }).then(function () { - return db.compact(); - }).then(function () { - var doc = { - _attachments: { - 'foo.txt': { - content_type: "text/plain", - digest: digest, - stub: true - } - } - }; - return db.post(doc).then(function () { - throw new Error('shouldn\'t have gotten here'); - }, function (err) { - err.status.should.equal(412); - }); - }); - }); - - it('#2818 successive new_edits okay with attachments', function () { - var db = new PouchDB(dbs.name); - var docs = [{ - '_id': 'foo', - '_rev': '1-x', - '_revisions': { - 'start': 1, - 'ids': ['x'] - }, - _attachments: { - 'att.txt': { - data: 'Zm9vYmFy', // 'foobar' - content_type: 'text/plain' - } - } - }]; - var digest; - return db.bulkDocs({docs: docs, new_edits: false}).then(function () { - return db.bulkDocs({docs: docs, new_edits: false}); - }).then(function () { - return db.get('foo', {attachments: true}); - }).then(function (doc) { - doc._rev.should.equal('1-x'); - digest = doc._attachments['att.txt'].digest; - }).then(function () { - var doc = { - _attachments: { - 'foo.txt': { - content_type: "text/plain", - digest: digest, - stub: true - } - } - }; - return db.post(doc); - }); - }); - - it('#2818 Compaction really replaces attachments', function () { - // now that we've established md5sum collisions, - // we can use that to detect true attachment replacement - var db = new PouchDB(dbs.name, {auto_compaction: false}); - return db.put({ - _id: 'doc1', - _attachments: { - 'att.txt': { - data: att1, - content_type: 'application/octet-stream' - } - } - }).then(function () { - return db.get('doc1', {attachments: true}); - }).then(function (doc1) { - doc1._attachments['att.txt'].data.should.equal(att1, 'doc1'); - return db.put({ - _id: 'doc2', - _attachments: { - 'att.txt': { - data: att2, - content_type: 'application/octet-stream' - } - } - }); - }).then(function () { - return db.allDocs({include_docs: true}); - }).then(function (res) { - res.rows[0].doc._attachments['att.txt'].digest.should.equal( - res.rows[1].doc._attachments['att.txt'].digest, - 'digests collide' - ); - return db.get('doc1', {attachments: true}); - }).then(function (doc1) { - doc1._attachments['att.txt'].data.should.equal(att1, - 'doc1 has original att, indicating we didn\'t overwrite it'); - return db.get('doc2', {attachments: true}); - }).then(function (doc2) { - doc2._attachments['att.txt'].data.should.equal(att1, - 'doc2 also has original att'); - return db.remove(doc2); - }).then(function () { - return db.get('doc1'); - }).then(function (doc1) { - return db.remove(doc1); - }).then(function () { - return db.compact(); - }).then(function () { - return db.put({ - _id: 'doc3', - _attachments: { - 'att.txt': { - data: att2, - content_type: 'application/octet-stream' - } - } - }); - }).then(function () { - return db.put({ - _id: 'doc4', - _attachments: { - 'att.txt': { - data: att1, - content_type: 'application/octet-stream' - } - } - }); - }).then(function () { - return db.get('doc3', {attachments: true}); - }).then(function (doc3) { - doc3._attachments['att.txt'].data.should.equal(att2, - 'md5-colliding content was really replaced'); - return db.get('doc4', {attachments: true}); - }).then(function (doc4) { - doc4._attachments['att.txt'].data.should.equal(att2, - 'md5-colliding content was really replaced'); - }); - }); - - it('#2818 Many orphaned attachments', function () { - // now that we've established md5sum collisions, - // we can use that to detect true attachment replacement - var db = new PouchDB(dbs.name, {auto_compaction: false}); - var docs = [ - { - _id: 'doc1', - _attachments: { - 'att1.txt': { - data: PouchDB.utils.btoa('1'), - content_type: 'text/plain' - }, - 'att2.txt': { - data: PouchDB.utils.btoa('2'), - content_type: 'text/plain' - }, - 'att3.txt': { - data: PouchDB.utils.btoa('3'), - content_type: 'text/plain' - }, - 'att4.txt': { - data: PouchDB.utils.btoa('4'), - content_type: 'text/plain' - }, - 'att5.txt': { - data: PouchDB.utils.btoa('5'), - content_type: 'text/plain' - } - } - }, { - _id: 'doc2', - _attachments: { - 'att3.txt': { - data: PouchDB.utils.btoa('3'), - content_type: 'text/plain' - }, - 'att4.txt': { - data: PouchDB.utils.btoa('4'), - content_type: 'text/plain' - }, - 'att5.txt': { - data: PouchDB.utils.btoa('5'), - content_type: 'text/plain' - }, - 'att6.txt': { - data: PouchDB.utils.btoa('6'), - content_type: 'text/plain' - } - } - }, { - _id: 'doc3', - _attachments: { - 'att1.txt': { - data: PouchDB.utils.btoa('1'), - content_type: 'text/plain' - }, - 'att6.txt': { - data: PouchDB.utils.btoa('6'), - content_type: 'text/plain' - }, - 'att7.txt': { - data: PouchDB.utils.btoa('7'), - content_type: 'text/plain' - } - } - } - ]; - - var digestsToForget; - var digestsToRemember; - return db.bulkDocs(docs).then(function () { - return db.compact(); - }).then(function () { - return db.allDocs({include_docs: true}); - }).then(function (res) { - var allAtts = {}; - res.rows.forEach(function (row) { - Object.keys(row.doc._attachments).forEach(function (attName) { - var att = row.doc._attachments[attName]; - allAtts[attName] = att.digest; - }); - }); - digestsToForget = [ - allAtts['att2.txt'], - allAtts['att3.txt'], - allAtts['att4.txt'], - allAtts['att5.txt'] - ]; - digestsToRemember = [ - allAtts['att1.txt'], - allAtts['att6.txt'], - allAtts['att7.txt'] - ]; - return db.get('doc1'); - }).then(function (doc1) { - return db.remove(doc1); - }).then(function () { - return db.get('doc2'); - }).then(function (doc2) { - return db.remove(doc2); - }).then(function () { - return db.compact(); - }).then(function () { - return PouchDB.utils.Promise.all( - digestsToRemember.map(function (digest) { - return db.post({ - _attachments: { - 'baz.txt' : { - stub: true, - digest: digest, - content_type: 'text/plain' - } - } - }); - })); - }).then(function () { - return PouchDB.utils.Promise.all( - digestsToForget.map(function (digest) { - return db.post({ - _attachments: { - 'baz.txt' : { - stub: true, - digest: digest, - content_type: 'text/plain' - } - } - }).then(function () { - throw new Error('shouldn\'t have gotten here'); - }, function (err) { - err.status.should.equal(412); - }); - })); - }); - }); - - it('#3092 atts should be ignored when _deleted - bulkDocs', function () { - // now that we've established md5sum collisions, - // we can use that to detect true attachment replacement - var db = new PouchDB(dbs.name, {auto_compaction: false}); - var doc = { _id: 'doc1',}; - return db.put(doc).then(function (info) { - doc._rev = info.rev; - doc._deleted = true; - doc._attachments = { - 'att1.txt': { - data: PouchDB.utils.btoa('1'), - content_type: 'application/octet-stream' - } - }; - return db.bulkDocs([doc]); - }).then(function () { - return db.post({ - _attachments: { - 'baz.txt' : { - stub: true, - digest: 'md5-xMpCOKC5I4INzFCab3WEmw==', - content_type: 'application/octet-stream' - } - } - }).then(function () { - throw new Error('shouldn\'t have gotten here'); - }, function (err) { - err.status.should.equal(412); - }); - }); - }); - - it('#3091 atts should be ignored when _deleted - put', function () { - // now that we've established md5sum collisions, - // we can use that to detect true attachment replacement - var db = new PouchDB(dbs.name, {auto_compaction: false}); - var doc = { _id: 'doc1'}; - return db.put(doc).then(function (info) { - doc._rev = info.rev; - doc._deleted = true; - doc._attachments = { - 'att1.txt': { - data: PouchDB.utils.btoa('1'), - content_type: 'application/octet-stream' - } - }; - return db.put(doc); - }).then(function () { - return db.post({ - _attachments: { - 'baz.txt' : { - stub: true, - digest: 'md5-xMpCOKC5I4INzFCab3WEmw==', - content_type: 'application/octet-stream' - } - } - }).then(function () { - throw new Error('shouldn\'t have gotten here'); - }, function (err) { - err.status.should.equal(412); - }); - }); - }); - - // - // AUTO-COMPACTION TESTS FOLLOW - // http adapters need not apply! - // - - it('Auto-compaction test', function (done) { - var db = new PouchDB(dbs.name, {auto_compaction: true}); - var doc = {_id: 'doc', val: '1'}; - db.post(doc, function (err, res) { - var rev1 = res.rev; - doc._rev = rev1; - doc.val = '2'; - db.post(doc, function (err, res) { - var rev2 = res.rev; - doc._rev = rev2; - doc.val = '3'; - db.post(doc, function (err, res) { - var rev3 = res.rev; - db.get('doc', { rev: rev1 }, function (err, doc) { - err.status.should.equal(404, 'rev-1 should be missing'); - err.name.should.equal( - 'not_found', 'rev-1 should be missing' - ); - db.get('doc', { rev: rev2 }, function (err, doc) { - err.status.should.equal(404, 'rev-2 should be missing'); - err.name.should.equal( - 'not_found', 'rev-2 should be missing' - ); - db.get('doc', { rev: rev3 }, function (err, doc) { - done(err); - }); - }); - }); - }); - }); - }); - }); - - it('Auto-compaction removes non-leaf revs (#2807)', function () { - var db = new PouchDB(dbs.name, {auto_compaction: true}); - var doc = {_id: 'foo'}; - return db.put(doc).then(function (res) { - doc._rev = res.rev; - return getRevisions(db, 'foo'); - }).then(function (docsAndRevs) { - docsAndRevs.should.have.length(1); - return db.put(doc); - }).then(function (res) { - doc._rev = res.rev; - return getRevisions(db, 'foo'); - }).then(function (docsAndRevs) { - docsAndRevs.should.have.length(2); - should.exist(docsAndRevs[0].doc); - should.not.exist(docsAndRevs[1].doc); - }); - }); - - it('Auto-compaction removes non-leaf revs pt 2 (#2807)', function () { - var db = new PouchDB(dbs.name, {auto_compaction: true}); - var doc = {_id: 'foo'}; - return db.put(doc).then(function (res) { - doc._rev = res.rev; - return db.put(doc); - }).then(function (res) { - doc._rev = res.rev; - return db.put(doc); - }).then(function () { - return getRevisions(db, 'foo'); - }).then(function (docsAndRevs) { - docsAndRevs.should.have.length(3); - should.exist(docsAndRevs[0].doc); - should.not.exist(docsAndRevs[1].doc); - should.not.exist(docsAndRevs[2].doc); - }); - }); - - it('Auto-compaction removes non-leaf revs pt 3 (#2807)', function () { - var db = new PouchDB(dbs.name, {auto_compaction: true}); - - var docs = [ - { - _id: 'foo', - _rev: '1-a1', - _revisions: { start: 1, ids: [ 'a1' ] } - }, { - _id: 'foo', - _rev: '2-a2', - _revisions: { start: 2, ids: [ 'a2', 'a1' ] } - }, { - _id: 'foo', - _deleted: true, - _rev: '3-a3', - _revisions: { start: 3, ids: [ 'a3', 'a2', 'a1' ] } - }, { - _id: 'foo', - _rev: '1-b1', - _revisions: { start: 1, ids: [ 'b1' ] } - } - ]; - - return db.bulkDocs(docs, {new_edits: false}).then(function () { - return getRevisions(db, 'foo'); - }).then(function (docsAndRevs) { - docsAndRevs.should.have.length(4); - var asMap = {}; - docsAndRevs.forEach(function (docAndRev) { - asMap[docAndRev.rev] = docAndRev.doc; - }); - // only leafs remain - should.not.exist(asMap['1-a1']); - should.not.exist(asMap['2-a2']); - should.exist(asMap['3-a3']); - should.exist(asMap['1-b1']); - }); - }); - - it('Auto-compaction removes non-leaf revs pt 4 (#2807)', function () { - var db = new PouchDB(dbs.name, {auto_compaction: true}); - var doc = {_id: 'foo'}; - return db.put(doc).then(function (res) { - doc._rev = res.rev; - doc._deleted = true; - return db.put(doc); - }).then(function (res) { - doc._rev = res.rev; - delete doc._deleted; - return db.put(doc); - }).then(function () { - return getRevisions(db, 'foo'); - }).then(function (docsAndRevs) { - docsAndRevs.should.have.length(3); - should.exist(docsAndRevs[0].doc); - should.not.exist(docsAndRevs[1].doc); - should.not.exist(docsAndRevs[2].doc); - }); - }); - - it('Auto-compaction removes non-leaf revs pt 5 (#2807)', function () { - var db = new PouchDB(dbs.name, {auto_compaction: true}); - var doc = {_id: 'foo'}; - return db.put(doc).then(function (res) { - doc._rev = res.rev; - return db.put(doc); - }).then(function (res) { - doc._rev = res.rev; - doc._deleted = true; - return db.put(doc); - }).then(function () { - return getRevisions(db, 'foo'); - }).then(function (docsAndRevs) { - docsAndRevs.should.have.length(3); - should.exist(docsAndRevs[0].doc); - should.not.exist(docsAndRevs[1].doc); - should.not.exist(docsAndRevs[2].doc); - }); - }); - - }); -});
diff --git a/tests/integration/test.conflicts.js b/tests/integration/test.conflicts.js deleted file mode 100644 index 4cbc9f1..0000000 --- a/tests/integration/test.conflicts.js +++ /dev/null
@@ -1,492 +0,0 @@ -'use strict'; - -var adapters = ['http', 'local']; - -adapters.forEach(function (adapter) { - describe('test.conflicts.js-' + adapter, function () { - - var dbs = {}; - - beforeEach(function (done) { - dbs.name = testUtils.adapterUrl(adapter, 'testdb'); - testUtils.cleanup([dbs.name], done); - }); - - after(function (done) { - testUtils.cleanup([dbs.name], done); - }); - - - it('Testing conflicts', function (done) { - var db = new PouchDB(dbs.name); - var doc = {_id: 'foo', a: 1, b: 1}; - db.put(doc, function (err, res) { - doc._rev = res.rev; - should.exist(res.ok, 'Put first document'); - db.get('foo', function (err, doc2) { - doc._id.should.equal(doc2._id); - doc.should.have.property('_rev'); - doc2.should.have.property('_rev'); - doc.a = 2; - doc2.a = 3; - db.put(doc, function (err, res) { - should.exist(res.ok, 'Put second doc'); - db.put(doc2, function (err) { - err.name.should.equal('conflict', 'Put got a conflicts'); - db.changes({ - complete: function (err, results) { - results.results.should.have.length(1); - doc2._rev = undefined; - db.put(doc2, function (err) { - err.name.should.equal('conflict', 'Another conflict'); - done(); - }); - } - }); - }); - }); - }); - }); - }); - - it('Testing conflicts', function (done) { - var doc = {_id: 'fubar', a: 1, b: 1}; - var db = new PouchDB(dbs.name); - db.put(doc, function (err, ndoc) { - doc._rev = ndoc.rev; - db.remove(doc, function () { - delete doc._rev; - db.put(doc, function (err, ndoc) { - if (err) { - return done(err); - } - should.exist(ndoc.ok, 'written previously deleted doc without rev'); - done(); - }); - }); - }); - }); - - it('#2882/#2883 last_seq for empty db', function () { - var db = new PouchDB(dbs.name); - return db.changes().then(function (changes) { - changes.last_seq.should.equal(0); - changes.results.should.have.length(0); - return db.info(); - }).then(function (info) { - info.update_seq.should.equal(0); - }); - }); - - - it('#2882/#2883 last_seq when putting parent before leaf', function () { - var db = new PouchDB(dbs.name); - var lastSeq; - return db.bulkDocs({ - docs: [ - { - _id: 'fubar', - _rev: '2-a2', - _revisions: { start: 2, ids: [ 'a2', 'a1' ] } - }, { - _id: 'fubar', - _rev: '1-a1', - _revisions: { start: 1, ids: [ 'a1' ] } - } - ], - new_edits: false - }).then(function () { - return db.changes(); - }).then(function (changes) { - lastSeq = changes.last_seq; - changes.results[0].changes[0].rev.should.equal('2-a2'); - changes.results[0].seq.should.equal(lastSeq); - return db.info(); - }).then(function (info) { - info.update_seq.should.equal(lastSeq); - }); - }); - - // Each revision includes a list of previous revisions. The - // revision with the longest revision history list becomes the - // winning revision. If they are the same, the _rev values are - // compared in ASCII sort order, and the highest wins. So, in our - // example, 2-de0ea16f8621cbac506d23a0fbbde08a beats - // 2-7c971bb974251ae8541b8fe045964219. - - it('Conflict resolution 1', function () { - var docs = [ - { - _id: 'fubar', - _rev: '1-a', - _revisions: { - start: 1, - ids: [ 'a' ] - } - }, { - _id: 'fubar', - _rev: '1-b', - _revisions: { - start: 1, - ids: [ 'b' ] - } - }, { - _id: 'fubar', - _rev: '1-1', - _revisions: { - start: 1, - ids: [ '1' ] - } - } - ]; - var db = new PouchDB(dbs.name); - return db.bulkDocs({ docs: docs, new_edits: false }).then(function () { - return db.get('fubar'); - }).then(function (doc) { - doc._rev.should.equal('1-b', 'Correct revision wins'); - return db.bulkDocs({ - new_edits: false, - docs: [{ - _id: 'fubar', - _rev: '2-2', - _revisions: { - start: 2, - ids: [ '2', '1' ] - } - }] - }); - }).then(function (res) { - return db.get('fubar'); - }).then(function (doc) { - doc._rev.should.equal('2-2', 'Correct revision wins'); - }); - }); - - - it('Conflict resolution 2', function () { - var docs = [ - { - _id: 'fubar', - _rev: '2-a', - _revisions: { - start: 2, - ids: [ 'a' ] - } - }, { - _id: 'fubar', - _rev: '1-b', - _revisions: { - start: 1, - ids: [ 'b' ] - } - } - ]; - var db = new PouchDB(dbs.name); - return db.bulkDocs({ docs: docs, new_edits: false }).then(function () { - return db.get('fubar'); - }).then(function (doc) { - doc._rev.should.equal('2-a', 'Correct revision wins'); - return db.info(); - }).then(function (info) { - info.doc_count.should.equal(1, 'Correct number of docs'); - }); - }); - - - it('Conflict resolution 3', function () { - var docs = [ - { - _id: 'fubar', - _rev: '10-a', - _revisions: { - start: 10, - ids: [ 'a' ] - } - }, { - _id: 'fubar', - _rev: '2-b', - _revisions: { - start: 2, - ids: [ 'b' ] - } - } - ]; - var db = new PouchDB(dbs.name); - return db.bulkDocs({ docs: docs, new_edits: false }).then(function () { - return db.get('fubar'); - }).then(function (doc) { - doc._rev.should.equal('10-a', 'Correct revision wins'); - return db.info(); - }).then(function (info) { - info.doc_count.should.equal(1, 'Correct number of docs'); - }); - }); - - - it('Conflict resolution 4-a', function () { - var docs = [ - { - _id: 'fubar', - _rev: '1-a1', - _revisions: { start: 1, ids: [ 'a1' ] } - }, { - _id: 'fubar', - _rev: '2-a2', - _revisions: { start: 2, ids: [ 'a2', 'a1' ] } - }, { - _id: 'fubar', - _deleted: true, - _rev: '3-a3', - _revisions: { start: 3, ids: [ 'a3', 'a2', 'a1' ] } - }, { - _id: 'fubar', - _rev: '1-b1', - _revisions: { start: 1, ids: [ 'b1' ] } - } - ]; - var db = new PouchDB(dbs.name); - return db.bulkDocs({ docs: docs, new_edits: false }).then(function () { - return db.get('fubar'); - }).then(function (doc) { - doc._rev.should.equal('1-b1', 'Correct revision wins'); - return db.info(); - }).then(function (info) { - info.doc_count.should.equal(1, 'Correct number of docs'); - }); - }); - - it('Conflict resolution 4-b', function () { - var docs = [ - { - _id: 'fubar', - _deleted: true, - _rev: '3-a3', - _revisions: { start: 3, ids: [ 'a3', 'a2', 'a1' ] } - }, { - _id: 'fubar', - _rev: '2-a2', - _revisions: { start: 2, ids: [ 'a2', 'a1' ] } - }, { - _id: 'fubar', - _rev: '1-a1', - _revisions: { start: 1, ids: [ 'a1' ] } - }, { - _id: 'fubar', - _rev: '1-b1', - _revisions: { start: 1, ids: [ 'b1' ] } - } - ]; - var db = new PouchDB(dbs.name); - return db.bulkDocs({ docs: docs, new_edits: false }).then(function () { - return db.get('fubar'); - }).then(function (doc) { - doc._rev.should.equal('1-b1', 'Correct revision wins'); - return db.info(); - }).then(function (info) { - info.doc_count.should.equal(1, 'Correct number of docs'); - }); - }); - - it('Conflict resolution 4-c', function () { - var docs = [ - { - _id: 'fubar', - _rev: '1-a1', - _revisions: { start: 1, ids: [ 'a1' ] } - }, { - _id: 'fubar', - _rev: '1-b1', - _revisions: { start: 1, ids: [ 'b1' ] } - }, { - _id: 'fubar', - _rev: '2-a2', - _revisions: { start: 2, ids: [ 'a2', 'a1' ] } - }, { - _id: 'fubar', - _deleted: true, - _rev: '3-a3', - _revisions: { start: 3, ids: [ 'a3', 'a2', 'a1' ] } - } - ]; - var db = new PouchDB(dbs.name); - return db.bulkDocs({ docs: docs, new_edits: false }).then(function () { - return db.get('fubar'); - }).then(function (doc) { - doc._rev.should.equal('1-b1', 'Correct revision wins'); - return db.info(); - }).then(function (info) { - info.doc_count.should.equal(1, 'Correct number of docs'); - }); - }); - - it('Conflict resolution 4-d', function () { - var docs = [ - { - _id: 'fubar', - _rev: '1-a1', - _revisions: { start: 1, ids: [ 'a1' ] } - }, { - _id: 'fubar', - _rev: '1-b1', - _revisions: { start: 1, ids: [ 'b1' ] } - }, { - _id: 'fubar', - _rev: '2-a2', - _revisions: { start: 2, ids: [ 'a2', 'a1' ] } - }, { - _id: 'fubar', - _deleted: true, - _rev: '3-a3', - _revisions: { start: 3, ids: [ 'a3', 'a2', 'a1' ] } - } - ]; - var db = new PouchDB(dbs.name); - return db.bulkDocs({ docs: docs, new_edits: false }).then(function () { - return db.get('fubar'); - }).then(function (doc) { - doc._rev.should.equal('1-b1', 'Correct revision wins'); - return db.info(); - }).then(function (info) { - info.doc_count.should.equal(1, 'Correct number of docs'); - }); - }); - - it('Conflict resolution 4-e', function () { - var docs = [ - { - _id: 'fubar', - _deleted: true, - _rev: '3-a3', - _revisions: { start: 3, ids: [ 'a3', 'a2', 'a1' ] } - }, { - _id: 'fubar', - _rev: '2-a2', - _revisions: { start: 2, ids: [ 'a2', 'a1' ] } - }, { - _id: 'fubar', - _rev: '1-b1', - _revisions: { start: 1, ids: [ 'b1' ] } - }, { - _id: 'fubar', - _rev: '1-a1', - _revisions: { start: 1, ids: [ 'a1' ] } - } - ]; - var db = new PouchDB(dbs.name); - return db.bulkDocs({ docs: docs, new_edits: false }).then(function () { - return db.get('fubar'); - }).then(function (doc) { - doc._rev.should.equal('1-b1', 'Correct revision wins'); - return db.info(); - }).then(function (info) { - info.doc_count.should.equal(1, 'Correct number of docs'); - }); - }); - - it('Conflict resolution 5-a', function () { - var docs = [ - { - _id: 'fubar', - _rev: '2-a2', - _revisions: { start: 2, ids: [ 'a2', 'a1' ] } - }, { - _id: 'fubar', - _deleted: true, - _rev: '1-b1', - _revisions: { start: 1, ids: [ 'b1' ] } - }, { - _id: 'fubar', - _deleted: true, - _rev: '1-c1', - _revisions: { start: 1, ids: [ 'c1' ] } - } - ]; - var db = new PouchDB(dbs.name); - return db.bulkDocs({ docs: docs, new_edits: false }).then(function () { - return db.get('fubar'); - }).then(function (doc) { - doc._rev.should.equal('2-a2', 'Correct revision wins'); - return db.info(); - }).then(function (info) { - info.doc_count.should.equal(1, 'Correct number of docs'); - }); - }); - - it('Conflict resolution 5-b', function () { - var docs = [ - { - _id: 'fubar', - _deleted: true, - _rev: '1-b1', - _revisions: { start: 1, ids: [ 'b1' ] } - }, { - _id: 'fubar', - _rev: '2-a2', - _revisions: { start: 2, ids: [ 'a2', 'a1' ] } - }, { - _id: 'fubar', - _deleted: true, - _rev: '1-c1', - _revisions: { start: 1, ids: [ 'c1' ] } - } - ]; - var db = new PouchDB(dbs.name); - return db.bulkDocs({ docs: docs, new_edits: false }).then(function () { - return db.get('fubar'); - }).then(function (doc) { - doc._rev.should.equal('2-a2', 'Correct revision wins'); - return db.info(); - }).then(function (info) { - info.doc_count.should.equal(1, 'Correct number of docs'); - }); - }); - - it('Conflict resolution 5-c', function () { - var docs = [ - { - _id: 'fubar', - _deleted: true, - _rev: '1-b1', - _revisions: { start: 1, ids: [ 'b1' ] } - }, { - _id: 'fubar', - _deleted: true, - _rev: '1-c1', - _revisions: { start: 1, ids: [ 'c1' ] } - }, { - _id: 'fubar', - _rev: '2-a2', - _revisions: { start: 2, ids: [ 'a2', 'a1' ] } - } - ]; - var db = new PouchDB(dbs.name); - return db.bulkDocs({ docs: docs, new_edits: false }).then(function () { - return db.get('fubar'); - }).then(function (doc) { - doc._rev.should.equal('2-a2', 'Correct revision wins'); - return db.info(); - }).then(function (info) { - info.doc_count.should.equal(1, 'Correct number of docs'); - }); - }); - - it('local conflicts', function (done) { - if (testUtils.isCouchMaster()) { - return done(); - } - var db = new PouchDB(dbs.name); - return db.put({foo: 'bar'}, '_local/baz').then(function (result) { - return db.put({foo: 'bar'}, '_local/baz', result.res); - }).then(function () { - return db.put({foo: 'bar'}, '_local/baz'); - }, function (e) { - should.not.exist(e, 'shouldn\'t error yet'); - done(e); - }).then(undefined, function (e) { - should.exist(e, 'error when you have a conflict'); - done(); - }); - }); - - }); -});
diff --git a/tests/integration/test.constructor.js b/tests/integration/test.constructor.js deleted file mode 100644 index 90ef6b5..0000000 --- a/tests/integration/test.constructor.js +++ /dev/null
@@ -1,72 +0,0 @@ -'use strict'; - -describe('constructor errors', function () { - it('should error on an undefined name', function (done) { - var notAName; - new PouchDB(notAName, function (err, db) { - should.exist(err); - done(db); - }); - }); - it('should error on an undefined adapter', function (done) { - new PouchDB('foo', {adapter : 'myFakeAdapter'}, function (err, db) { - should.exist(err); - err.message.should - .equal('Adapter is missing', - 'should give the correct error message'); - done(db); - }); - }); - it('should error on a null name', function (done) { - var notAName = null; - new PouchDB(notAName).then(done, function (err) { - should.exist(err); - err.message.should - .equal('Missing/invalid DB name', - 'should give the correct error message'); - done(); - }); - }); - describe('it should always return methods', function () { - it('put', function (done) { - new PouchDB().put({ - _id: 'lala' - }, function (err, resp) { - should.exist(err); - err.message.should - .equal('Missing/invalid DB name', - 'should give the correct error message'); - done(resp); - }); - }); - it('post', function (done) { - new PouchDB().post({ - something: 'lala' - }).then(done, function (err) { - should.exist(err); - done(); - }); - }); - it('get', function (done) { - var nothing; - new PouchDB(nothing).get('something', function (err, resp) { - should.exist(err); - done(resp); - }); - }); - it('allDocs', function (done) { - new PouchDB().allDocs().then(done, function (err) { - should.exist(err); - done(); - }); - }); - it('changes', function (done) { - new PouchDB().changes({ - complete: function (err, resp) { - should.exist(err); - done(resp); - } - }); - }); - }); -});
diff --git a/tests/integration/test.defaults.js b/tests/integration/test.defaults.js deleted file mode 100644 index 8810d3f..0000000 --- a/tests/integration/test.defaults.js +++ /dev/null
@@ -1,97 +0,0 @@ -'use strict'; -if (!process.env.LEVEL_ADAPTER && - !process.env.LEVEL_PREFIX && !process.env.AUTO_COMPACTION) { - // these tests don't make sense for anything other than default leveldown - var path = require('path'); - var mkdirp = require('mkdirp'); - var rimraf = require('rimraf'); - - describe('defaults', function () { - - beforeEach(function () { - return PouchDB.destroy('mydb').then(function () { - return PouchDB.destroy('mydb', {db: require('memdown')}); - }); - }); - - afterEach(function (done) { - rimraf.sync('./tmp/_pouch_.'); - rimraf.sync('./tmp/path'); - done(); - }); - - it('should allow prefixes', function () { - var prefix = './tmp/path/to/db/1/'; - var dir = path.join(prefix, '/tmp/'); - var dir2 = path.join('./tmp/_pouch_./', prefix); - var dir3 = path.join(dir2, './tmp/_pouch_mydb'); - mkdirp.sync(dir); - mkdirp.sync(dir2); - mkdirp.sync(dir3); - - return new PouchDB('mydb', { - prefix: prefix - }).then(function (db) { - return db.info().then(function (info1) { - info1.db_name.should.equal('mydb'); - return db.destroy(); - }); - }); - }); - - it('should allow us to set a prefix by default', function () { - var prefix = './tmp/path/to/db/2/'; - var dir = path.join(prefix, '/tmp/'); - var dir2 = path.join('./tmp/_pouch_./', prefix); - var dir3 = path.join(dir2, './tmp/_pouch_mydb'); - mkdirp.sync(dir); - mkdirp.sync(dir2); - mkdirp.sync(dir3); - - var CustomPouch = PouchDB.defaults({ - prefix: prefix - }); - return new CustomPouch('mydb').then(function (db) { - return db.info().then(function (info1) { - info1.db_name.should.equal('mydb'); - return db.destroy(); - }); - }); - }); - - it('should allow us to use memdown', function () { - var opts = { name: 'mydb', db: require('memdown') }; - return new PouchDB(opts).then(function (db) { - return db.put({_id: 'foo'}).then(function () { - return new PouchDB('mydb').then(function (otherDB) { - return db.info().then(function (info1) { - return otherDB.info().then(function (info2) { - info1.doc_count.should.not.equal(info2.doc_count); - return otherDB.destroy(); - }).then(function () { - return db.destroy(); - }); - }); - }); - }); - }); - }); - it('should allow us to use memdown by default', function () { - var CustomPouch = PouchDB.defaults({db: require('memdown')}); - return new CustomPouch('mydb').then(function (db) { - return db.put({_id: 'foo'}).then(function () { - return new PouchDB('mydb').then(function (otherDB) { - return db.info().then(function (info1) { - return otherDB.info().then(function (info2) { - info1.doc_count.should.not.equal(info2.doc_count); - return otherDB.destroy(); - }).then(function () { - return db.destroy(); - }); - }); - }); - }); - }); - }); - }); -}
diff --git a/tests/integration/test.design_docs.js b/tests/integration/test.design_docs.js deleted file mode 100644 index 7af9c36..0000000 --- a/tests/integration/test.design_docs.js +++ /dev/null
@@ -1,123 +0,0 @@ -'use strict'; - -var adapters = ['http', 'local']; - -adapters.forEach(function (adapter) { - describe('test.design_docs.js-' + adapter, function () { - - var dbs = {}; - - beforeEach(function (done) { - dbs.name = testUtils.adapterUrl(adapter, 'testdb'); - testUtils.cleanup([dbs.name], done); - }); - - after(function (done) { - testUtils.cleanup([dbs.name], done); - }); - - - var doc = { - _id: '_design/foo', - views: { - scores: { - map: 'function (doc) { if (doc.score) { emit(null, doc.score); } }', - reduce: 'function (keys, values, rereduce) { return sum(values); }' - } - }, - filters: { even: 'function (doc) { return doc.integer % 2 === 0; }' } - }; - - it('Test writing design doc', function (done) { - var db = new PouchDB(dbs.name); - db.post(doc, function (err, info) { - should.not.exist(err, 'Wrote design doc'); - db.get('_design/foo', function (err, info) { - done(err); - }); - }); - }); - - it('Changes filter', function (done) { - var docs1 = [ - doc, - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - {_id: '2', integer: 2}, - {_id: '3', integer: 3} - ]; - var docs2 = [ - {_id: '4', integer: 4}, - {_id: '5', integer: 5}, - {_id: '6', integer: 6}, - {_id: '7', integer: 7} - ]; - - var db = new PouchDB(dbs.name); - var count = 0; - db.bulkDocs({ docs: docs1 }, function (err, info) { - var changes = db.changes({ - live: true, - filter: 'foo/even', - onChange: function (change) { - count += 1; - if (count === 4) { - changes.cancel(); - } - }, - complete: function (err, result) { - result.status.should.equal('cancelled'); - done(); - }, - - }); - db.bulkDocs({ docs: docs2 }, {}); - }); - }); - - it('Basic views', function (done) { - var docs1 = [ - doc, - {_id: 'dale', score: 3}, - {_id: 'mikeal', score: 5}, - {_id: 'max', score: 4}, - {_id: 'nuno', score: 3} - ]; - var db = new PouchDB(dbs.name); - db.bulkDocs({ docs: docs1 }, function (err, info) { - db.query('foo/scores', { reduce: false }, function (err, result) { - result.rows.should.have.length(4, 'Correct # of results'); - db.query('foo/scores', function (err, result) { - result.rows[0].value.should.equal(15, 'Reduce gave correct result'); - done(); - }); - }); - }); - }); - - it('Concurrent queries', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs({ - docs: [ - doc, - {_id: 'dale', score: 3} - ] - }, function (err, info) { - var cnt = 0; - db.query('foo/scores', { reduce: false }, function (err, result) { - result.rows.should.have.length(1, 'Correct # of results'); - if (++cnt === 2) { - done(); - } - }); - db.query('foo/scores', { reduce: false }, function (err, result) { - result.rows.should.have.length(1, 'Correct # of results'); - if (++cnt === 2) { - done(); - } - }); - }); - }); - - }); -});
diff --git a/tests/integration/test.events.js b/tests/integration/test.events.js deleted file mode 100644 index 63eaec3..0000000 --- a/tests/integration/test.events.js +++ /dev/null
@@ -1,131 +0,0 @@ -'use strict'; - -var adapters = ['local']; - -adapters.forEach(function (adapter) { - describe('test.events.js-' + adapter, function () { - - var dbs = {}; - beforeEach(function (done) { - dbs.name = testUtils.adapterUrl(adapter, 'testdb'); - testUtils.cleanup([dbs.name], done); - }); - - after(function (done) { - testUtils.cleanup([dbs.name], done); - }); - - - it('PouchDB emits creation event', function (done) { - PouchDB.once('created', function (name) { - name.should.equal(dbs.name, 'should be same thing'); - done(); - }); - new PouchDB(dbs.name); - }); - - it('PouchDB emits destruction event', function (done) { - new PouchDB(dbs.name, function () { - PouchDB.destroy(dbs.name); - }).once('destroyed', function () { - new PouchDB(dbs.name, function () { - done(); - }); - }); - }); - - it('PouchDB emits destruction event on PouchDB object', function (done) { - PouchDB.once('destroyed', function (name) { - name.should.equal(dbs.name, 'should have the same name'); - new PouchDB(dbs.name, function () { - done(); - }); - }); - new PouchDB(dbs.name, function () { - PouchDB.destroy(dbs.name); - }); - }); - - it('emit creation event', function (done) { - var db = new PouchDB(dbs.name).on('created', function (newDB) { - db.should.equal(newDB, 'should be same thing'); - done(); - }); - }); - - it('emit changes event', function (done) { - new PouchDB(dbs.name, function (err, db) { - var id = 'emiting'; - var obj = { - something: 'here', - somethingElse: 'overHere' - }; - db.on('change', function (change) { - change.seq.should.equal(1, 'changed'); - change.id.should.equal('emiting'); - done(err); - }); - db.put(obj, id); - }); - }); - - it('emit create event', function (done) { - new PouchDB(dbs.name, function (err, db) { - var id = 'creating'; - var obj = { - something: 'here', - somethingElse: 'overHere' - }; - db.on('create', function (change) { - change.id.should.equal('creating'); - change.seq.should.equal(1, 'created'); - done(err); - }); - db.put(obj, id); - }); - }); - - it('emit update event', function (done) { - new PouchDB(dbs.name, function (err, db) { - var id = 'updating'; - var obj = { - something: 'here', - somethingElse: 'overHere' - }; - db.on('update', function (change) { - change.id.should.equal('updating'); - change.seq.should.equal(2, 'seq 2, updated'); - done(err); - }); - - db.put(obj, id).then(function (doc) { - db.put({'something': 'else'}, id, doc.rev); - }); - - }); - }); - - it('emit delete event', function (done) { - new PouchDB(dbs.name, function (err, db) { - var id = 'emiting'; - var obj = { - something: 'here', - somethingElse: 'overHere' - }; - db.on('delete', function (change) { - change.seq.should.equal(2, 'deleted'); - change.id.should.equal('emiting'); - done(err); - }); - - db.put(obj, id).then(function (doc) { - db.remove({ - _id: id, - _rev: doc.rev - }); - }); - }); - }); - - }); -});
diff --git a/tests/integration/test.get.js b/tests/integration/test.get.js deleted file mode 100644 index e3b2253..0000000 --- a/tests/integration/test.get.js +++ /dev/null
@@ -1,721 +0,0 @@ -'use strict'; - -var adapters = ['http', 'local']; - -adapters.forEach(function (adapter) { - describe('test.get.js-' + adapter, function () { - - var dbs = {}; - - beforeEach(function (done) { - dbs.name = testUtils.adapterUrl(adapter, 'testdb'); - testUtils.cleanup([dbs.name], done); - }); - - after(function (done) { - testUtils.cleanup([dbs.name], done); - }); - - - var origDocs = [ - {_id: '0', a: 1, b: 1}, - {_id: '3', a: 4, b: 16}, - {_id: '1', a: 2, b: 4}, - {_id: '2', a: 3, b: 9} - ]; - - function writeDocs(db, docs, callback) { - if (!docs.length) { - return callback(); - } - var doc = docs.shift(); - db.put(doc, function (err, doc) { - should.exist(doc.ok); - writeDocs(db, docs, callback); - }); - } - - it('Get doc', function (done) { - var db = new PouchDB(dbs.name); - db.post({ test: 'somestuff' }, function (err, info) { - db.get(info.id, function (err, doc) { - doc.should.have.property('test'); - db.get(info.id + 'asdf', function (err) { - err.should.have.property('name'); - done(); - }); - }); - }); - }); - - it('Get design doc', function (done) { - var db = new PouchDB(dbs.name); - db.put({ - _id: '_design/someid', - test: 'somestuff' - }, function (err, info) { - db.get(info.id, function (err, doc) { - db.get(info.id + 'asdf', function (err) { - err.should.have.property('name'); - done(); - }); - }); - }); - }); - - it('Check error of deleted document', function (done) { - var db = new PouchDB(dbs.name); - db.post({ test: 'somestuff' }, function (err, info) { - db.remove({ - _id: info.id, - _rev: info.rev - }, function (err, res) { - db.get(info.id, function (err, res) { - err.name.should.equal('not_found'); - err.message.should.equal('deleted'); - done(); - }); - }); - }); - }); - - it('Get local_seq of document', function (done) { - var db = new PouchDB(dbs.name); - db.post({ test: 'somestuff' }, function (err, info1) { - db.get(info1.id, { local_seq: true }, function (err, res) { - res._local_seq.should.equal(1); - db.post({ test: 'someotherstuff' }, function (err, info2) { - db.get(info2.id, { local_seq: true }, function (err, res) { - res._local_seq.should.equal(2); - done(); - }); - }); - }); - }); - }); - - it('Get revisions of removed doc', function (done) { - var db = new PouchDB(dbs.name, {auto_compaction: false}); - db.post({ test: 'somestuff' }, function (err, info) { - var rev = info.rev; - db.remove({ - test: 'somestuff', - _id: info.id, - _rev: info.rev - }, function (doc) { - db.get(info.id, { rev: rev }, function (err, doc) { - should.not.exist(err); - done(); - }); - }); - }); - }); - - it('Testing get with rev', function (done) { - new PouchDB(dbs.name, function (err, db) { - writeDocs(db, JSON.parse(JSON.stringify(origDocs)), function () { - db.get('3', function (err, parent) { - // add conflicts - var pRevId = parent._rev.split('-')[1]; - var conflicts = [ - { - _id: '3', - _rev: '2-aaa', - value: 'x', - _revisions: { - start: 2, - ids: [ - 'aaa', - pRevId - ] - } - }, - { - _id: '3', - _rev: '3-bbb', - value: 'y', - _deleted: true, - _revisions: { - start: 3, - ids: [ - 'bbb', - 'some', - pRevId - ] - } - }, - { - _id: '3', - _rev: '4-ccc', - value: 'z', - _revisions: { - start: 4, - ids: [ - 'ccc', - 'even', - 'more', - pRevId - ] - } - } - ]; - db.put(conflicts[0], { new_edits: false }, function (err, doc) { - db.put(conflicts[1], { new_edits: false }, function (err, doc) { - db.put(conflicts[2], { new_edits: false }, function (err, doc) { - db.get('3', { rev: '2-aaa' }, function (err, doc) { - doc._rev.should.equal('2-aaa'); - doc.value.should.equal('x'); - db.get('3', { rev: '3-bbb' }, function (err, doc) { - doc._rev.should.equal('3-bbb'); - doc.value.should.equal('y'); - db.get('3', { rev: '4-ccc' }, function (err, doc) { - doc._rev.should.equal('4-ccc'); - doc.value.should.equal('z'); - done(); - }); - }); - }); - }); - }); - }); - }); - }); - }); - }); - - it('Testing rev format', function (done) { - var revs = []; - var db = new PouchDB(dbs.name); - db.post({ test: 'somestuff' }, function (err, info) { - revs.unshift(info.rev.split('-')[1]); - db.put({ - _id: info.id, - _rev: info.rev, - another: 'test1' - }, function (err, info2) { - revs.unshift(info2.rev.split('-')[1]); - db.put({ - _id: info.id, - _rev: info2.rev, - last: 'test2' - }, function (err, info3) { - revs.unshift(info3.rev.split('-')[1]); - db.get(info.id, { revs: true }, function (err, doc) { - doc._revisions.start.should.equal(3); - revs.should.deep.equal(doc._revisions.ids); - done(); - }); - }); - }); - }); - }); - - it('Test opts.revs=true with rev other than winning', function (done) { - var db = new PouchDB(dbs.name, {auto_compaction: false}); - var docs = [ - {_id: 'foo', _rev: '1-a', value: 'foo a'}, - {_id: 'foo', _rev: '2-b', value: 'foo b'}, - {_id: 'foo', _rev: '3-c', value: 'foo c'}, - {_id: 'foo', _rev: '4-d', value: 'foo d'} - ]; - testUtils.putBranch(db, docs, function () { - db.get('foo', { - rev: '3-c', - revs: true - }, function (err, doc) { - doc._revisions.ids.length.should.equal(3, 'correct revisions length'); - doc._revisions.start.should.equal(3, 'correct revisions start'); - doc._revisions.ids[0].should.equal('c', 'correct rev'); - doc._revisions.ids[1].should.equal('b', 'correct rev'); - doc._revisions.ids[2].should.equal('a', 'correct rev'); - done(); - }); - }); - }); - - it('Test opts.revs=true return only winning branch', function (done) { - var db = new PouchDB(dbs.name); - var simpleTree = [ - [{_id: 'foo', _rev: '1-a', value: 'foo a'}, - {_id: 'foo', _rev: '2-b', value: 'foo b'}, - {_id: 'foo', _rev: '3-c', value: 'foo c'}], - [{_id: 'foo', _rev: '1-a', value: 'foo a'}, - {_id: 'foo', _rev: '2-d', value: 'foo d'}, - {_id: 'foo', _rev: '3-e', value: 'foo e'}, - {_id: 'foo', _rev: '4-f', value: 'foo f'} - ] - ]; - testUtils.putTree(db, simpleTree, function () { - db.get('foo', { revs: true }, function (err, doc) { - doc._revisions.ids.length.should.equal(4, 'correct revisions length'); - doc._revisions.start.should.equal(4, 'correct revisions start'); - doc._revisions.ids[0].should.equal('f', 'correct rev'); - doc._revisions.ids[1].should.equal('e', 'correct rev'); - doc._revisions.ids[2].should.equal('d', 'correct rev'); - doc._revisions.ids[3].should.equal('a', 'correct rev'); - done(); - }); - }); - }); - - it('Test get with simple revs_info', function (done) { - var db = new PouchDB(dbs.name); - db.post({ test: 'somestuff' }, function (err, info) { - db.put({ - _id: info.id, - _rev: info.rev, - another: 'test' - }, function (err, info) { - db.put({ - _id: info.id, - _rev: info.rev, - a: 'change' - }, function (err, info2) { - db.get(info.id, { revs_info: true }, function (err, doc) { - doc._revs_info.length.should.equal(3, 'updated a doc with put'); - done(); - }); - }); - }); - }); - }); - - it('Test get with revs_info on tree', function (done) { - var db = new PouchDB(dbs.name); - var simpleTree = [ - [{_id: 'foo', _rev: '1-a', value: 'foo a'}, - {_id: 'foo', _rev: '2-b', value: 'foo b'}, - {_id: 'foo', _rev: '3-c', value: 'foo c'}], - [{_id: 'foo', _rev: '1-a', value: 'foo a'}, - {_id: 'foo', _rev: '2-d', value: 'foo d'}, - {_id: 'foo', _rev: '3-e', _deleted: true}] - ]; - testUtils.putTree(db, simpleTree, function () { - db.get('foo', { revs_info: true }, function (err, doc) { - var revs = doc._revs_info; - revs.length.should.equal(3, 'correct number of revs'); - revs[0].rev.should.equal('3-c', 'rev ok'); - revs[1].rev.should.equal('2-b', 'rev ok'); - revs[2].rev.should.equal('1-a', 'rev ok'); - done(); - }); - }); - }); - - it('Test get with revs_info on compacted tree', function (done) { - var db = new PouchDB(dbs.name); - var simpleTree = [ - [ - { - _id: 'foo', - _rev: '1-a', - value: 'foo a' - }, - { - _id: 'foo', - _rev: '2-b', - value: 'foo d' - }, - { - _id: 'foo', - _rev: '3-c', - value: 'foo c' - } - ], - [ - { - _id: 'foo', - _rev: '1-a', - value: 'foo a' - }, - { - _id: 'foo', - _rev: '2-d', - value: 'foo d' - }, - { - _id: 'foo', - _rev: '3-e', - _deleted: true - } - ] - ]; - testUtils.putTree(db, simpleTree, function () { - db.compact(function (err, ok) { - db.get('foo', { revs_info: true }, function (err, doc) { - var revs = doc._revs_info; - revs.length.should.equal(3, 'correct number of revs'); - revs[0].rev.should.equal('3-c', 'rev ok'); - revs[0].status.should.equal('available', 'not compacted'); - revs[1].rev.should.equal('2-b', 'rev ok'); - revs[1].status.should.equal('missing', 'compacted'); - revs[2].rev.should.equal('1-a', 'rev ok'); - revs[2].status.should.equal('missing', 'compacted'); - done(); - }); - }); - }); - }); - - it('#2951 Parallelized gets with 409s/404s', function () { - var db = new PouchDB(dbs.name); - - var numSimultaneous = 20; - var numDups = 3; - - var tasks = []; - - for (var i = 0; i < numSimultaneous; i++) { - var key = Math.random().toString(); - for (var j = 0; j < numDups; j++) { - tasks.push(key); - } - } - - function getDocWithDefault(db, id, defaultDoc) { - return db.get(id).catch(function (err) { - /* istanbul ignore if */ - if (err.status !== 404) { - throw err; - } - defaultDoc._id = id; - return db.put(defaultDoc).catch(function (err) { - /* istanbul ignore if */ - if (err.status !== 409) { // conflict - throw err; - } - }).then(function () { - return db.get(id); - }); - }); - } - - return PouchDB.utils.Promise.all(tasks.map(function (task) { - return getDocWithDefault(db, task, {foo: 'bar'}); - })); - }); - - it('#2951 Parallelized _local gets with 409s/404s', function () { - var db = new PouchDB(dbs.name); - - var numSimultaneous = 20; - var numDups = 3; - - var tasks = []; - - for (var i = 0; i < numSimultaneous; i++) { - var key = Math.random().toString(); - for (var j = 0; j < numDups; j++) { - tasks.push('_local/' + key); - } - } - - function getDocWithDefault(db, id, defaultDoc) { - return db.get(id).catch(function (err) { - /* istanbul ignore if */ - if (err.status !== 404) { - throw err; - } - defaultDoc._id = id; - return db.put(defaultDoc).catch(function (err) { - /* istanbul ignore if */ - if (err.status !== 409) { // conflict - throw err; - } - }).then(function () { - return db.get(id); - }); - }); - } - - return PouchDB.utils.Promise.all(tasks.map(function (task) { - return getDocWithDefault(db, task, {foo: 'bar'}); - })); - }); - - it('Test get with conflicts', function (done) { - var db = new PouchDB(dbs.name); - var simpleTree = [ - [ - { - _id: 'foo', - _rev: '1-a', - value: 'foo a' - }, - { - _id: 'foo', - _rev: '2-b', - value: 'foo b' - } - ], - [ - { - _id: 'foo', - _rev: '1-a', - value: 'foo a' - }, - { - _id: 'foo', - _rev: '2-c', - value: 'foo c' - } - ], - [ - { - _id: 'foo', - _rev: '1-a', - value: 'foo a' - }, - { - _id: 'foo', - _rev: '2-d', - value: 'foo d', - _deleted: true - } - ] - ]; - testUtils.putTree(db, simpleTree, function () { - db.get('foo', { conflicts: true }, function (err, doc) { - doc._rev.should.equal('2-c', 'correct rev'); - doc._conflicts.length.should.equal(1, 'just one conflict'); - doc._conflicts[0].should.equal('2-b', 'just one conflict'); - done(); - }); - }); - }); - - it('Retrieve old revision', function (done) { - var db = new PouchDB(dbs.name, {auto_compaction: false}); - db.post({ version: 'first' }, function (err, info) { - db.put({ - _id: info.id, - _rev: info.rev, - version: 'second' - }, function (err, info2) { - should.not.exist(err); - db.get(info.id, { rev: info.rev }, function (err, oldRev) { - oldRev.version.should.equal('first', 'Fetched old revision'); - db.get(info.id, { rev: '1-nonexistentRev' }, function (err, doc) { - should.exist(err, 'Non existent row error correctly reported'); - done(); - }); - }); - }); - }); - }); - - it('Testing get open_revs="all"', function (done) { - var db = new PouchDB(dbs.name); - writeDocs(db, JSON.parse(JSON.stringify(origDocs)), function () { - db.get('3', function (err, parent) { - // add conflicts - var previd = parent._rev.split('-')[1]; - var conflicts = [ - { - _id: '3', - _rev: '2-aaa', - value: 'x', - _revisions: { - start: 2, - ids: [ - 'aaa', - previd - ] - } - }, - { - _id: '3', - _rev: '3-bbb', - value: 'y', - _deleted: true, - _revisions: { - start: 3, - ids: [ - 'bbb', - 'some', - previd - ] - } - }, - { - _id: '3', - _rev: '4-ccc', - value: 'z', - _revisions: { - start: 4, - ids: [ - 'ccc', - 'even', - 'more', - previd - ] - } - } - ]; - db.put(conflicts[0], { new_edits: false }, function (err, doc) { - db.put(conflicts[1], { new_edits: false }, function (err, doc) { - db.put(conflicts[2], { new_edits: false }, function (err, doc) { - db.get('3', { open_revs: 'all' }, function (err, res) { - var i; - res = res.map(function (row) { - return row.ok; - }); - res.sort(function (a, b) { - return a._rev === b._rev ? 0 : a._rev < b._rev ? -1 : 1; - }); - res.length.should.equal(conflicts.length); - for (i = 0; i < conflicts.length; i++) { - conflicts[i]._rev.should.equal(res[i]._rev, 'correct rev'); - } - done(); - }); - }); - }); - }); - }); - }); - }); - - it('Testing get with some open_revs', function (done) { - var db = new PouchDB(dbs.name); - writeDocs(db, JSON.parse(JSON.stringify(origDocs)), function () { - db.get('3', function (err, parent) { - // add conflicts - var previd = parent._rev.split('-')[1]; - var conflicts = [ - { - _id: '3', - _rev: '2-aaa', - value: 'x', - _revisions: { - start: 2, - ids: [ - 'aaa', - previd - ] - } - }, - { - _id: '3', - _rev: '3-bbb', - value: 'y', - _deleted: true, - _revisions: { - start: 3, - ids: [ - 'bbb', - 'some', - previd - ] - } - }, - { - _id: '3', - _rev: '4-ccc', - value: 'z', - _revisions: { - start: 4, - ids: [ - 'ccc', - 'even', - 'more', - previd - ] - } - } - ]; - db.put(conflicts[0], { new_edits: false }, function (err, doc) { - db.put(conflicts[1], { new_edits: false }, function (err, doc) { - db.put(conflicts[2], { new_edits: false }, function (err, doc) { - db.get('3', { - open_revs: [ - '2-aaa', - '5-nonexistent', - '3-bbb' - ] - }, function (err, res) { - res.sort(function (a, b) { - if (a.ok) { - if (b.ok) { - var x = a.ok._rev, y = b.ok._rev; - return x === y ? 0 : x < y ? -1 : 1; - } else { - return -1; - } - } - return 1; - }); - res.length.should.equal(3, 'correct number of open_revs'); - res[0].ok._rev.should.equal('2-aaa', 'ok'); - res[1].ok._rev.should.equal('3-bbb', 'ok'); - res[2].missing.should.equal('5-nonexistent', 'ok'); - done(); - }); - }); - }); - }); - }); - }); - }); - - it('Testing get with open_revs and revs', function (done) { - var db = new PouchDB(dbs.name); - var docs = [ - [{_id: 'foo', _rev: '1-a', value: 'foo a'}, - {_id: 'foo', _rev: '2-b', value: 'foo b'} - ], - [{_id: 'foo', _rev: '1-a', value: 'foo a'}, - {_id: 'foo', _rev: '2-c', value: 'foo c'}] - ]; - testUtils.putTree(db, docs, function () { - db.get('foo', { - open_revs: ['2-b'], - revs: true - }, function (err, res) { - var doc = res[0].ok; - doc._revisions.ids.length.should.equal(2, 'got two revs'); - doc._revisions.ids[0].should.equal('b', 'got correct rev'); - done(); - }); - }); - }); - - it('Testing get with open_revs on nonexistent doc', function (done) { - var db = new PouchDB(dbs.name); - db.get('nonexistent', { open_revs: ['2-whatever'] }, function (err, res) { - res.length.should.equal(1, 'just one result'); - res[0].missing.should.equal('2-whatever', 'just one result'); - db.get('nonexistent', { open_revs: 'all' }, function (err, res) { - res.length.should.equal(0, 'no open revisions'); - done(); - }); - }); - }); - - it('Testing get with open_revs with wrong params', function (done) { - var db = new PouchDB(dbs.name); - db.put({ _id: 'foo' }, function (err, res) { - db.get('foo', { - open_revs: { - 'whatever': 'which is', - 'not an array': 'or all string' - } - }, function (err, res) { - err.name.should.equal('unknown_error', 'correct error'); - // unfortunately! - db.get('foo', { - open_revs: [ - '1-almost', - '2-correct', - 'keys' - ] - }, function (err, res) { - err.name.should.equal('bad_request', 'correct error'); - done(); - }); - }); - }); - }); - - }); -});
diff --git a/tests/integration/test.http.js b/tests/integration/test.http.js deleted file mode 100644 index 5835c77..0000000 --- a/tests/integration/test.http.js +++ /dev/null
@@ -1,73 +0,0 @@ -'use strict'; - -describe('test.http.js', function () { - - var dbs = {}; - - beforeEach(function (done) { - dbs.name = testUtils.adapterUrl('http', 'test_http'); - testUtils.cleanup([dbs.name], done); - }); - - after(function (done) { - testUtils.cleanup([dbs.name], done); - }); - - - it('Create a pouch without DB setup', function (done) { - var instantDB; - testUtils.isCouchDB(function (isCouchDB) { - if (!isCouchDB) { - return done(); - } - PouchDB.destroy(dbs.name, function () { - instantDB = new PouchDB(dbs.name, { skipSetup: true }); - instantDB.post({ test: 'abc' }, function (err, info) { - should.exist(err); - err.name.should.equal('not_found', 'Skipped setup of database'); - done(); - }); - }); - }); - }); - - it('Issue 1269 redundant _changes requests', function (done) { - var docs = []; - var num = 100; - for (var i = 0; i < num; i++) { - docs.push({ - _id: 'doc_' + i, - foo: 'bar_' + i - }); - } - var db = new PouchDB(dbs.name); - db.bulkDocs({ docs: docs }, function (err, result) { - var callCount = 0; - var ajax = PouchDB.utils.ajax; - PouchDB.utils.ajax = function (opts) { - if (/_changes/.test(opts.url)) { - callCount++; - } - ajax.apply(this, arguments); - }; - db.changes({ - since: 100, - onChange: function (change) { }, - complete: function (err, result) { - callCount.should.equal(1, 'One _changes call to complete changes'); - PouchDB.utils.ajax = ajax; - done(); - } - }); - }); - }); - - it('#2853 test uri parsing usernames/passwords', function () { - var uri = PouchDB.utils.parseUri( - 'http://u%24ern%40me:p%26%24%24w%40rd@foo.com'); - uri.password.should.equal('p&$$w@rd'); - uri.user.should.equal('u$ern@me'); - uri.host.should.equal('foo.com'); - }); - -});
diff --git a/tests/integration/test.issue1175.js b/tests/integration/test.issue1175.js deleted file mode 100644 index 72d6570..0000000 --- a/tests/integration/test.issue1175.js +++ /dev/null
@@ -1,98 +0,0 @@ -'use strict'; -function MockDatabase(statusCodeToReturn, dataToReturn) { - this.once = this.removeListener = function () {}; - this.type = function () { return 'mock'; }; - this.id = function (callback) { - if (callback) { - callback(123); - } else { - return PouchDB.utils.Promise.resolve(123); - } - }; - this.get = function (id, callback) { - return new PouchDB.utils.Promise(function (fulfill, reject) { - setTimeout(function () { - if (statusCodeToReturn !== 200) { - reject({ status: statusCodeToReturn }); - } else { - fulfill(dataToReturn); - } - }, 0); - }); - }; - this.changes = function (opts) { - if (opts.complete) { - opts.complete(null, {results: []}); - } - var promise = PouchDB.utils.Promise.resolve({results: []}); - promise.on = function () { return this; }; - return promise; - }; - this.put = function () { - return PouchDB.utils.Promise.resolve(); - }; -} -function getCallback(expectError, done) { - // returns a function which expects to be called within a certain time. - // Fails the test otherwise - var maximumTimeToWait = 500; - var hasBeenCalled = false; - var result; - var err; - function callback(error, resp) { - hasBeenCalled = true; - result = resp; - err = error; - } - function timeOutCallback() { - hasBeenCalled.should.equal(true, 'callback has been called'); - if (!expectError) { - should.not.exist(err, 'error expectation fulfilled'); - } - done(); - } - setTimeout(timeOutCallback, maximumTimeToWait); - return callback; -} -describe('replication-http-errors:', function () { - it('Initial replication is ok if source returns HTTP 404', function (done) { - var source = new MockDatabase(404, null); - var target = new MockDatabase(200, {}); - PouchDB.replicate(source, target, {}, getCallback(false, done)); - }); - it('Initial replication is ok if target returns HTTP 404', function (done) { - var source = new MockDatabase(200, {}); - var target = new MockDatabase(404, null); - PouchDB.replicate(source, target, {}, getCallback(false, done)); - }); - it('Initial replication is ok if source and target return HTTP 200', - function (done) { - var source = new MockDatabase(200, {}); - var target = new MockDatabase(200, {}); - PouchDB.replicate(source, target, {}, getCallback(false, done)); - }); - it('Initial replication returns err if source returns HTTP 500', - function (done) { - var source = new MockDatabase(500, null); - var target = new MockDatabase(200, {}); - PouchDB.replicate(source, target, {}, getCallback(true, done)); - }); - it('Initial replication returns err if target returns HTTP 500', - function (done) { - var source = new MockDatabase(200, {}); - var target = new MockDatabase(500, null); - PouchDB.replicate(source, target, {}, getCallback(true, done)); - }); - it('Initial replication returns err if target and source return HTTP 500', - function (done) { - var source = new MockDatabase(500, null); - var target = new MockDatabase(500, null); - PouchDB.replicate(source, target, {}, getCallback(true, done)); - }); - it('Subsequent replication returns err if source return HTTP 500', - function (done) { - var source = new MockDatabase(500, null); - var target = new MockDatabase(200, { last_seq: 456 }); - PouchDB.replicate(source, target, {}, getCallback(true, done)); - }); -});
diff --git a/tests/integration/test.issue221.js b/tests/integration/test.issue221.js deleted file mode 100644 index 5f655c6..0000000 --- a/tests/integration/test.issue221.js +++ /dev/null
@@ -1,84 +0,0 @@ -'use strict'; - -var adapters = [ - ['local', 'http'], - ['http', 'http'], - ['http', 'local'], - ['local', 'local'] -]; - -adapters.forEach(function (adapters) { - describe('test.issue221.js-' + adapters[0] + '-' + adapters[1], function () { - - var dbs = {}; - - beforeEach(function (done) { - dbs.name = testUtils.adapterUrl(adapters[0], 'testdb'); - dbs.remote = testUtils.adapterUrl(adapters[1], 'test_repl_remote'); - testUtils.cleanup([dbs.name, dbs.remote], done); - }); - - after(function (done) { - testUtils.cleanup([dbs.name, dbs.remote], done); - }); - - var doc = {_id: '0', integer: 0}; - - it('Testing issue #221', function (done) { - var local = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - // Write a doc in CouchDB. - remote.put(doc, function (err, results) { - // Update the doc. - doc._rev = results.rev; - doc.integer = 1; - remote.put(doc, function (err, results) { - // Compact the db. - remote.compact(function () { - remote.get(doc._id, { revs_info: true }, function (err, data) { - var correctRev = data._revs_info[0]; - local.replicate.from(remote, function (err, results) { - // Check the Pouch doc. - local.get(doc._id, function (err, results) { - results._rev.should.equal(correctRev.rev); - results.integer.should.equal(1); - done(); - }); - }); - }); - }); - }); - }); - }); - - it('Testing issue #221 again', function (done) { - if (testUtils.isCouchMaster()) { - return done(); - } - var local = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - // Write a doc in CouchDB. - remote.put(doc, function (err, results) { - doc._rev = results.rev; - // Second doc so we get 2 revisions from replicate. - remote.put(doc, function (err, results) { - doc._rev = results.rev; - local.replicate.from(remote, function (err, results) { - doc.integer = 1; - // One more change - remote.put(doc, function (err, results) { - // Testing if second replications fails now - local.replicate.from(remote, function (err, results) { - local.get(doc._id, function (err, results) { - results.integer.should.equal(1); - done(); - }); - }); - }); - }); - }); - }); - }); - - }); -});
diff --git a/tests/integration/test.issue915.js b/tests/integration/test.issue915.js deleted file mode 100644 index 992b837..0000000 --- a/tests/integration/test.issue915.js +++ /dev/null
@@ -1,37 +0,0 @@ -'use strict'; -if (!process.env.LEVEL_ADAPTER && - !process.env.LEVEL_PREFIX && !process.env.AUTO_COMPACTION) { - // these tests don't make sense for anything other than default leveldown - var fs = require('fs'); - describe('Remove DB', function () { - afterEach(function (done) { - fs.unlink('./tmp/_pouch_veryimportantfiles/something', function () { - fs.rmdir('./tmp/_pouch_veryimportantfiles/', function () { - done(); - }); - }); - }); - it('Put a file in the db, then destroy it', function (done) { - new PouchDB('veryimportantfiles', function (err, db) { - fs.writeFile('./tmp/_pouch_veryimportantfiles/something', - new Buffer('lalala'), function (err) { - db.destroy(function (err) { - if (err) { - return done(err); - } - fs.readFile('./tmp/_pouch_veryimportantfiles/something', - {encoding: 'utf8'}, function (err, resp) { - if (err) { - return done(err); - } - resp.should - .equal('lalala', - './tmp/veryimportantfiles/something was not removed'); - done(); - }); - }); - }); - }); - }); - }); -}
diff --git a/tests/integration/test.local_docs.js b/tests/integration/test.local_docs.js deleted file mode 100644 index 42cc818..0000000 --- a/tests/integration/test.local_docs.js +++ /dev/null
@@ -1,215 +0,0 @@ -'use strict'; - -var adapters = ['http', 'local']; - -adapters.forEach(function (adapter) { - describe('test.local_docs.js-' + adapter, function () { - - var dbs = {}; - - beforeEach(function (done) { - dbs.name = testUtils.adapterUrl(adapter, 'testdb'); - testUtils.cleanup([dbs.name], done); - }); - - after(function (done) { - testUtils.cleanup([dbs.name], done); - }); - - it('local docs - put then get', function () { - var db = new PouchDB(dbs.name); - return db.put({_id: '_local/foo'}).then(function (res) { - res.id.should.equal('_local/foo'); - res.rev.should.be.a('string'); - res.ok.should.equal(true); - return db.get('_local/foo'); - }); - }); - - it('local docs - put then get w/ revisions', function () { - var db = new PouchDB(dbs.name); - var doc = { - _id: '_local/foo' - }; - return db.put(doc).then(function (res) { - res.id.should.equal('_local/foo'); - res.rev.should.be.a('string'); - res.ok.should.equal(true); - return db.get('_local/foo'); - }).then(function (doc) { - should.not.exist(doc._revisions); - doc._revisions = {start: 0, ids: ['1']}; - return db.put(doc); - }).then(function () { - return db.get('_local/foo'); - }).then(function (doc) { - should.not.exist(doc._revisions); - }); - }); - - it('local docs - put then remove then get', function () { - var db = new PouchDB(dbs.name); - var doc = {_id: '_local/foo'}; - return db.put(doc).then(function (res) { - doc._rev = res.rev; - return db.remove(doc); - }).then(function (res) { - res.id.should.equal('_local/foo'); - res.rev.should.equal('0-0'); - res.ok.should.equal(true); - return db.get('_local/foo').then(function (doc) { - should.not.exist(doc); - }).catch(function (err) { - err.name.should.equal('not_found'); - }); - }); - }); - - it('local docs - put after remove', function () { - var db = new PouchDB(dbs.name); - var doc = {_id: '_local/foo'}; - return db.put(doc).then(function (res) { - doc._rev = res.rev; - return db.remove(doc); - }).then(function (res) { - res.id.should.equal('_local/foo'); - res.rev.should.equal('0-0'); - res.ok.should.equal(true); - delete doc._rev; - return db.put(doc); - }); - }); - - it('local docs - put after remove, check return vals', function () { - // as long as it starts with 0-, couch - // treats it as a new local doc - var db = new PouchDB(dbs.name); - var doc = {_id: '_local/quux'}; - return db.put(doc).then(function (res) { - res.rev.should.equal('0-1'); - res.ok.should.equal(true); - doc._rev = res.rev; - return db.put(doc); - }).then(function (res) { - res.rev.should.equal('0-2'); - res.ok.should.equal(true); - doc._rev = res.rev; - return db.put(doc); - }).then(function (res) { - res.rev.should.equal('0-3'); - res.ok.should.equal(true); - }); - }); - - it('local docs - remove missing', function () { - var db = new PouchDB(dbs.name); - return db.remove({ - _id: '_local/foo', - _rev: '1-fake' - }).then(function () { - throw new Error('should not be here'); - }, function (err) { - err.name.should.be.a('string'); - }); - }); - - it('local docs - put after put w/ deleted:true', function () { - var db = new PouchDB(dbs.name); - var doc = {_id: '_local/foo'}; - return db.put(doc).then(function (res) { - doc._rev = res.rev; - doc._deleted = true; - return db.put(doc); - }).then(function (res) { - res.id.should.equal('_local/foo'); - res.rev.should.equal('0-0'); - res.ok.should.equal(true); - delete doc._deleted; - delete doc._rev; - return db.put(doc); - }); - }); - - it('local docs - put after remove with a rev', function () { - var db = new PouchDB(dbs.name); - var doc = {_id: '_local/foo'}; - return db.put(doc).then(function (res) { - doc._rev = res.rev; - return db.remove(doc); - }).then(function (res) { - res.id.should.equal('_local/foo'); - res.ok.should.equal(true); - res.rev.should.equal('0-0'); - delete doc._rev; - return db.put(doc); - }); - }); - - it('local docs - multiple removes', function () { - var db = new PouchDB(dbs.name); - var doc = {_id: '_local/foo'}; - return db.put(doc).then(function (res) { - doc._rev = res.rev; - return db.put(doc); - }).then(function (res) { - doc._rev = res.rev; - return db.remove(doc); - }).then(function (res) { - res.rev.should.equal('0-0'); - delete doc._rev; - return db.put(doc); - }).then(function (res) { - doc._rev = res.rev; - return db.remove(doc); - }).then(function (res) { - res.rev.should.equal('0-0'); - }); - }); - - it('local docs - get unknown', function () { - var db = new PouchDB(dbs.name); - return db.get('_local/foo').then(function (doc) { - should.not.exist(doc); - }).catch(function (err) { - err.name.should.equal('not_found'); - }); - }); - - it('local docs - put unknown', function () { - var db = new PouchDB(dbs.name); - var doc = {_id: '_local/foo', _rev: '1-fake'}; - return db.put(doc).then(function (res) { - should.not.exist(res); - }).catch(function (err) { - err.name.should.be.a('string'); - }); - }); - - it('local docs - put new and conflicting', function () { - var db = new PouchDB(dbs.name); - var doc = {_id: '_local/foo'}; - return db.put(doc).then(function () { - return db.put(doc); - }).then(function (res) { - should.not.exist(res); - }).catch(function (err) { - err.name.should.be.a('string'); - }); - }); - - it('local docs - put modified and conflicting', function () { - var db = new PouchDB(dbs.name); - var doc = {_id: '_local/foo'}; - return db.put(doc).then(function (res) { - doc._rev = res.rev; - return db.put(doc); - }).then(function () { - return db.put(doc); - }).then(function (res) { - should.not.exist(res); - }).catch(function (err) { - err.name.should.be.a('string'); - }); - }); - }); -});
diff --git a/tests/integration/test.migration.js b/tests/integration/test.migration.js deleted file mode 100644 index 670021a..0000000 --- a/tests/integration/test.migration.js +++ /dev/null
@@ -1,87 +0,0 @@ -'use strict'; -if (!process.env.LEVEL_ADAPTER && - !process.env.LEVEL_PREFIX && !process.env.AUTO_COMPACTION) { - // these tests don't make sense for anything other than default leveldown - var fs = require('fs'); - var ncp = require('ncp').ncp; - - ncp.limit = 16; - - describe('migration one', function () { - beforeEach(function (done) { - var input = - fs.createReadStream('./tests/integration/leveldb/oldStyle.uuid'); - input.on('end', function () { - ncp('./tests/integration/leveldb/oldStyle', - './tmp/_pouch_oldStyle', done); - }); - input.pipe(fs.createWriteStream('./tmp/_pouch_oldStyle.uuid')); - }); - it('should work', function () { - return new PouchDB('oldStyle').then(function (db) { - return db.get('doc').then(function (doc) { - doc.something.should.equal('awesome'); - return db.destroy(); - }); - }); - }); - }); - describe('migration two', function () { - beforeEach(function (done) { - ncp('./tests/integration/leveldb/middleStyle', - './tmp/_pouch_middleStyle', done); - }); - it('should work', function () { - return new PouchDB('middleStyle').then(function (db) { - db.id().then(function (id) { - id.should.equal('8E049E64-784A-3209-8DD6-97C29D7A5868'); - return db.get('_local/foo'); - }).then(function (resp) { - resp.something.should.equal('else'); - return db.allDocs(); - }).then(function (resp) { - resp.total_rows.should.equal(1); - resp.rows[0].id.should.equal('_design/foo'); - return db.destroy(); - }); - }); - }); - }); - - // sanity check to ensure we don't actually need to migrate - // attachments for #2818 - describe('#2818 no migration needed for attachments', function () { - beforeEach(function (done) { - ncp('./tests/integration/leveldb/lateStyle', - './tmp/_pouch_lateStyle', done); - }); - it('should work', function () { - return new PouchDB('lateStyle', { - auto_compaction: false - }).then(function (db) { - return db.put({ - _id: 'doc_b', - _attachments: { - 'att.txt': { - data: 'Zm9v', // 'foo' - content_type: 'text/plain' - } - } - }).then(function () { - return db.get('doc_b'); - }).then(function (doc) { - return db.remove(doc); - }).then(function () { - return db.compact(); - }).then(function () { - return db.get('doc_a', {attachments: true}); - }).then(function (doc) { - doc._attachments['att.txt'].data.should.equal('Zm9vYmFy'); - doc._attachments['att2.txt'].data.should.equal('Zm9vYmFy'); - doc._attachments['att3.txt'].data.should.equal('Zm9v'); - return db.destroy(); - }); - }); - }); - }); -}
diff --git a/tests/integration/test.replication.js b/tests/integration/test.replication.js deleted file mode 100644 index d514584..0000000 --- a/tests/integration/test.replication.js +++ /dev/null
@@ -1,2747 +0,0 @@ -'use strict'; - -var adapters = [ - ['local', 'http'], - ['http', 'http'], - ['http', 'local'], - ['local', 'local'] -]; - -if ('saucelabs' in testUtils.params()) { - adapters = [['local', 'http'], ['http', 'local']]; -} - -var downAdapters = ['local']; - -adapters.forEach(function (adapters) { - describe('test.replication.js-' + adapters[0] + '-' + adapters[1], - function () { - - var dbs = {}; - - beforeEach(function (done) { - dbs.name = testUtils.adapterUrl(adapters[0], 'testdb'); - dbs.remote = testUtils.adapterUrl(adapters[1], 'test_repl_remote'); - testUtils.cleanup([dbs.name, dbs.remote], done); - }); - - after(function (done) { - testUtils.cleanup([dbs.name, dbs.remote], done); - }); - - - var docs = [ - {_id: '0', integer: 0, string: '0'}, - {_id: '1', integer: 1, string: '1'}, - {_id: '2', integer: 2, string: '2'} - ]; - - it('Test basic pull replication', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - remote.bulkDocs({ docs: docs }, {}, function (err, results) { - db.replicate.from(dbs.remote, function (err, result) { - result.ok.should.equal(true); - result.docs_written.should.equal(docs.length); - db.info(function (err, info) { - info.update_seq.should.equal(3, 'update_seq'); - info.doc_count.should.equal(3, 'doc_count'); - done(); - }); - }); - }); - }); - - it('Test basic pull replication plain api', function (done) { - var remote = new PouchDB(dbs.remote); - remote.bulkDocs({ docs: docs }, {}, function (err, results) { - PouchDB.replicate(dbs.remote, dbs.name, {}, function (err, result) { - result.ok.should.equal(true); - result.docs_written.should.equal(docs.length); - new PouchDB(dbs.name).info(function (err, info) { - info.update_seq.should.equal(3, 'update_seq'); - info.doc_count.should.equal(3, 'doc_count'); - done(); - }); - }); - }); - }); - - it('Test basic pull replication plain api 2', function (done) { - var remote = new PouchDB(dbs.remote); - remote.bulkDocs({ docs: docs }, {}, function (err, results) { - PouchDB.replicate(dbs.remote, dbs.name, { - complete: function (err, result) { - result.ok.should.equal(true); - result.docs_written.should.equal(docs.length); - new PouchDB(dbs.name).info(function (err, info) { - info.update_seq.should.equal(3, 'update_seq'); - info.doc_count.should.equal(3, 'doc_count'); - done(); - }); - } - }); - }); - }); - - it('Test pull replication with many changes', function (done) { - var remote = new PouchDB(dbs.remote); - - var numDocs = 201; - var docs = []; - for (var i = 0; i < numDocs; i++) { - docs.push({_id: i.toString()}); - } - - remote.bulkDocs({ docs: docs }, {}, function (err) { - should.not.exist(err); - PouchDB.replicate(dbs.remote, dbs.name, { - complete: function (err, result) { - result.ok.should.equal(true); - result.docs_written.should.equal(docs.length); - new PouchDB(dbs.name).info(function (err, info) { - info.update_seq.should.equal(numDocs, 'update_seq'); - info.doc_count.should.equal(numDocs, 'doc_count'); - done(); - }); - } - }); - }); - }); - - it('Test basic pull replication with funny ids', function (done) { - var docs = [ - {_id: '4/5', integer: 0, string: '0'}, - {_id: '3&2', integer: 1, string: '1'}, - {_id: '1>0', integer: 2, string: '2'} - ]; - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - remote.bulkDocs({docs: docs}, function (err, results) { - db.replicate.from(dbs.remote, function (err, result) { - result.ok.should.equal(true); - result.docs_written.should.equal(docs.length); - db.info(function (err, info) { - info.update_seq.should.equal(3, 'update_seq'); - info.doc_count.should.equal(3, 'doc_count'); - done(); - }); - }); - }); - }); - - it('pull replication with many changes + a conflict (#2543)', function () { - var db = new PouchDB(dbs.remote); - var remote = new PouchDB(dbs.remote); - // simulate 5000 normal commits with two conflicts at the very end - function uuid() { - return PouchDB.utils.uuid(32, 16).toLowerCase(); - } - - var numRevs = 5000; - var isSafari = (typeof process === 'undefined' || process.browser) && - /Safari/.test(window.navigator.userAgent) && - !/Chrome/.test(window.navigator.userAgent); - if (isSafari) { - numRevs = 10; // fuck safari, we've hit the storage limit again - } - - var uuids = []; - for (var i = 0; i < numRevs - 1; i++) { - uuids.push(uuid()); - } - var conflict1 = 'a' + uuid(); - var conflict2 = 'b' + uuid(); - - var doc1 = { - _id: 'doc', - _rev: numRevs + '-' + conflict1, - _revisions: { - start: numRevs, - ids: [conflict1].concat(uuids) - } - }; - var doc2 = { - _id: 'doc', - _rev: numRevs + '-' + conflict2, - _revisions: { - start: numRevs, - ids: [conflict2].concat(uuids) - } - }; - return remote.bulkDocs([doc1], {new_edits: false}).then(function () { - return remote.replicate.to(db); - }).then(function (result) { - result.ok.should.equal(true); - result.docs_written.should.equal(0, 'correct # docs written (1)'); - return db.info(); - }).then(function (info) { - info.doc_count.should.equal(1, 'doc_count'); - return db.get('doc', {open_revs: "all"}); - }).then(function (doc) { - doc.should.deep.equal([{"ok": {"_id": "doc", "_rev": doc1._rev}}]); - return remote.bulkDocs([doc2], {new_edits: false}); - }).then(function () { - return remote.replicate.to(db); - }).then(function (result) { - result.ok.should.equal(true); - result.docs_written.should.equal(0, 'correct # docs written (2)'); - return db.info(); - }).then(function (info) { - info.doc_count.should.equal(1, 'doc_count'); - return db.get('doc', {open_revs: "all"}); - }).then(function (docs) { - // order with open_revs is unspecified - docs.sort(function (a, b) { - return a.ok._rev < b.ok._rev ? -1 : 1; - }); - docs.should.deep.equal([ - {"ok": {"_id": "doc", "_rev": doc1._rev}}, - {"ok": {"_id": "doc", "_rev": doc2._rev}} - ]); - }); - }); - - it('issue 2779, undeletion when replicating', function () { - if (testUtils.isCouchMaster()) { - return true; - } - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var rev; - - function checkNumRevisions(num) { - return db.get('foo', { - open_revs: 'all', - revs: true - }).then(function (fullDocs) { - fullDocs[0].ok._revisions.ids.should.have.length(num, - 'local is correct'); - }).then(function () { - return remote.get('foo', { - open_revs: 'all', - revs: true - }); - }).then(function (fullDocs) { - fullDocs[0].ok._revisions.ids.should.have.length(num, - 'remote is correct'); - }); - } - - return db.put({_id: 'foo'}).then(function (resp) { - rev = resp.rev; - return db.replicate.to(remote); - }).then(function () { - return checkNumRevisions(1); - }).then(function () { - return db.remove('foo', rev); - }).then(function () { - return db.replicate.to(remote); - }).then(function () { - return checkNumRevisions(2); - }).then(function () { - return db.allDocs({keys: ['foo']}); - }).then(function (res) { - rev = res.rows[0].value.rev; - return db.put({_id: 'foo', _rev: rev}); - }).then(function () { - return db.replicate.to(remote); - }).then(function () { - return checkNumRevisions(3); - }); - }); - - it('Test pull replication with many conflicts', function (done) { - var remote = new PouchDB(dbs.remote); - - var numRevs = 200; // repro "url too long" error with open_revs - var docs = []; - for (var i = 0; i < numRevs; i++) { - var rev = '1-' + PouchDB.utils.uuid(32, 16).toLowerCase(); - docs.push({_id: 'doc', _rev: rev}); - } - - remote.bulkDocs({ docs: docs }, {new_edits: false}, function (err) { - should.not.exist(err); - PouchDB.replicate(dbs.remote, dbs.name, { - complete: function (err, result) { - result.ok.should.equal(true); - result.docs_written.should.equal(docs.length); - var db = new PouchDB(dbs.name); - db.info(function (err, info) { - should.not.exist(err); - info.doc_count.should.equal(1, 'doc_count'); - db.get('doc', {open_revs: "all"}, function (err, docs) { - should.not.exist(err); - var okDocs = docs.filter(function (doc) { return doc.ok; }); - okDocs.should.have.length(numRevs); - done(); - }); - }); - } - }); - }); - }); - - it('Test correct # docs replicated with staggered revs', function (done) { - // ensure we don't just process all the open_revs with - // every replication; we should only process the current subset - var remote = new PouchDB(dbs.remote); - - var docs = [{_id: 'doc', _rev: '1-a'}, {_id: 'doc', _rev: '1-b'}]; - remote.bulkDocs({ docs: docs }, {new_edits: false}, function (err) { - should.not.exist(err); - PouchDB.replicate(dbs.remote, dbs.name, { - complete: function (err, result) { - result.ok.should.equal(true); - result.docs_written.should.equal(2); - result.docs_read.should.equal(2); - var docs = [{_id: 'doc', _rev: '1-c'}, {_id: 'doc', _rev: '1-d'}]; - remote.bulkDocs({ docs: docs }, {new_edits: false}, function (err) { - should.not.exist(err); - PouchDB.replicate(dbs.remote, dbs.name, { - complete: function (err, result) { - result.docs_written.should.equal(2); - result.docs_read.should.equal(2); - var db = new PouchDB(dbs.name); - db.info(function (err, info) { - should.not.exist(err); - info.doc_count.should.equal(1, 'doc_count'); - db.get('doc', {open_revs: "all"}, function (err, docs) { - should.not.exist(err); - var okDocs = docs.filter(function (doc) { - return doc.ok; - }); - okDocs.should.have.length(4); - done(); - }); - }); - } - }); - }); - } - }); - }); - }); - - it('Local DB contains documents', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - remote.bulkDocs({ docs: docs }, {}, function (err, _) { - db.bulkDocs({ docs: docs }, {}, function (err, _) { - db.replicate.from(dbs.remote, function (err, _) { - db.allDocs(function (err, result) { - result.rows.length.should.equal(docs.length); - db.info(function (err, info) { - info.update_seq.should.be.above(2, 'update_seq local'); - info.doc_count.should.equal(3, 'doc_count local'); - remote.info(function (err, info) { - info.update_seq.should.be.above(2, 'update_seq remote'); - info.doc_count.should.equal(3, 'doc_count remote'); - done(); - }); - }); - }); - }); - }); - }); - }); - - it('Test basic push replication', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs({ docs: docs }, {}, function (err, results) { - db.replicate.to(dbs.remote, function (err, result) { - result.ok.should.equal(true); - result.docs_written.should.equal(docs.length); - db.info(function (err, info) { - info.update_seq.should.equal(3); - info.doc_count.should.equal(3); - done(); - }); - }); - }); - }); - - it('Test basic push replication take 2', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - db.bulkDocs({ docs: docs }, {}, function (err, _) { - db.replicate.to(dbs.remote, function (err, _) { - remote.allDocs(function (err, result) { - result.rows.length.should.equal(docs.length); - db.info(function (err, info) { - info.update_seq.should.equal(3); - info.doc_count.should.equal(3); - done(); - }); - }); - }); - }); - }); - - it('Test basic push replication sequence tracking', function (done) { - var db = new PouchDB(dbs.name); - var doc1 = {_id: 'adoc', foo: 'bar'}; - db.put(doc1, function (err, result) { - db.replicate.to(dbs.remote, function (err, result) { - result.docs_read.should.equal(1); - db.replicate.to(dbs.remote, function (err, result) { - result.docs_read.should.equal(0); - db.replicate.to(dbs.remote, function (err, result) { - result.docs_read.should.equal(0); - db.info(function (err, info) { - info.update_seq.should.equal(1); - info.doc_count.should.equal(1); - done(); - }); - }); - }); - }); - }); - }); - - it('Test checkpoint', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - remote.bulkDocs({ docs: docs }, {}, function (err, results) { - db.replicate.from(dbs.remote, function (err, result) { - result.ok.should.equal(true); - result.docs_written.should.equal(docs.length); - db.replicate.from(dbs.remote, function (err, result) { - result.ok.should.equal(true); - result.docs_written.should.equal(0); - result.docs_read.should.equal(0); - db.info(function (err, info) { - info.update_seq.should.equal(3); - info.doc_count.should.equal(3); - done(); - }); - }); - }); - }); - }); - - it('Test live pull checkpoint', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - remote.bulkDocs({ docs: docs }, {}, function (err, results) { - var changeCount = docs.length; - var changes = db.changes({ - live: true, - onChange: function (change) { - if (--changeCount) { - return; - } - replication.cancel(); - changes.cancel(); - }, - complete: function () { - db.replicate.from(dbs.remote, { - complete: function (err, details) { - details.docs_read.should.equal(0); - db.info(function (err, info) { - info.update_seq.should.equal(3); - info.doc_count.should.equal(3); - done(); - }); - } - }); - } - }); - var replication = db.replicate.from(dbs.remote, { live: true }); - }); - }); - - it('Test live push checkpoint', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - db.bulkDocs({ docs: docs }, {}, function (err, results) { - var changeCount = docs.length; - var finished = 0; - var isFinished = function () { - if (++finished !== 2) { - return; - } - db.replicate.to(dbs.remote, { - complete: function (err, details) { - details.docs_read.should.equal(0); - db.info(function (err, info) { - info.update_seq.should.equal(3); - info.doc_count.should.equal(3); - done(); - }); - } - }); - }; - var changes = remote.changes({ - live: true, - onChange: function (change) { - if (--changeCount) { - return; - } - replication.cancel(); - changes.cancel(); - }, - complete: isFinished - }); - var replication = db.replicate.to(dbs.remote, { - live: true, - complete: isFinished - }); - }); - }); - - it('Test checkpoint 2', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var doc = {_id: '3', count: 0}; - remote.put(doc, {}, function (err, results) { - db.replicate.from(dbs.remote, function (err, result) { - result.ok.should.equal(true); - doc._rev = results.rev; - doc.count++; - remote.put(doc, {}, function (err, results) { - doc._rev = results.rev; - doc.count++; - remote.put(doc, {}, function (err, results) { - db.replicate.from(dbs.remote, function (err, result) { - result.ok.should.equal(true); - result.docs_written.should.equal(1); - db.info(function (err, info) { - info.update_seq.should.equal(2); - info.doc_count.should.equal(1); - done(); - }); - }); - }); - }); - }); - }); - }); - - it('Test checkpoint 3 :)', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var doc = {_id: '3', count: 0}; - db.put(doc, {}, function (err, results) { - PouchDB.replicate(db, remote, {}, function (err, result) { - result.ok.should.equal(true); - doc._rev = results.rev; - doc.count++; - db.put(doc, {}, function (err, results) { - doc._rev = results.rev; - doc.count++; - db.put(doc, {}, function (err, results) { - PouchDB.replicate(db, remote, {}, function (err, result) { - result.ok.should.equal(true); - result.docs_written.should.equal(1); - db.info(function (err, info) { - info.update_seq.should.equal(3); - info.doc_count.should.equal(1); - done(); - }); - }); - }); - }); - }); - }); - }); - - it('Test checkpoint read only 3 :)', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var put = function (doc) { - return db.bulkDocs({docs: [doc]}).then(function (resp) { - return resp[0]; - }); - }; - var err = { - "message": "_writer access is required for this request", - "name": "unauthorized", - "status": 401 - }; - db.put = function () { - if (typeof arguments[arguments.length - 1] === 'function') { - arguments[arguments.length - 1](err); - } else { - return PouchDB.utils.Promise.reject(err); - } - }; - var doc = {_id: '3', count: 0}; - put(doc).then(function (results) { - return PouchDB.replicate(db, remote).then(function (result) { - result.ok.should.equal(true); - doc._rev = results.rev; - doc.count++; - return put(doc); - }); - }).then(function (results) { - doc._rev = results.rev; - doc.count++; - return put(doc); - }).then(function () { - return PouchDB.replicate(db, remote); - }).then(function (result) { - result.ok.should.equal(true); - result.docs_written.should.equal(1); - db.info(function (err, info) { - info.update_seq.should.equal(3); - info.doc_count.should.equal(1); - done(); - }); - }, function (a) { - done(JSON.stringify(a, false, 4)); - }); - }); - - it('Testing allDocs with some conflicts (issue #468)', function (done) { - var db1 = new PouchDB(dbs.name); - var db2 = new PouchDB(dbs.remote); - // we indeed needed replication to create failing test here! - var doc = {_id: 'foo', _rev: '1-a', value: 'generic'}; - db1.put(doc, { new_edits: false }, function (err, res) { - db2.put(doc, { new_edits: false }, function (err, res) { - testUtils.putAfter(db2, { - _id: 'foo', - _rev: '2-b', - value: 'db2' - }, '1-a', function (err, res) { - testUtils.putAfter(db1, { - _id: 'foo', - _rev: '2-c', - value: 'whatever' - }, '1-a', function (err, res) { - testUtils.putAfter(db1, { - _id: 'foo', - _rev: '3-c', - value: 'db1' - }, '2-c', function (err, res) { - db1.get('foo', function (err, doc) { - doc.value.should.equal('db1'); - db2.get('foo', function (err, doc) { - doc.value.should.equal('db2'); - PouchDB.replicate(db1, db2, function () { - PouchDB.replicate(db2, db1, function () { - db1.get('foo', function (err, doc) { - doc.value.should.equal('db1'); - db2.get('foo', function (err, doc) { - doc.value.should.equal('db1'); - db1.allDocs({ include_docs: true }, - function (err, res) { - res.rows.should.have.length.above(0, 'first'); - // redundant but we want to test it - res.rows[0].doc.value.should.equal('db1'); - db2.allDocs({ include_docs: true }, - function (err, res) { - res.rows.should.have.length.above(0, 'second'); - res.rows[0].doc.value.should.equal('db1'); - db1.info(function (err, info) { - // if auto_compaction is enabled, will - // be 5 because 2-c goes "missing" and - // the other db tries to re-put it - info.update_seq.should.be.within(4, 5); - info.doc_count.should.equal(1); - db2.info(function (err, info2) { - info2.update_seq.should.equal(3); - info2.doc_count.should.equal(1); - done(); - }); - }); - }); - }); - }); - }); - }); - }); - }); - }); - }); - }); - }); - }); - }); - }); - - // CouchDB will not generate a conflict here, it uses a deteministic - // method to generate the revision number, however we cannot copy its - // method as it depends on erlangs internal data representation - it('Test basic conflict', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var doc1 = {_id: 'adoc', foo: 'bar'}; - var doc2 = {_id: 'adoc', bar: 'baz'}; - db.put(doc1, function (err, localres) { - remote.put(doc2, function (err, remoteres) { - db.replicate.to(dbs.remote, function (err, _) { - remote.get('adoc', { conflicts: true }, function (err, result) { - result.should.have.property('_conflicts'); - db.info(function (err, info) { - info.update_seq.should.equal(1); - info.doc_count.should.equal(1); - done(); - }); - }); - }); - }); - }); - }); - - it('Test _conflicts key', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var doc1 = {_id: 'adoc', foo: 'bar'}; - var doc2 = {_id: 'adoc', bar: 'baz'}; - db.put(doc1, function (err, localres) { - remote.put(doc2, function (err, remoteres) { - db.replicate.to(dbs.remote, function (err, _) { - var queryFun = { - map: function (doc) { - if (doc._conflicts) { - emit(doc._id, [doc._rev].concat(doc._conflicts)); - } - } - }; - remote.query(queryFun, { - reduce: false, - conflicts: true - }, function (_, res) { - res.rows.length.should.equal(1); - db.info(function (err, info) { - info.update_seq.should.equal(1); - info.doc_count.should.equal(1); - done(); - }); - }); - }); - }); - }); - }); - - it('Test basic live pull replication', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var doc1 = {_id: 'adoc', foo: 'bar'}; - remote.bulkDocs({ docs: docs }, {}, function (err, results) { - var count = 0; - var finished = 0; - var isFinished = function () { - if (++finished !== 2) { - return; - } - db.info(function (err, info) { - info.update_seq.should.equal(4); - info.doc_count.should.equal(4); - done(); - }); - }; - var rep = db.replicate.from(dbs.remote, { - live: true, - complete: isFinished - }); - var changes = db.changes({ - onChange: function (change) { - ++count; - if (count === 3) { - return remote.put(doc1); - } - if (count === 4) { - rep.cancel(); - changes.cancel(); - } - }, - live: true, - complete: isFinished - }); - }); - }); - - it('Test basic live push replication', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var doc1 = {_id: 'adoc', foo: 'bar'}; - db.bulkDocs({ docs: docs }, {}, function (err, results) { - var count = 0; - var finished = 0; - var isFinished = function () { - if (++finished !== 2) { - return; - } - db.info(function (err, info) { - info.update_seq.should.equal(4); - info.doc_count.should.equal(4); - done(); - }); - }; - var rep = remote.replicate.from(db, { - live: true, - complete: isFinished - }); - var changes = remote.changes({ - onChange: function (change) { - ++count; - if (count === 3) { - return db.put(doc1); - } - if (count === 4) { - rep.cancel(); - changes.cancel(); - } - }, - live: true, - complete: isFinished - }); - }); - }); - - it('test-cancel-pull-replication', function (done) { - new PouchDB(dbs.remote, function (err, remote) { - var db = new PouchDB(dbs.name); - var docs = [ - {_id: '0', integer: 0, string: '0'}, - {_id: '1', integer: 1, string: '1'}, - {_id: '2', integer: 2, string: '2'} - ]; - var doc1 = {_id: 'adoc', foo: 'bar' }; - var doc2 = {_id: 'anotherdoc', foo: 'baz'}; - remote.bulkDocs({ docs: docs }, {}, function (err, results) { - var count = 0; - var replicate = db.replicate.from(remote, { - live: true, - complete: function () { - remote.put(doc2); - setTimeout(function () { - changes.cancel(); - }, 100); - } - }); - var changes = db.changes({ - live: true, - complete: function (err, reason) { - count.should.equal(4); - db.info(function (err, info) { - info.update_seq.should.equal(4); - info.doc_count.should.equal(4); - done(); - }); - }, - onChange: function (change) { - ++count; - if (count === 3) { - remote.put(doc1); - } - if (count === 4) { - replicate.cancel(); - } - } - }); - }); - }); - }); - - it('Test basic events', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs({ docs: docs }).then(function () { - db.replicate.to(dbs.remote) - .on('complete', function (res) { - should.exist(res); - db.replicate.to('http://0.0.0.0:0') - .on('error', function (res) { - should.exist(res); - done(); - }); - }); - }); - }); - - it('Replication filter', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var docs1 = [ - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - {_id: '2', integer: 2}, - {_id: '3', integer: 3} - ]; - remote.bulkDocs({ docs: docs1 }, function (err, info) { - db.replicate.from(remote, { - complete: function (err, res) { - if (err) { - done(err); - } - db.allDocs(function (err, docs) { - if (err) { done(err); } - docs.rows.length.should.equal(2); - db.info(function (err, info) { - info.update_seq.should.equal(2); - info.doc_count.should.equal(2); - done(); - }); - }); - }, - filter: function (doc) { - return doc.integer % 2 === 0; - } - }); - }); - }); - - it('Replication with different filters', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var more_docs = [ - {_id: '3', integer: 3, string: '3'}, - {_id: '4', integer: 4, string: '4'} - ]; - remote.bulkDocs({ docs: docs }, function (err, info) { - db.replicate.from(remote, { - filter: function (doc) { - return doc.integer % 2 === 0; - } - }, function (err, response) { - remote.bulkDocs({ docs: more_docs }, function (err, info) { - db.replicate.from(remote, {}, function (err, response) { - response.docs_written.should.equal(3); - db.info(function (err, info) { - info.update_seq.should.equal(5); - info.doc_count.should.equal(5); - done(); - }); - }); - }); - }); - }); - }); - - it('Replication doc ids', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var thedocs = [ - {_id: '3', integer: 3, string: '3'}, - {_id: '4', integer: 4, string: '4'}, - {_id: '5', integer: 5, string: '5'} - ]; - remote.bulkDocs({ docs: thedocs }, function (err, info) { - db.replicate.from(remote, { - doc_ids: ['3', '4'] - }, function (err, response) { - response.docs_written.should.equal(2); - db.info(function (err, info) { - info.update_seq.should.equal(2); - info.doc_count.should.equal(2); - done(); - }); - }); - }); - }); - - it('Replication since', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var thedocs = [ - {_id: '1', integer: 1, string: '1'}, - {_id: '2', integer: 2, string: '2'}, - {_id: '3', integer: 3, string: '3'}, - {_id: '4', integer: 4, string: '4'}, - {_id: '5', integer: 5, string: '5'} - ]; - remote.bulkDocs({ docs: thedocs }, function (err, info) { - db.replicate.from(remote, { - since: 3, - complete: function (err, result) { - should.not.exist(err); - result.docs_written.should.equal(2); - db.replicate.from(remote, { - since: 0, - complete: function (err, result) { - should.not.exist(err); - result.docs_written.should.equal(3); - db.info(function (err, info) { - info.update_seq.should.equal(5); - info.doc_count.should.equal(5); - done(); - }); - } - }); - } - }); - }); - }); - - it('Replication with same filters', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var more_docs = [ - {_id: '3', integer: 3, string: '3'}, - {_id: '4', integer: 4, string: '4'} - ]; - remote.bulkDocs({ docs: docs }, function (err, info) { - db.replicate.from(remote, { - filter: function (doc) { - return doc.integer % 2 === 0; - } - }, function (err, response) { - remote.bulkDocs({ docs: more_docs }, function (err, info) { - db.replicate.from(remote, { - filter: function (doc) { - return doc.integer % 2 === 0; - } - }, function (err, response) { - response.docs_written.should.equal(1); - db.info(function (err, info) { - info.update_seq.should.equal(3); - info.doc_count.should.equal(3); - done(); - }); - }); - }); - }); - }); - }); - - it('Replication with filter that leads to some empty batches (#2689)', - function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var docs1 = [ - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - {_id: '2', integer: 1}, - {_id: '3', integer: 1}, - {_id: '4', integer: 2}, - {_id: '5', integer: 2} - ]; - remote.bulkDocs({ docs: docs1 }, function (err, info) { - db.replicate.from(remote, { - batch_size: 2, - complete: function (err, res) { - if (err) { - done(err); - } - db.allDocs(function (err, docs) { - if (err) { done(err); } - docs.rows.length.should.equal(3); - db.info(function (err, info) { - info.update_seq.should.equal(3); - info.doc_count.should.equal(3); - done(); - }); - }); - }, - filter: function (doc) { - return doc.integer % 2 === 0; - } - }); - }); - }); - - it('Replication with deleted doc', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var docs1 = [ - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - {_id: '2', integer: 2}, - {_id: '3', integer: 3}, - {_id: '4', integer: 4, _deleted: true} - ]; - remote.bulkDocs({ docs: docs1 }, function (err, info) { - db.replicate.from(remote, function () { - db.allDocs(function (err, res) { - res.total_rows.should.equal(4); - db.info(function (err, info) { - info.update_seq.should.equal(5); - info.doc_count.should.equal(4); - done(); - }); - }); - }); - }); - }); - - it('Replication with doc deleted twice', function (done) { - if (testUtils.isCouchMaster()) { - return done(); - } - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - remote.bulkDocs({ docs: docs }).then(function (info) { - return remote.get('0'); - }).then(function (doc) { - return remote.remove(doc); - }).then(function () { - return db.replicate.from(remote); - }).then(function () { - return db.allDocs(); - }).then(function (res) { - res.total_rows.should.equal(2); - return remote.allDocs({ keys: [ '0' ] }); - }).then(function (res) { - var row = res.rows[0]; - should.not.exist(row.error); - // set rev to latest so we go at the end (otherwise new - // rev is 1 and the subsequent remove below won't win) - var doc = { - _id: '0', - integer: 10, - string: '10', - _rev: row.value.rev - }; - return remote.put(doc); - }).then(function () { - return remote.get('0'); - }).then(function (doc) { - return remote.remove(doc); - }).then(function () { - return db.replicate.from(remote); - }).then(function () { - return db.allDocs(); - }).then(function (res) { - res.total_rows.should.equal(2); - db.info(function (err, info) { - info.update_seq.should.equal(4); - info.doc_count.should.equal(2); - done(); - }); - }).catch(function (err) { - done(JSON.stringify(err, false, 4)); - }); - }); - - it('Replication notifications', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var changes = 0; - var onChange = function (c) { - changes++; - if (changes === 3) { - db.info(function (err, info) { - info.update_seq.should.equal(3); - info.doc_count.should.equal(3); - done(); - }); - } - }; - remote.bulkDocs({ docs: docs }, {}, function (err, results) { - db.replicate.from(dbs.remote, { onChange: onChange }); - }); - }); - - it('Replication with remote conflict', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var doc = {_id: 'test', test: 'Remote 1'}, winningRev; - remote.post(doc, function (err, resp) { - doc._rev = resp.rev; - PouchDB.replicate(remote, db, function (err, resp) { - doc.test = 'Local 1'; - db.put(doc, function (err, resp) { - doc.test = 'Remote 2'; - remote.put(doc, function (err, resp) { - doc._rev = resp.rev; - doc.test = 'Remote 3'; - remote.put(doc, function (err, resp) { - winningRev = resp.rev; - PouchDB.replicate(db, remote, function (err, resp) { - PouchDB.replicate(remote, db, function (err, resp) { - remote.get('test', { revs_info: true }, - function (err, remotedoc) { - db.get('test', { revs_info: true }, - function (err, localdoc) { - localdoc._rev.should.equal(winningRev); - remotedoc._rev.should.equal(winningRev); - db.info(function (err, info) { - info.update_seq.should.equal(3); - info.doc_count.should.equal(1); - done(); - }); - }); - }); - }); - }); - }); - }); - }); - }); - }); - }); - - it('Replicate and modify three times', function () { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - - var doc = { - _id: 'foo', - generation: 1 - }; - - return db.put(doc).then(function (res) { - doc._rev = res.rev; - return db.replicate.to(remote); - }).then(function () { - return remote.get('foo'); - }).then(function (doc) { - doc.generation.should.equal(1); - doc.generation = 2; - return remote.put(doc); - }).then(function (res) { - doc._rev = res.rev; - return remote.replicate.to(db); - }).then(function () { - return db.get('foo'); - }).then(function (doc) { - doc.generation.should.equal(2); - doc.generation = 3; - return db.put(doc); - }).then(function () { - return db.replicate.to(remote); - }).then(function () { - return db.get('foo', {conflicts: true}); - }).then(function (doc) { - doc.generation.should.equal(3); - should.not.exist(doc._conflicts); - }).then(function () { - return remote.get('foo', {conflicts: true}); - }).then(function (doc) { - doc.generation.should.equal(3); - should.not.exist(doc._conflicts); - }); - }); - - function waitForChange(db, fun) { - return new PouchDB.utils.Promise(function (resolve) { - var remoteChanges = db.changes({live: true, include_docs: true}); - remoteChanges.on('change', function (change) { - if (fun(change)) { - remoteChanges.cancel(); - resolve(); - } - }); - }); - } - - it('Replicates deleted docs (issue #2636)', function () { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - - var replication = db.replicate.to(remote, { - live: true - }); - - return db.post({}).then(function (res) { - var doc = { - _id: res.id, - _rev: res.rev - }; - return db.remove(doc); - }).then(function () { - return db.allDocs(); - }).then(function (res) { - res.rows.should.have.length(0, 'deleted locally'); - }).then(function () { - return waitForChange(remote, function (change) { - return change.deleted === true; - }); - }).then(function () { - return remote.allDocs(); - }).then(function (res) { - replication.cancel(); - res.rows.should.have.length(0, 'deleted in remote'); - }); - }); - - it('Replicates deleted docs w/ delay (issue #2636)', function () { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - - var replication = db.replicate.to(remote, { - live: true - }); - - var doc; - return db.post({}).then(function (res) { - doc = {_id: res.id, _rev: res.rev}; - return waitForChange(remote, function () { return true; }); - }).then(function () { - return db.remove(doc); - }).then(function () { - return db.allDocs(); - }).then(function (res) { - res.rows.should.have.length(0, 'deleted locally'); - }).then(function () { - return waitForChange(remote, function (c) { return c.seq === 2; }); - }).then(function () { - return remote.allDocs(); - }).then(function (res) { - replication.cancel(); - res.rows.should.have.length(0, 'deleted in remote'); - }); - }); - - it('Replicates deleted docs w/ compaction', function () { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - - var doc = {_id: 'foo'}; - return db.put(doc).then(function (res) { - doc._rev = res.rev; - return db.replicate.to(remote); - }).then(function () { - return db.put(doc); - }).then(function (res) { - doc._rev = res.rev; - return db.remove(doc); - }).then(function () { - return db.compact(); - }).then(function () { - return db.allDocs(); - }).then(function (res) { - res.rows.should.have.length(0, 'deleted locally'); - }).then(function () { - return db.replicate.to(remote); - }).then(function () { - return remote.allDocs(); - }).then(function (res) { - res.rows.should.have.length(0, 'deleted in remote'); - }); - }); - - it('Replicates modified docs (issue #2636)', function () { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - - var replication = db.replicate.to(remote, { - live: true - }); - - return db.post({}).then(function (res) { - var doc = { - _id: res.id, - _rev: res.rev, - modified: 'yep' - }; - - return db.put(doc); - }).then(function () { - return db.allDocs({include_docs: true}); - }).then(function (res) { - res.rows.should.have.length(1, 'one doc synced locally'); - res.rows[0].doc.modified.should.equal('yep', 'modified locally'); - }).then(function () { - return waitForChange(remote, function (change) { - return change.doc.modified === 'yep'; - }); - }).then(function () { - return remote.allDocs({include_docs: true}); - }).then(function (res) { - replication.cancel(); - res.rows.should.have.length(1, '1 doc in remote'); - res.rows[0].doc.modified.should.equal('yep', 'modified in remote'); - }); - }); - - it('Replication of multiple remote conflicts (#789)', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var doc = {_id: '789', _rev: '1-a', value: 'test'}; - function createConflicts(db, callback) { - db.put(doc, { new_edits: false }, function (err, res) { - testUtils.putAfter(db, { - _id: '789', - _rev: '2-a', - value: 'v1' - }, '1-a', function (err, res) { - testUtils.putAfter(db, { - _id: '789', - _rev: '2-b', - value: 'v2' - }, '1-a', function (err, res) { - testUtils.putAfter(db, { - _id: '789', - _rev: '2-c', - value: 'v3' - }, '1-a', function (err, res) { - callback(); - }); - }); - }); - }); - } - createConflicts(remote, function () { - db.replicate.from(remote, function (err, result) { - result.ok.should.equal(true); - // in this situation, all the conflicting revisions should be read and - // written to the target database (this is consistent with CouchDB) - result.docs_written.should.equal(3); - result.docs_read.should.equal(3); - db.info(function (err, info) { - info.update_seq.should.be.above(0); - info.doc_count.should.equal(1); - done(); - }); - }); - }); - }); - - it('Replicate large number of docs', function (done) { - if ('saucelabs' in testUtils.params()) { - return done(); - } - this.timeout(15000); - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var docs = []; - var num = 30; - for (var i = 0; i < num; i++) { - docs.push({ - _id: 'doc_' + i, - foo: 'bar_' + i - }); - } - remote.bulkDocs({ docs: docs }, function (err, info) { - db.replicate.from(remote, {}, function () { - db.allDocs(function (err, res) { - res.total_rows.should.equal(num); - db.info(function (err, info) { - info.update_seq.should.equal(30); - info.doc_count.should.equal(30); - done(); - }); - }); - }); - }); - }); - - it.skip('Changes error', function (done) { - if ('saucelabs' in testUtils.params()) { - return done(); - } - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var docs = []; - var num = 80; - for (var i = 0; i < num; i++) { - docs.push({ - _id: 'doc_' + i, - foo: 'bar_' + i - }); - } - remote.bulkDocs({docs: docs}, {}, function (err, results) { - var changes = remote.changes; - var doc_count = 0; - - // Mock remote.get to fail writing doc_3 - remote.changes = function (opts) { - var onChange = opts.onChange; - opts.onChange = function () { - doc_count++; - onChange.apply(this, arguments); - }; - var complete = opts.complete; - opts.complete = function () { - complete.apply(this, [{ - status: 500, - error: 'mock changes error', - reason: 'simulate and error from changes' - }]); - }; - changes.apply(this, arguments); - }; - - // Replicate and confirm failure - db.replicate.from(remote, function (err, result) { - should.exist(err); - doc_count.should.equal(result.docs_read); - remote.changes = changes; - db.info(function (err, info) { - info.update_seq.should.equal(3); - info.doc_count.should.equal(3); - done(); - }); - }); - }); - }); - - it('Ensure checkpoint after deletion', function (done) { - var db1name = dbs.name; - var adoc = { '_id': 'adoc' }; - var newdoc = { '_id': 'newdoc' }; - var db1 = new PouchDB(dbs.name); - var db2 = new PouchDB(dbs.remote); - db1.post(adoc, function () { - PouchDB.replicate(db1, db2, { - complete: function () { - PouchDB.destroy(db1name, function () { - var fresh = new PouchDB(db1name); - fresh.post(newdoc, function () { - PouchDB.replicate(fresh, db2, { - complete: function () { - db2.allDocs(function (err, docs) { - docs.rows.length.should.equal(2); - done(); - }); - } - }); - }); - }); - } - }); - }); - }); - - it('issue #1001 cb as 3rd argument', function (done) { - PouchDB.replicate('http://example.com', dbs.name, function (err, result) { - should.exist(err); - done(); - }); - }); - - it('issue #1001 cb in options', function (done) { - PouchDB.replicate('http://example.com', dbs.name, { - complete: function (err, result) { - should.exist(err); - done(); - } - }); - }); - - it('issue #1001 cb as 4th argument', function (done) { - PouchDB.replicate( - 'http://example.com', - dbs.name, - {}, - function (err, result) { - should.exist(err); - done(); - } - ); - }); - - it('issue #909 Filtered replication bails at paging limit', - function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var docs = []; - var num = 100; - for (var i = 0; i < num; i++) { - docs.push({ - _id: 'doc_' + i, - foo: 'bar_' + i - }); - } - num = 100; - var docList = []; - for (i = 0; i < num; i += 5) { - docList.push('doc_' + i); - } - // uncomment this line to test only docs higher than paging limit - docList = [ - 'doc_33', - 'doc_60', - 'doc_90' - ]; - remote.bulkDocs({ docs: docs }, {}, function (err, results) { - db.replicate.from(dbs.remote, { - live: false, - doc_ids: docList - }, function (err, result) { - result.docs_written.should.equal(docList.length); - db.info(function (err, info) { - info.update_seq.should.equal(3); - info.doc_count.should.equal(3); - done(); - }); - }); - }); - }); - - it.skip('(#1240) - get error', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - // 10 test documents - var num = 10; - var docs = []; - for (var i = 0; i < num; i++) { - docs.push({ - _id: 'doc_' + i, - foo: 'bar_' + i - }); - } - // Initialize remote with test documents - remote.bulkDocs({ docs: docs }, {}, function (err, results) { - var get = remote.get; - function first_replicate() { - // Mock remote.get to fail writing doc_3 (fourth doc) - remote.get = function () { - // Simulate failure to get the document with id 'doc_4' - // This should block the replication at seq 4 - if (arguments[0] === 'doc_4') { - arguments[2].apply(null, [{}]); - } else { - get.apply(this, arguments); - } - }; - // Replicate and confirm failure, docs_written and target docs - db.replicate.from(remote, function (err, result) { - should.exist(err); - should.exist(result); - result.docs_written.should.equal(4); - function check_docs(id, result) { - if (!id) { - second_replicate(); - return; - } - db.get(id, function (err, exists) { - if (exists) { - should.not.exist(err); - } else { - should.exist(err); - } - check_docs(docs.shift()); - }); - } - var docs = [ - [ - 'doc_0', - true - ], - [ - 'doc_1', - true - ], - [ - 'doc_2', - true - ], - [ - 'doc_3', - false - ], - [ - 'doc_4', - false - ], - [ - 'doc_5', - false - ], - [ - 'doc_6', - false - ], - [ - 'doc_7', - false - ], - [ - 'doc_8', - false - ], - [ - 'doc_9', - false - ] - ]; - check_docs(docs.shift()); - }); - } - function second_replicate() { - // Restore remote.get to original - remote.get = get; - // Replicate and confirm success, docs_written and target docs - db.replicate.from(remote, function (err, result) { - should.not.exist(err); - should.exist(result); - result.docs_written.should.equal(6); - function check_docs(id, exists) { - if (!id) { - db.info(function (err, info) { - info.update_seq.should.equal(6); - info.doc_count.should.equal(6); - done(); - }); - return; - } - db.get(id, function (err, result) { - if (exists) { - should.not.exist(err); - } else { - should.exist(err); - } - check_docs(docs.shift()); - }); - } - var docs = [ - [ - 'doc_0', - true - ], - [ - 'doc_1', - true - ], - [ - 'doc_2', - true - ], - [ - 'doc_3', - true - ], - [ - 'doc_4', - true - ], - [ - 'doc_5', - true - ], - [ - 'doc_6', - true - ], - [ - 'doc_7', - true - ], - [ - 'doc_8', - true - ], - [ - 'doc_9', - true - ] - ]; - check_docs(docs.shift()); - }); - } - // Done the test - first_replicate(); - }); - }); - - it.skip('Get error 2', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - // 10 test documents - var num = 10; - var docs = []; - for (var i = 0; i < num; i++) { - docs.push({ - _id: 'doc_' + i, - foo: 'bar_' + i - }); - } - // Initialize remote with test documents - remote.bulkDocs({ docs: docs }, {}, function (err, results) { - var get = remote.get; - function first_replicate() { - // Mock remote.get to fail writing doc_3 (fourth doc) - remote.get = function () { - // Simulate failure to get the document with id 'doc_4' - // This should block the replication at seq 4 - if (arguments[0] === 'doc_4') { - arguments[2].apply(null, [{ - status: 500, - error: 'mock error', - reason: 'mock get failure' - }]); - } else { - get.apply(this, arguments); - } - }; - // Replicate and confirm failure, docs_written and target docs - db.replicate.from(remote, function (err, result) { - err.status.should.equal(500); - err.error.should.equal('Replication aborted'); - err.reason.should.equal('src.get completed with error'); - err.details.status.should.equal(500); - err.details.error.should.equal('mock error'); - err.details.reason.should.equal('mock get failure'); - result.errors[0].status.should.equal(500); - result.errors[0].error.should.equal('mock error'); - result.errors[0].reason.should.equal('mock get failure'); - result.docs_written.should.equal(4); - function check_docs(id, result) { - if (!id) { - second_replicate(); - return; - } - db.get(id, function (err, exists) { - if (exists) { - should.not.exist(err); - } else { - should.exist(err); - } - check_docs(docs.shift()); - }); - } - var docs = [ - [ - 'doc_0', - true - ], - [ - 'doc_1', - true - ], - [ - 'doc_2', - true - ], - [ - 'doc_3', - false - ], - [ - 'doc_4', - false - ], - [ - 'doc_5', - false - ], - [ - 'doc_6', - false - ], - [ - 'doc_7', - false - ], - [ - 'doc_8', - false - ], - [ - 'doc_9', - false - ] - ]; - check_docs(docs.shift()); - }); - } - function second_replicate() { - // Restore remote.get to original - remote.get = get; - // Replicate and confirm success, docs_written and target docs - db.replicate.from(remote, function (err, result) { - should.not.exist(err); - should.exist(result); - result.docs_written.should.equal(6); - function check_docs(id, exists) { - if (!id) { - db.info(function (err, info) { - info.update_seq.should.equal(6); - info.doc_count.should.equal(6); - done(); - }); - return; - } - db.get(id, function (err, result) { - if (exists) { - should.not.exist(err); - } else { - should.exist(err); - } - check_docs(docs.shift()); - }); - } - var docs = [ - [ - 'doc_0', - true - ], - [ - 'doc_1', - true - ], - [ - 'doc_2', - true - ], - [ - 'doc_3', - true - ], - [ - 'doc_4', - true - ], - [ - 'doc_5', - true - ], - [ - 'doc_6', - true - ], - [ - 'doc_7', - true - ], - [ - 'doc_8', - true - ], - [ - 'doc_9', - true - ] - ]; - check_docs(docs.shift()); - }); - } - // Done the test - first_replicate(); - }); - }); - - it.skip("error updating checkpoint", function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - remote.bulkDocs({docs: docs}, {}, function (err, results) { - var get = remote.get; - var local_count = 0; - // Mock remote.get to fail writing doc_3 (fourth doc) - remote.get = function () { - // Simulate failure to get the checkpoint - if (arguments[0].slice(0, 6) === '_local') { - local_count++; - if (local_count === 2) { - arguments[1].apply(null, [{ - status: 500, - error: 'mock get error', - reason: 'simulate an error updating the checkpoint' - }]); - } else { - get.apply(this, arguments); - } - } else { - get.apply(this, arguments); - } - }; - - db.replicate.from(remote, { - complete: function (err, result) { - should.exist(err); - db.info(function (err, info) { - info.update_seq.should.equal(2); - info.doc_count.should.equal(2); - done(); - }); - } - }); - }); - }); - - it('(#1307) - replicate empty database', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - db.replicate.from(remote, function (err, result) { - should.not.exist(err); - should.exist(result); - result.docs_written.should.equal(0); - db.info(function (err, info) { - info.update_seq.should.equal(0); - info.doc_count.should.equal(0); - done(); - }); - }); - }); - - - // This fails as it somehow triggers an xhr abort in the http adapter in - // node which doesnt have xhr.... - it.skip('Syncing should stop if one replication fails (issue 838)', - function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var doc1 = {_id: 'adoc', foo: 'bar'}; - var doc2 = {_id: 'anotherdoc', foo: 'baz'}; - var finished = false; - var replications = db.replicate.sync(remote, { - live: true, - complete: function () { - if (finished) { - return; - } - finished = true; - remote.put(doc2, function (err) { - setTimeout(function () { - db.allDocs(function (err, res) { - res.total_rows.should.be.below(2); - done(); - }); - }, 100); - }); - } - }); - db.put(doc1, function (err) { - replications.pull.cancel(); - }); - }); - - it("Reporting write failures (#942)", function (done) { - var docs = [{_id: 'a', _rev: '1-a'}, {_id: 'b', _rev: '1-b'}]; - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - db.bulkDocs({docs: docs}, {new_edits: false}, function (err, _) { - var bulkDocs = remote.bulkDocs; - remote.bulkDocs = function (content, opts, callback) { - return new PouchDB.utils.Promise(function (fulfill, reject) { - if (typeof callback !== 'function') { - callback = function (err, resp) { - if (err) { - reject(err); - } else { - fulfill(resp); - } - }; - } - var ids = content.docs.map(function (doc) { return doc._id; }); - if (ids.indexOf('a') >= 0) { - callback(null, [{ok: true, id: 'a', rev: '1-a'}]); - } else if (ids.indexOf('b') >= 0) { - callback(null, [{ - id: 'b', - error: 'internal server error', - reason: 'test document write error' - }]); - } else { - bulkDocs.apply(remote, [content, opts, callback]); - } - }); - }; - - db.replicate.to(remote, { batch_size: 1 }, function (err, result) { - should.not.exist(result); - should.exist(err); - err.result.docs_read.should.equal(2, 'docs_read'); - err.result.docs_written.should.equal(1, 'docs_written'); - err.result.doc_write_failures.should.equal(1, 'doc_write_failures'); - remote.bulkDocs = bulkDocs; - db.replicate.to(remote, { batch_size: 1 }, function (err, result) { - // checkpoint should not be moved past first doc - // should continue from this point and retry second doc - result.docs_read.should.equal(1, 'second replication, docs_read'); - result.docs_written.should - .equal(1, 'second replication, docs_written'); - result.doc_write_failures.should - .equal(0, 'second replication, doc_write_failures'); - db.info(function (err, info) { - info.update_seq.should.equal(2); - info.doc_count.should.equal(2); - done(); - }); - }); - }); - }); - }); - - it("Reporting write failures if whole saving fails (#942)", - function (done) { - var docs = [{_id: 'a', _rev: '1-a'}, {_id: 'b', _rev: '1-b'}]; - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - db.bulkDocs({docs: docs}, {new_edits: false}, function (err, _) { - var bulkDocs = remote.bulkDocs; - remote.bulkDocs = function (docs, opts, callback) { - if (typeof callback !== 'function') { - return PouchDB.utils.Promise.reject(new Error()); - } - callback(new Error()); - }; - - db.replicate.to(remote, { batch_size: 1 }, function (err, result) { - should.not.exist(result); - should.exist(err); - err.result.docs_read.should.equal(1, 'docs_read'); - err.result.docs_written.should.equal(0, 'docs_written'); - err.result.doc_write_failures.should.equal(1, 'doc_write_failures'); - err.result.last_seq.should.equal(0, 'last_seq'); - remote.bulkDocs = bulkDocs; - db.replicate.to(remote, { batch_size: 1 }, function (err, result) { - result.doc_write_failures.should - .equal(0, 'second replication, doc_write_failures'); - result.docs_written.should - .equal(2, 'second replication, docs_written'); - result.last_seq.should.equal(2, 'second replication, last_seq'); - done(); - }); - }); - }); - }); - - it('Test consecutive replications with different query_params', - function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var myDocs = [ - {_id: '0', integer: 0, string: '0'}, - {_id: '1', integer: 1, string: '1'}, - {_id: '2', integer: 2, string: '2'}, - {_id: '3', integer: 3, string: '3'}, - {_id: '4', integer: 5, string: '5'} - ]; - remote.bulkDocs({ docs: myDocs }, {}, function (err, results) { - var filterFun = function (doc, req) { - if (req.query.even) { - return doc.integer % 2 === 0; - } else { - return true; - } - }; - db.replicate.from(dbs.remote, { - filter: filterFun, - query_params: { 'even': true } - }, function (err, result) { - result.docs_written.should.equal(2); - db.replicate.from(dbs.remote, { - filter: filterFun, - query_params: { 'even': false } - }, function (err, result) { - result.docs_written.should.equal(3); - done(); - }); - }); - }); - }); - - it('Test consecutive replications with different query_params and promises', - function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var myDocs = [ - {_id: '0', integer: 0, string: '0'}, - {_id: '1', integer: 1, string: '1'}, - {_id: '2', integer: 2, string: '2'}, - {_id: '3', integer: 3, string: '3'}, - {_id: '4', integer: 5, string: '5'} - ]; - var filterFun; - remote.bulkDocs({ docs: myDocs }).then(function (results) { - filterFun = function (doc, req) { - if (req.query.even) { - return doc.integer % 2 === 0; - } else { - return true; - } - }; - return db.replicate.from(dbs.remote, { - filter: filterFun, - query_params: { 'even': true } - }); - }).then(function (result) { - result.docs_written.should.equal(2); - return db.replicate.from(dbs.remote, { - filter: filterFun, - query_params: { 'even': false } - }); - }).then(function (result) { - result.docs_written.should.equal(3); - done(); - }).catch(done); - }); - - it('Test consecutive replications with different doc_ids', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var myDocs = [ - {_id: '0', integer: 0, string: '0'}, - {_id: '1', integer: 1, string: '1'}, - {_id: '2', integer: 2, string: '2'}, - {_id: '3', integer: 3, string: '3'}, - {_id: '4', integer: 5, string: '5'} - ]; - remote.bulkDocs({ docs: myDocs }, {}, function (err, results) { - db.replicate.from(dbs.remote, { - doc_ids: ['0', '4'] - }, function (err, result) { - result.docs_written.should.equal(2); - db.replicate.from(dbs.remote, { - doc_ids: ['1', '2', '3'] - }, function (err, result) { - result.docs_written.should.equal(3); - db.replicate.from(dbs.remote, { - doc_ids: ['5'] - }, function (err, result) { - result.docs_written.should.equal(0); - db.info(function (err, info) { - info.update_seq.should.equal(5); - info.doc_count.should.equal(5); - done(); - }); - }); - }); - }); - }); - }); - - it('doc count after multiple replications', function (done) { - - var runs = 2; - // helper. remove each document in db and bulk load docs into same - function rebuildDocuments(db, docs, callback) { - db.allDocs({ include_docs: true }, function (err, response) { - var count = 0; - var limit = response.rows.length; - if (limit === 0) { - bulkLoad(db, docs, callback); - } - response.rows.forEach(function (doc) { - db.remove(doc, function (err, response) { - ++count; - if (count === limit) { - bulkLoad(db, docs, callback); - } - }); - }); - }); - } - - // helper. - function bulkLoad(db, docs, callback) { - db.bulkDocs({ docs: docs }, function (err, results) { - if (err) { - console.error('Unable to bulk load docs. Err: ' + - JSON.stringify(err)); - return; - } - callback(results); - }); - } - - // a basic map function to mimic our testing situation - var map = 'function(doc) {' + - 'if (doc.common === true) {' + - 'emit(doc._id, doc.rev);' + - '}' + - '}'; - - // The number of workflow cycles to perform. 2+ was always failing - // reason for this test. - var workflow = function (name, remote, x) { - // some documents. note that the variable Date component, - //thisVaries, makes a difference. - // when the document is otherwise static, couch gets the same hash - // when calculating revision. - // and the revisions get messed up in pouch - var docs = [ - { - _id: '0', - integer: 0, - thisVaries: new Date(), - common: true - }, - { - _id: '1', - integer: 1, - thisVaries: new Date(), - common: true - }, - { - _id: '2', - integer: 2, - thisVaries: new Date(), - common: true - }, - { - _id: '3', - integer: 3, - thisVaries: new Date(), - common: true - } - ]; - var dbr = new PouchDB(remote); - rebuildDocuments(dbr, docs, function () { - var db = new PouchDB(name); - db.replicate.from(remote, function (err, result) { - db.query({ map: map }, { reduce: false }, function (err, result) { - result.rows.length.should.equal(docs.length); - if (--x) { - workflow(name, remote, x); - } else { - db.info(function (err, info) { - info.update_seq.should.equal(4); - info.doc_count.should.equal(4); - done(); - }); - } - }); - }); - }); - }; - - workflow(dbs.name, dbs.remote, runs); - }); - - it('issue #300 rev id unique per doc', function (done) { - var remote = new PouchDB(dbs.remote); - var db = new PouchDB(dbs.name); - var docs = [{ _id: 'a' }, { _id: 'b' }]; - remote.bulkDocs({ docs: docs }, {}, function (err, _) { - db.replicate.from(dbs.remote, function (err, _) { - db.allDocs(function (err, result) { - result.rows.length.should.equal(2); - result.rows[0].id.should.equal('a'); - result.rows[1].id.should.equal('b'); - db.info(function (err, info) { - info.update_seq.should.equal(2); - info.doc_count.should.equal(2); - done(); - }); - }); - }); - }); - }); - - it('issue #585 Store checkpoint on target db.', function (done) { - var db = new PouchDB(dbs.name); - var docs = [{ _id: 'a' }, { _id: 'b' }]; - db.bulkDocs({ docs: docs }, {}, function (err, _) { - db.replicate.to(dbs.remote, function (err, result) { - result.docs_written.should.equal(docs.length); - PouchDB.destroy(dbs.remote, function (err, result) { - db.replicate.to(dbs.remote, function (err, result) { - result.docs_written.should.equal(docs.length); - db.info(function (err, info) { - info.update_seq.should.equal(2); - info.doc_count.should.equal(2); - done(); - }); - }); - }); - }); - }); - }); - it('should work with a read only source', function (done) { - var src = new PouchDB(dbs.name); - var target = new PouchDB(dbs.remote); - var err = { - "message": "_writer access is required for this request", - "name": "unauthorized", - "status": 401 - }; - src.bulkDocs({docs: [ - {_id: '0', integer: 0, string: '0'}, - {_id: '1', integer: 1, string: '1'}, - {_id: '2', integer: 2, string: '2'}, - ]}).then(function () { - src.put = function () { - if (typeof arguments[arguments.length - 1] === 'function') { - arguments[arguments.length - 1](err); - } else { - return PouchDB.utils.Promise.reject(err); - } - }; - return src.replicate.to(target); - }).then(function () { - target.info(function (err, info) { - info.update_seq.should.equal(3); - info.doc_count.should.equal(3); - done(); - }); - }, function (a) { - done(JSON.stringify(a, false, 4)); - }); - }); - - it('issue #2342 update_seq after replication', function (done) { - this.timeout(30000); - var docs = []; - for (var i = 0; i < 10; i++) { - docs.push({_id: i.toString()}); - } - - var remote = new PouchDB(dbs.remote); - var db = new PouchDB(dbs.name); - - remote.bulkDocs({ docs: docs }, {}, function (err, res) { - res.forEach(function (row, i) { - docs[i]._rev = row.rev; - if (i % 2 === 0) { - docs[i]._deleted = true; - } - }); - remote.bulkDocs({docs: docs}, {}, function (err, res) { - db.replicate.from(dbs.remote, function (err, _) { - db.info(function (err, info) { - db.changes({ - since: 'latest', - live: true, - onChange: function (change) { - change.changes.should.have.length(1); - change.seq.should.equal(info.update_seq); - done(); - } - }); - }); - }); - }); - }); - }); - - it('issue #2393 update_seq after new_edits + replication', function (done) { - var docs = [{ - '_id': 'foo', - '_rev': '1-x', - '_revisions': { - 'start': 1, - 'ids': ['x'] - } - }]; - - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - - remote.bulkDocs({docs: docs, new_edits: false}, function (err, result) { - should.not.exist(err); - remote.bulkDocs({docs: docs, new_edits: false}, function (err, result) { - should.not.exist(err); - db.replicate.from(dbs.remote, function (err, _) { - db.info(function (err, info) { - db.changes({ - since: 'latest', - live: true, - onChange: function (change) { - change.changes.should.have.length(1); - change.seq.should.equal(info.update_seq); - remote.info(function (err, info) { - remote.changes({ - since: 'latest', - live: true, - onChange: function (change) { - change.changes.should.have.length(1); - change.seq.should.equal(info.update_seq); - done(); - } - }); - }); - } - }); - }); - }); - }); - }); - }); - - it('should cancel for live replication', function (done) { - var remote = new PouchDB(dbs.remote); - var db = new PouchDB(dbs.name); - var rep = db.replicate.from(remote, {live: true}); - var called = false; - rep.on('change', function () { - if (called) { - done(new Error('called too many times!')); - } else { - called = true; - rep.cancel(); - remote.put({}, 'foo').then(function () { - return remote.put({}, 'bar'); - }).then(function () { - setTimeout(function () { - done(); - }, 500); - }); - } - }); - remote.put({}, 'hazaa'); - }); - - it('retry stuff', function (done) { - var remote = new PouchDB(dbs.remote); - var Promise = PouchDB.utils.Promise; - var allDocs = remote.allDocs; - var i = 0; - var started = 0; - remote.allDocs = function (opts) { - if (opts.keys[0] === 'foo') { - i++; - if (i !== 3) { - return Promise.reject(new Error('flunking you')); - } - } - return allDocs.apply(remote, arguments); - }; - var db = new PouchDB(dbs.name); - var rep = db.replicate.from(remote, { - live: true, - retry: true - }); - rep.once('syncStopped', function () { - i.should.equal(1, 'sync stopped event'); - started.should.equal(1, 'sync stopped event'); - started++; - }); - rep.on('syncRestarted', function () { - i.should.equal(3, 'sync restarted event'); - started.should.equal(2, 'sync stopped event'); - started++; - }); - rep.on('syncStarted', function () { - i.should.equal(0, 'sync started event'); - started.should.equal(0, 'sync started event'); - started++; - }); - rep.catch(done); - var called = 3; - rep.on('change', function () { - if ((--called) === 2) { - remote.put({}, 'foo').then(function () { - return remote.put({}, 'bar'); - }); - } else if (!called) { - rep.cancel(); - remote.put({}, 'foo2').then(function () { - return remote.put({}, 'bar2'); - }).then(function () { - setTimeout(function () { - started.should.equal(3, 'everything was emitted'); - done(); - }, 500); - }); - } else if (called < 0) { - done(new Error('called too many times')); - } - }); - remote.put({}, 'hazaa'); - }); - - it('#2970 should replicate remote database w/ deleted conflicted revs', - function (done) { - var local = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var docid = "mydoc"; - - function uuid() { - return PouchDB.utils.uuid(32, 16).toLowerCase(); - } - - // create a bunch of rando, good revisions - var numRevs = 5; - var uuids = []; - for (var i = 0; i < numRevs - 1; i++) { - uuids.push(uuid()); - } - - // good branch - // this branch is one revision ahead of the conflicted branch - var a_conflict = uuid(); - var a_burner = uuid(); - var a_latest = uuid(); - var a_rev_num = numRevs + 2; - var a_doc = { - _id: docid, - _rev: a_rev_num + '-' + a_latest, - _revisions: { - start: a_rev_num, - ids: [ a_latest, a_burner, a_conflict ].concat(uuids) - } - }; - - // conflicted deleted branch - var b_conflict = uuid(); - var b_deleted = uuid(); - var b_rev_num = numRevs + 1; - var b_doc = { - _id: docid, - _rev: b_rev_num + '-' + b_deleted, - _deleted: true, - _revisions: { - start: b_rev_num, - ids: [ b_deleted, b_conflict ].concat(uuids) - } - }; - - // push the conflicted documents - return remote.bulkDocs([ a_doc, b_doc ], { - new_edits: false - }).then(function () { - return remote.get(docid, { open_revs: 'all' }).then(function (revs) { - revs.length.should.equal(2, 'correct number of open revisions'); - revs[0].ok._id.should.equal(docid, 'rev 1, correct document id'); - revs[1].ok._id.should.equal(docid, 'rev 2, correct document id'); - // order of revisions is not specified - (( - revs[0].ok._rev === a_doc._rev && - revs[1].ok._rev === b_doc._rev) || - ( - revs[0].ok._rev === b_doc._rev && - revs[1].ok._rev === a_doc._rev) - ).should.equal(true); - }); - }) - - // attempt to replicate - .then(function () { - return local.replicate.from(remote).then(function (result) { - result.ok.should.equal(true, 'replication result was ok'); - // # of documents is 2 because deleted - // conflicted revision counts as one - result.docs_written.should.equal(2, - 'replicated the correct number of documents'); - }); - }) - - .then(function () { done(); }, done); - }); - - - // test validate_doc_update, which is a reasonable substitute - // for testing design doc replication of non-admin users, since we - // always test in admin party - it('#2268 dont stop replication if single forbidden', function (done) { - - testUtils.isCouchDB(function (isCouchDB) { - if (adapters[1] !== 'http' || !isCouchDB) { - return done(); - } - - var ddoc = { - "_id": "_design/validate", - "validate_doc_update": function (newDoc) { - if (newDoc.foo === undefined) { - throw {forbidden: 'Document must have a foo.'}; - } - }.toString() - }; - - var remote = new PouchDB(dbs.remote); - var db = new PouchDB(dbs.name); - - return remote.put(ddoc).then(function () { - var docs = [{foo: 'bar'}, {foo: 'baz'}, {}, {foo: 'quux'}]; - return db.bulkDocs({docs: docs}); - }).then(function () { - return db.replicate.to(dbs.remote); - }).then(function (res) { - res.ok.should.equal(true); - res.docs_read.should.equal(4); - res.docs_written.should.equal(3); - res.doc_write_failures.should.equal(1); - res.errors.should.have.length(1); - - return remote.allDocs({limit: 0}); - }).then(function (res) { - res.total_rows.should.equal(4); // 3 plus the validate doc - return db.allDocs({limit: 0}); - }).then(function (res) { - res.total_rows.should.equal(4); // 3 plus the invalid doc - }).then(done); - }); - }); - - it('#2268 dont stop replication if single unauth', function (done) { - - testUtils.isCouchDB(function (isCouchDB) { - if (adapters[1] !== 'http' || !isCouchDB) { - return done(); - } - - var ddoc = { - "_id": "_design/validate", - "validate_doc_update": function (newDoc) { - if (newDoc.foo === undefined) { - throw {unauthorized: 'Document must have a foo.'}; - } - }.toString() - }; - - var remote = new PouchDB(dbs.remote); - var db = new PouchDB(dbs.name); - - return remote.put(ddoc).then(function () { - var docs = [{foo: 'bar'}, {foo: 'baz'}, {}, {foo: 'quux'}]; - return db.bulkDocs({docs: docs}); - }).then(function () { - return db.replicate.to(dbs.remote); - }).then(function (res) { - res.ok.should.equal(true); - res.docs_read.should.equal(4); - res.docs_written.should.equal(3); - res.doc_write_failures.should.equal(1); - res.errors.should.have.length(1); - - return remote.allDocs({limit: 0}); - }).then(function (res) { - res.total_rows.should.equal(4); // 3 plus the validate doc - return db.allDocs({limit: 0}); - }).then(function (res) { - res.total_rows.should.equal(4); // 3 plus the invalid doc - }).then(done); - }); - }); - - it('#2268 dont stop replication if many unauth', function (done) { - - testUtils.isCouchDB(function (isCouchDB) { - if (adapters[1] !== 'http' || !isCouchDB) { - return done(); - } - - var ddoc = { - "_id": "_design/validate", - "validate_doc_update": function (newDoc) { - if (newDoc.foo === undefined) { - throw {unauthorized: 'Document must have a foo.'}; - } - }.toString() - }; - - var remote = new PouchDB(dbs.remote); - var db = new PouchDB(dbs.name); - - return remote.put(ddoc).then(function () { - var docs = [{foo: 'bar'}, {foo: 'baz'}, {}, {foo: 'quux'}, {}, {}, - {foo: 'toto'}, {}]; - return db.bulkDocs({docs: docs}); - }).then(function () { - return db.replicate.to(dbs.remote); - }).then(function (res) { - res.ok.should.equal(true); - res.docs_read.should.equal(8); - res.docs_written.should.equal(4); - res.doc_write_failures.should.equal(4); - res.errors.should.have.length(4); - - return remote.allDocs({limit: 0}); - }).then(function (res) { - res.total_rows.should.equal(5); // 4 plus the validate doc - return db.allDocs({limit: 0}); - }).then(function (res) { - res.total_rows.should.equal(8); // 4 valid and 4 invalid - }).then(done); - }); - }); - - }); -}); - -// // This test only needs to run for one configuration, and it slows stuff -// // down -downAdapters.map(function (adapter) { - - describe('test.replication.js-down-test', function () { - - var dbs = {}; - - beforeEach(function (done) { - dbs.name = testUtils.adapterUrl(adapters[0], 'testdb'); - testUtils.cleanup([dbs.name], done); - }); - - afterEach(function (done) { - testUtils.cleanup([dbs.name], done); - }); - - it('replicate from down server test', function (done) { - var db = new PouchDB(dbs.name); - db.replicate.to('http://infiniterequest.com', function (err, changes) { - should.exist(err); - done(); - }); - }); - - }); -});
diff --git a/tests/integration/test.reserved.js b/tests/integration/test.reserved.js deleted file mode 100644 index 5598da1..0000000 --- a/tests/integration/test.reserved.js +++ /dev/null
@@ -1,66 +0,0 @@ -'use strict'; - -var adapters = [ - ['local', 'http'], - ['http', 'http'], - ['http', 'local'], - ['local', 'local'] -]; - -adapters.forEach(function (adapters) { - describe('test.reserved.js-' + adapters[0] + '-' + adapters[1], function () { - - var dbs = {}; - - beforeEach(function (done) { - dbs.name = testUtils.adapterUrl(adapters[0], 'testdb'); - dbs.remote = testUtils.adapterUrl(adapters[1], 'test_repl_remote'); - testUtils.cleanup([dbs.name, dbs.remote], done); - }); - - after(function (done) { - testUtils.cleanup([dbs.name, dbs.remote], done); - }); - - it('test docs with reserved javascript ids', function () { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - return db.bulkDocs([ - {_id: 'constructor'}, - {_id: 'toString'}, - {_id: 'valueOf'} - ]).then(function () { - return db.allDocs({key: 'constructor'}); - }).then(function (res) { - res.rows.should.have.length(1, 'allDocs with key'); - return db.allDocs({keys: ['constructor']}); - }).then(function (res) { - res.rows.should.have.length(1, 'allDocs with keys'); - return db.allDocs(); - }).then(function (res) { - res.rows.should.have.length(3, 'allDocs empty opts'); - return db.query(function (doc) { - emit(doc._id); - }, {key: 'constructor'}); - }).then(function (res) { - res.rows.should.have.length(1, 'query with key'); - return db.query(function (doc) { - emit(doc._id); - }, {keys: ['constructor']}); - }).then(function (res) { - res.rows.should.have.length(1, 'query with keys'); - return new PouchDB.utils.Promise(function (resolve, reject) { - db.replicate.to(remote).on('complete', resolve).on('error', reject); - }); - }); - }); - - it('can create db with reserved name', function () { - return new PouchDB('constructor').then(function (db) { - return db.info().then(function () { - return db.destroy(); - }); - }); - }); - }); -});
diff --git a/tests/integration/test.revs_diff.js b/tests/integration/test.revs_diff.js deleted file mode 100644 index deda990..0000000 --- a/tests/integration/test.revs_diff.js +++ /dev/null
@@ -1,140 +0,0 @@ -'use strict'; - -var adapters = ['http', 'local']; - -adapters.forEach(function (adapter) { - describe('test.revs_diff.js-' + adapter, function () { - - var dbs = {}; - - beforeEach(function (done) { - dbs.name = testUtils.adapterUrl(adapter, 'testdb'); - testUtils.cleanup([dbs.name], done); - }); - - afterEach(function (done) { - testUtils.cleanup([dbs.name], done); - }); - - - it('Test revs diff', function (done) { - var db = new PouchDB(dbs.name, {auto_compaction: false}); - var revs = []; - db.post({ - test: 'somestuff', - _id: 'somestuff' - }, function (err, info) { - revs.push(info.rev); - db.put({ - _id: info.id, - _rev: info.rev, - another: 'test' - }, function (err, info2) { - revs.push(info2.rev); - db.revsDiff({ 'somestuff': revs }, function (err, results) { - results.should.not.include.keys('somestuff'); - revs.push('2-randomid'); - db.revsDiff({ 'somestuff': revs }, function (err, results) { - results.should.include.keys('somestuff'); - results.somestuff.missing.should.have.length(1); - done(); - }); - }); - }); - }); - }); - - it('Missing docs should be returned with all revisions', function (done) { - new PouchDB(dbs.name, function (err, db) { - var revs = ['1-a', '2-a', '2-b']; - db.revsDiff({'foo': revs }, function (err, results) { - results.should.include.keys('foo'); - results.foo.missing.should.deep.equal(revs, 'listed all revs'); - done(); - }); - }); - }); - - it('Conflicting revisions that are available', function (done) { - var doc = {_id: '939', _rev: '1-a'}; - function createConflicts(db, callback) { - db.put(doc, { new_edits: false }, function (err, res) { - testUtils.putAfter(db, { - _id: '939', - _rev: '2-a' - }, '1-a', function (err, res) { - testUtils.putAfter(db, { - _id: '939', - _rev: '2-b' - }, '1-a', callback); - }); - }); - } - var db = new PouchDB(dbs.name, {auto_compaction: false}); - createConflicts(db, function () { - db.revsDiff({'939': ['1-a', '2-a', '2-b']}, function (err, results) { - results.should.not.include.keys('939'); - done(); - }); - }); - }); - - it('Deleted revisions that are available', function (done) { - function createDeletedRevision(db, callback) { - db.put({ - _id: '935', - _rev: '1-a' - }, { new_edits: false }, function (err, info) { - testUtils.putAfter(db, { - _id: '935', - _rev: '2-a', - _deleted: true - }, '1-a', callback); - }); - } - var db = new PouchDB(dbs.name); - createDeletedRevision(db, function () { - db.revsDiff({'935': ['1-a', '2-a']}, function (err, results) { - results.should.not.include.keys('939'); - done(); - }); - }); - }); - - it('Revs diff with empty revs', function () { - return new PouchDB(dbs.name).then(function (db) { - return db.revsDiff({}).then(function (res) { - should.exist(res); - }); - }); - }); - - it('Test revs diff with reserved ID', function (done) { - var db = new PouchDB(dbs.name, {auto_compaction: false}); - var revs = []; - db.post({ - test: 'constructor', - _id: 'constructor' - }, function (err, info) { - revs.push(info.rev); - db.put({ - _id: info.id, - _rev: info.rev, - another: 'test' - }, function (err, info2) { - revs.push(info2.rev); - db.revsDiff({ 'constructor': revs }, function (err, results) { - results.should.not.include.keys('constructor'); - revs.push('2-randomid'); - db.revsDiff({ 'constructor': revs }, function (err, results) { - results.should.include.keys('constructor'); - results.constructor.missing.should.have.length(1); - done(); - }); - }); - }); - }); - }); - - }); -});
diff --git a/tests/integration/test.slash_id.js b/tests/integration/test.slash_id.js deleted file mode 100644 index 0467722..0000000 --- a/tests/integration/test.slash_id.js +++ /dev/null
@@ -1,148 +0,0 @@ -'use strict'; - -var adapters = ['local', 'http']; -var repl_adapters = [ - ['local', 'http'], - ['http', 'http'], - ['http', 'local'], - ['local', 'local'] -]; - -adapters.forEach(function (adapter) { - describe('test.slash_ids.js-' + adapter, function () { - - var dbs = {}; - - beforeEach(function (done) { - dbs.name = testUtils.adapterUrl(adapter, 'testdb'); - testUtils.cleanup([dbs.name], done); - }); - - after(function (done) { - testUtils.cleanup([dbs.name], done); - }); - - - it('Insert a doc, putAttachment and allDocs', function (done) { - var db = new PouchDB(dbs.name); - var docId = 'doc/with/slashes'; - var attachmentId = 'attachment/with/slashes'; - var blobData = 'attachment content'; - var blob = testUtils.makeBlob(blobData); - var doc = {_id: docId, test: true}; - db.put(doc, function (err, info) { - should.not.exist(err, 'saved doc'); - info.id.should.equal('doc/with/slashes', 'id is the same as inserted'); - db.putAttachment(docId, attachmentId, info.rev, blob, 'text/plain', - function (err, res) { - db.getAttachment(docId, attachmentId, function (err, res) { - testUtils.readBlob(res, function (data) { - db.get(docId, function (err, res) { - res._id.should.equal(docId); - res._attachments.should.include.keys(attachmentId); - done(); - }); - }); - }); - }); - }); - }); - - it('BulkDocs and changes', function (done) { - var db = new PouchDB(dbs.name); - var docs = [ - {_id: 'part/doc1', int: 1}, - {_id: 'part/doc2', int: 2, _attachments: { - 'attachment/with/slash': { - content_type: 'text/plain', - data: 'c29tZSBkYXRh' - } - }}, - {_id: 'part/doc3', int: 3} - ]; - db.bulkDocs({ docs: docs }, function (err, res) { - for (var i = 0; i < 3; i++) { - res[i].ok.should.equal(true, 'correctly inserted ' + docs[i]._id); - } - db.allDocs({ - include_docs: true, - attachments: true - }, function (err, res) { - res.rows.sort(function (a, b) { - return a.doc.int - b.doc.int; - }); - for (var i = 0; i < 3; i++) { - res.rows[i].doc._id.should - .equal(docs[i]._id, '(allDocs) correctly inserted ' + - docs[i]._id); - } - res.rows[1].doc._attachments.should.include - .keys('attachment/with/slash'); - db.changes({ - complete: function (err, res) { - res.results.sort(function (a, b) { - return a.id.localeCompare(b.id); - }); - for (var i = 0; i < 3; i++) { - res.results[i].id.should - .equal(docs[i]._id, 'correctly inserted'); - } - done(); - } - }); - }); - }); - }); - - }); -}); - - -repl_adapters.forEach(function (adapters) { - describe('test.slash_ids.js-' + adapters[0] + '-' + adapters[1], function () { - - var dbs = {}; - - beforeEach(function (done) { - dbs.name = testUtils.adapterUrl(adapters[0], 'test_slash_ids'); - dbs.remote = testUtils.adapterUrl(adapters[1], 'test_slash_ids_remmote'); - testUtils.cleanup([dbs.name, dbs.remote], done); - }); - - afterEach(function (done) { - testUtils.cleanup([dbs.name, dbs.remote], done); - }); - - - it('Attachments replicate', function (done) { - var binAttDoc = { - _id: 'bin_doc/with/slash', - _attachments: { - 'foo/with/slash.txt': { - content_type: 'text/plain', - data: 'VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ=' - } - } - }; - var docs1 = [ - binAttDoc, - {_id: '0', integer: 0}, - {_id: '1', integer: 1}, - {_id: '2', integer: 2}, - {_id: '3', integer: 3} - ]; - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - remote.bulkDocs({ docs: docs1 }, function (err, info) { - db.replicate.from(remote, function () { - db.get('bin_doc/with/slash', { attachments: true }, - function (err, doc) { - binAttDoc._attachments['foo/with/slash.txt'].data.should - .equal(doc._attachments['foo/with/slash.txt'].data); - done(); - }); - }); - }); - }); - }); -});
diff --git a/tests/integration/test.sync.js b/tests/integration/test.sync.js deleted file mode 100644 index faf290c..0000000 --- a/tests/integration/test.sync.js +++ /dev/null
@@ -1,359 +0,0 @@ -'use strict'; - -var adapters = [ - ['local', 'http'], - ['http', 'http'], - ['http', 'local'], - ['local', 'local'] -]; - -if ('saucelabs' in testUtils.params()) { - adapters = [['local', 'http'], ['http', 'local']]; -} - -adapters.forEach(function (adapters) { - describe('test.sync.js-' + adapters[0] + '-' + adapters[1], function () { - - var dbs = {}; - - beforeEach(function (done) { - dbs.name = testUtils.adapterUrl(adapters[0], 'testdb'); - dbs.remote = testUtils.adapterUrl(adapters[1], 'test_repl_remote'); - testUtils.cleanup([dbs.name, dbs.remote], done); - }); - - after(function (done) { - testUtils.cleanup([dbs.name, dbs.remote], done); - }); - - it('PouchDB.sync event', function (done) { - var doc1 = { - _id: 'adoc', - foo: 'bar' - }; - var doc2 = { - _id: 'anotherdoc', - foo: 'baz' - }; - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - db.put(doc1, function (err) { - remote.put(doc2, function (err) { - PouchDB.sync(db, remote).on('complete', function (result) { - result.pull.ok.should.equal(true); - result.pull.docs_read.should.equal(1); - result.pull.docs_written.should.equal(1); - result.pull.errors.should.have.length(0); - done(); - }); - }); - }); - }); - - it('PouchDB.sync callback', function (done) { - var doc1 = { - _id: 'adoc', - foo: 'bar' - }; - var doc2 = { - _id: 'anotherdoc', - foo: 'baz' - }; - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - db.put(doc1, function (err) { - remote.put(doc2, function (err) { - PouchDB.sync(db, remote, function (err, result) { - result.pull.ok.should.equal(true); - result.pull.docs_read.should.equal(1); - result.pull.docs_written.should.equal(1); - result.pull.errors.should.have.length(0); - done(); - }); - }); - }); - }); - - it('PouchDB.sync promise', function (done) { - var doc1 = { - _id: 'adoc', - foo: 'bar' - }; - var doc2 = { - _id: 'anotherdoc', - foo: 'baz' - }; - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - db.put(doc1).then(function () { - return remote.put(doc2); - }).then(function () { - return PouchDB.sync(db, remote); - }).then(function (result) { - result.pull.ok.should.equal(true); - result.pull.docs_read.should.equal(1); - result.pull.docs_written.should.equal(1); - result.pull.errors.should.have.length(0); - done(); - }, done); - }); - - it('db.sync event', function (done) { - var doc1 = { - _id: 'adoc', - foo: 'bar' - }; - var doc2 = { - _id: 'anotherdoc', - foo: 'baz' - }; - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - db.put(doc1, function (err) { - remote.put(doc2, function (err) { - db.sync(remote).on('complete', function (result) { - result.pull.ok.should.equal(true); - result.pull.docs_read.should.equal(1); - result.pull.docs_written.should.equal(1); - result.pull.errors.should.have.length(0); - done(); - }); - }); - }); - }); - - it('db.sync callback', function (done) { - var doc1 = { - _id: 'adoc', - foo: 'bar' - }; - var doc2 = { - _id: 'anotherdoc', - foo: 'baz' - }; - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - db.put(doc1, function (err) { - remote.put(doc2, function (err) { - db.sync(remote, function (err, result) { - result.pull.ok.should.equal(true); - result.pull.docs_read.should.equal(1); - result.pull.docs_written.should.equal(1); - result.pull.errors.should.have.length(0); - done(); - }); - }); - }); - }); - - it('db.sync promise', function (done) { - var doc1 = { - _id: 'adoc', - foo: 'bar' - }; - var doc2 = { - _id: 'anotherdoc', - foo: 'baz' - }; - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - db.put(doc1).then(function () { - return remote.put(doc2); - }).then(function () { - return db.sync(remote); - }).then(function (result) { - result.pull.ok.should.equal(true); - result.pull.docs_read.should.equal(1); - result.pull.docs_written.should.equal(1); - result.pull.errors.should.have.length(0); - done(); - }, done); - }); - - // Skipped due to https://github.com/daleharvey/pouchdb/issues/1409 - // This will only call once in the case of being cancelled before starting - // but will call twice when cancelled after starting - it('Test sync cancel', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var replications = db.sync(remote, { - complete: function (err, result) { - done(); - } - }); - should.exist(replications); - replications.cancel(); - return; - }); - - it('Test syncing two endpoints (issue 838)', function (done) { - var doc1 = { - _id: 'adoc', - foo: 'bar' - }; - var doc2 = { - _id: 'anotherdoc', - foo: 'baz' - }; - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - // Replication isn't finished until onComplete has been called twice - function onComplete() { - db.allDocs(function (err, res1) { - should.not.exist(err); - remote.allDocs(function (err, res2) { - should.not.exist(err); - res1.total_rows.should.equal(res2.total_rows); - done(); - }); - }); - } - db.put(doc1, function (err) { - remote.put(doc2, function (err) { - db.replicate.sync(remote).on('complete', onComplete); - }); - }); - }); - - it('Syncing should stop if one replication fails (issue 838)', - function (done) { - var doc1 = {_id: 'adoc', foo: 'bar'}; - var doc2 = {_id: 'anotherdoc', foo: 'baz'}; - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var replications = db.sync(remote, {live: true}); - - db.on('change', function (ch) { - if (ch.seq !== 1) { - done(true); - } - }); - - replications.on('cancel', function () { - remote.put(doc2, function () { - changes.should.equal(2); - done(); - }); - }); - - var changes = 0; - replications.on('change', function (ch) { - changes++; - if (changes === 2) { - replications.pull.cancel(); - } - }); - db.put(doc1); - }); - - it('Push and pull changes both fire (issue 2555)', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - var correct = false; - db.post({}).then(function () { - return remote.post({}); - }).then(function () { - var numChanges = 0; - var lastChange; - var sync = db.sync(remote); - sync.on('change', function (change) { - ['push', 'pull'].should.contain(change.direction); - change.change.docs_read.should.equal(1); - change.change.docs_written.should.equal(1); - if (!lastChange) { - lastChange = change.direction; - } else { - lastChange.should.not.equal(change.direction); - } - if (++numChanges === 2) { - correct = true; - sync.cancel(); - } - }).on('complete', function () { - correct.should.equal(true, 'things happened right'); - done(); - }); - }); - }); - - it('Doesn\'t have a memory leak (push)', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - - db.bulkDocs([{}, {}, {}]).then(function () { - return remote.bulkDocs([{}, {}, {}]); - }).then(function () { - var sync = db.replicate.to(remote); - sync.on('change', function () {}); - sync.on('error', function () {}); - sync.on('complete', function () { - setTimeout(function () { - Object.keys(sync._events).should.have.length(0); - done(); - }); - }); - }); - }); - - it('Doesn\'t have a memory leak (pull)', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - - db.bulkDocs([{}, {}, {}]).then(function () { - return remote.bulkDocs([{}, {}, {}]); - }).then(function () { - var sync = db.replicate.from(remote); - sync.on('change', function () {}); - sync.on('error', function () {}); - sync.on('complete', function () { - setTimeout(function () { - Object.keys(sync._events).should.have.length(0); - done(); - }); - }); - }); - }); - - it('Doesn\'t have a memory leak (bi)', function (done) { - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - - db.bulkDocs([{}, {}, {}]).then(function () { - return remote.bulkDocs([{}, {}, {}]); - }).then(function () { - var sync = db.sync(remote); - sync.on('change', function () {}); - sync.on('error', function () {}); - sync.on('complete', function () { - setTimeout(function () { - Object.keys(sync._events).should.have.length(0); - done(); - }); - }); - }); - }); - it('PouchDB.sync with strings for dbs', function (done) { - var doc1 = { - _id: 'adoc', - foo: 'bar' - }; - var doc2 = { - _id: 'anotherdoc', - foo: 'baz' - }; - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - db.put(doc1).then(function () { - return remote.put(doc2); - }).then(function () { - return PouchDB.sync(dbs.name, dbs.remote); - }).then(function (result) { - result.pull.ok.should.equal(true); - result.pull.docs_read.should.equal(1); - result.pull.docs_written.should.equal(1); - result.pull.errors.should.have.length(0); - done(); - }, done); - }); - }); -});
diff --git a/tests/integration/test.taskqueue.js b/tests/integration/test.taskqueue.js deleted file mode 100644 index ac3c9a1..0000000 --- a/tests/integration/test.taskqueue.js +++ /dev/null
@@ -1,71 +0,0 @@ -'use strict'; - -var adapters = ['http', 'local']; - -adapters.forEach(function (adapter) { - describe('test.taskqueue.js-' + adapter, function () { - - var dbs = {}; - - beforeEach(function (done) { - dbs.name = testUtils.adapterUrl(adapter, 'testdb'); - testUtils.cleanup([dbs.name], done); - }); - - after(function (done) { - testUtils.cleanup([dbs.name], done); - }); - - - it('Add a doc', function (done) { - var db = new PouchDB(dbs.name); - db.post({ test: 'somestuff' }, function (err, info) { - done(err); - }); - }); - - it('Query', function (done) { - var db = new PouchDB(dbs.name); - var queryFun = { - map: function (doc) { - } - }; - db.query(queryFun, { reduce: false }, function (_, res) { - res.rows.should.have.length(0); - done(); - }); - }); - - it('Bulk docs', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs({ - docs: [ - { test: 'somestuff' }, - { test: 'another' } - ] - }, function (err, infos) { - should.not.exist(infos[0].error); - should.not.exist(infos[1].error); - done(); - }); - }); - - it('Get', function (done) { - var db = new PouchDB(dbs.name); - db.get('0', function (err, res) { - should.exist(err); - done(); - }); - }); - - it('Info', function (done) { - var db = new PouchDB(dbs.name); - db.info(function (err, info) { - info.doc_count.should.equal(0); - info.update_seq.should.equal(0); - done(); - }); - }); - - }); -});
diff --git a/tests/integration/test.uuids.js b/tests/integration/test.uuids.js deleted file mode 100644 index e1fde4c..0000000 --- a/tests/integration/test.uuids.js +++ /dev/null
@@ -1,68 +0,0 @@ -'use strict'; -/* jshint maxlen: false */ -var rfcRegexp = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/; - -function makeUuids(count, length, radix) { - count = count || 1; - var i = -1; - var out = []; - while (++i < count) { - out.push(PouchDB.utils.uuid(length, radix)); - } - return out; -} - -describe('test.uuid.js', function () { - - it('UUID RFC4122 test', function () { - rfcRegexp.test(makeUuids()[0]).should - .equal(true, 'Single UUID complies with RFC4122.'); - rfcRegexp.test(PouchDB.utils.uuid()).should - .equal(true, - 'Single UUID through Pouch.utils.uuid complies with RFC4122.'); - }); - - it('UUID generation uniqueness', function () { - var count = 1000; - var uuids = makeUuids(count); - testUtils.eliminateDuplicates(uuids).should.have - .length(count, 'Generated UUIDS are unique.'); - }); - - it('Test small uuid uniqness', function () { - var length = 8; - var count = 2000; - var uuids = makeUuids(count, length); - testUtils.eliminateDuplicates(uuids).should.have - .length(count, 'Generated small UUIDS are unique.'); - }); - - it('Test custom length', function () { - var length = 32; - var count = 10; - var uuids = makeUuids(count, length); - // Test single UUID wrapper - uuids.push(PouchDB.utils.uuid(length)); - uuids.map(function (uuid) { - uuid.should.have.length(length, 'UUID length is correct.'); - }); - }); - - it('Test custom length, redix', function () { - var length = 32; - var count = 10; - var radix = 5; - var uuids = makeUuids(count, length, radix); - // Test single UUID wrapper - uuids.push(PouchDB.utils.uuid(length, radix)); - uuids.map(function (uuid) { - var nums = uuid.split('').map(function (character) { - return parseInt(character, radix); - }); - var max = Math.max.apply(Math, nums); - var min = Math.min.apply(Math, nums); - max.should.be.below(radix, 'Maximum character is less than radix'); - min.should.be.at.least(0, 'Min character is greater than or equal to 0'); - }); - }); -});
diff --git a/tests/integration/test.views.js b/tests/integration/test.views.js deleted file mode 100644 index 4233bb0..0000000 --- a/tests/integration/test.views.js +++ /dev/null
@@ -1,684 +0,0 @@ -/*jshint expr:true */ -'use strict'; - -var adapters = [ - ['local', 'http'], -]; - -adapters.forEach(function (adapters) { - describe('test.views.js-' + adapters[0] + '-' + adapters[1], function () { - - var dbs = {}; - - beforeEach(function (done) { - dbs.name = testUtils.adapterUrl(adapters[0], 'testdb'); - dbs.remote = testUtils.adapterUrl(adapters[1], 'test_repl_remote'); - testUtils.cleanup([dbs.name, dbs.remote], done); - }); - - after(function (done) { - testUtils.cleanup([dbs.name, dbs.remote], done); - }); - - - it('Test basic view', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs({ - docs: [ - { foo: 'bar' }, - { - _id: 'volatile', - foo: 'baz' - } - ] - }, {}, function () { - var queryFun = { - map: function (doc) { - emit(doc.foo, doc); - } - }; - db.get('volatile', function (_, doc) { - db.remove(doc, function (_, resp) { - db.query(queryFun, { - include_docs: true, - reduce: false - }, function (_, res) { - res.rows.should.have.length(1, 'Dont include deleted documents'); - res.total_rows.should.equal(1, 'Include total_rows property.'); - res.rows.forEach(function (x, i) { - x.id.should.exist; - x.key.should.exist; - x.value._rev.should.exist; - x.doc._rev.should.exist; - }); - done(); - }); - }); - }); - }); - }); - - it('Test passing just a function', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs({ - docs: [ - { foo: 'bar' }, - { - _id: 'volatile', - foo: 'baz' - } - ] - }, {}, function () { - var queryFun = function (doc) { - emit(doc.foo, doc); - }; - db.get('volatile', function (_, doc) { - db.remove(doc, function (_, resp) { - db.query(queryFun, { - include_docs: true, - reduce: false - }, function (_, res) { - res.rows.should.have.length(1, 'Dont include deleted documents'); - res.rows.forEach(function (x, i) { - x.id.should.exist; - x.key.should.exist; - x.value._rev.should.exist; - x.doc._rev.should.exist; - }); - done(); - }); - }); - }); - }); - }); - - it('Test opts.startkey/opts.endkey', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs({ - docs: [ - { key: 'key1' }, - { key: 'key2' }, - { key: 'key3' }, - { key: 'key4' }, - { key: 'key5' } - ] - }, {}, function () { - var queryFun = { - map: function (doc) { - emit(doc.key, doc); - } - }; - db.query(queryFun, { - reduce: false, - startkey: 'key2' - }, function (_, res) { - res.rows.should.have.length(4, 'Startkey is inclusive'); - db.query(queryFun, { - reduce: false, - endkey: 'key3' - }, function (_, res) { - res.rows.should.have.length(3, 'Endkey is inclusive'); - db.query(queryFun, { - reduce: false, - startkey: 'key2', - endkey: 'key3' - }, function (_, res) { - res.rows.should.have.length(2, 'Startkey and endkey together'); - db.query(queryFun, { - reduce: false, - startkey: 'key4', - endkey: 'key4' - }, function (_, res) { - res.rows.should.have.length(1, 'Startkey=endkey'); - done(); - }); - }); - }); - }); - }); - }); - - it('Test opts.key', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs({ - docs: [ - { key: 'key1' }, - { key: 'key2' }, - { key: 'key3' }, - { key: 'key3' } - ] - }, {}, function () { - var queryFun = { - map: function (doc) { - emit(doc.key, doc); - } - }; - db.query(queryFun, { - reduce: false, - key: 'key2' - }, function (_, res) { - res.rows.should.have.length(1, 'Doc with key'); - db.query(queryFun, { - reduce: false, - key: 'key3' - }, function (_, res) { - res.rows.should.have.length(2, 'Multiple docs with key'); - done(); - }); - }); - }); - }); - - it.skip('Test basic view collation', function (done) { - var values = []; - // special values sort before all other types - values.push(null); - values.push(false); - values.push(true); - // then numbers - values.push(1); - values.push(2); - values.push(3); - values.push(4); - // then text, case sensitive - // currently chrome uses ascii ordering and so wont handle - // capitals properly - values.push('a'); - //values.push("A"); - values.push('aa'); - values.push('b'); - //values.push("B"); - values.push('ba'); - values.push('bb'); - // then arrays. compared element by element until different. - // Longer arrays sort after their prefixes - values.push(['a']); - values.push(['b']); - values.push([ - 'b', - 'c' - ]); - values.push([ - 'b', - 'c', - 'a' - ]); - values.push([ - 'b', - 'd' - ]); - values.push([ - 'b', - 'd', - 'e' - ]); - // then object, compares each key value in the list until different. - // larger objects sort after their subset objects. - values.push({ a: 1 }); - values.push({ a: 2 }); - values.push({ b: 1 }); - values.push({ b: 2 }); - values.push({ - b: 2, - a: 1 - }); - // Member order does matter for collation. - // CouchDB preserves member order - // but doesn't require that clients will. - // (this test might fail if used with a js engine - // that doesn't preserve order) - values.push({ - b: 2, - c: 2 - }); - var db = new PouchDB(dbs.name); - var docs = values.map(function (x, i) { - return { - _id: i.toString(), - foo: x - }; - }); - db.bulkDocs({ docs: docs }, {}, function (err) { - var queryFun = { - map: function (doc) { - emit(doc.foo, null); - } - }; - if (err) { - done(err); - } - db.query(queryFun, { reduce: false }, function (err, res) { - if (err) { - done(err); - } - res.rows.forEach(function (x, i) { - x.key.should.deep.equal(values[i], 'keys collate'); - }); - db.query(queryFun, { - descending: true, - reduce: false - }, function (err, res) { - if (err) { - done(err); - } - res.rows.forEach(function (x, i) { - x.key.should.deep - .equal(values[values.length - 1 - i], - 'keys collate descending'); - }); - done(); - }); - }); - }); - }); - - it('Test joins', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs({ - docs: [ - { - _id: 'mydoc', - foo: 'bar' - }, - { doc_id: 'mydoc' } - ] - }, {}, function () { - var queryFun = { - map: function (doc) { - if (doc.doc_id) { - emit(doc._id, { _id: doc.doc_id }); - } - } - }; - db.query(queryFun, { - include_docs: true, - reduce: false - }, function (_, res) { - res.rows[0].doc.should.exist; - res.rows[0].doc._id.should.equal('mydoc', 'mydoc included'); - done(); - }); - }); - }); - - it('No reduce function', function (done) { - var db = new PouchDB(dbs.name); - db.post({ foo: 'bar' }, function (err, res) { - var queryFun = { - map: function (doc) { - emit('key', 'val'); - } - }; - db.query(queryFun, function (err, res) { - done(); - }); - }); - }); - - it('Built in _sum reduce function', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs({ - docs: [ - { val: 'bar' }, - { val: 'bar' }, - { val: 'baz' } - ] - }, null, function () { - var queryFun = { - map: function (doc) { - emit(doc.val, 1); - }, - reduce: '_sum' - }; - db.query(queryFun, { - reduce: true, - group_level: 999 - }, function (err, res) { - res.rows.should.have.length(2); - res.rows[0].value.should.equal(2); - res.rows[1].value.should.equal(1); - done(); - }); - }); - }); - - it('Built in _count reduce function', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs({ - docs: [ - { val: 'bar' }, - { val: 'bar' }, - { val: 'baz' } - ] - }, null, function () { - var queryFun = { - map: function (doc) { - emit(doc.val, doc.val); - }, - reduce: '_count' - }; - db.query(queryFun, { - reduce: true, - group_level: 999 - }, function (err, res) { - res.rows.should.have.length(2); - res.rows[0].value.should.equal(2); - res.rows[1].value.should.equal(1); - done(); - }); - }); - }); - - it('Built in _stats reduce function', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs({ - docs: [ - { val: 'bar' }, - { val: 'bar' }, - { val: 'baz' } - ] - }, null, function () { - var queryFun = { - map: function (doc) { - emit(doc.val, 1); - }, - reduce: '_stats' - }; - db.query(queryFun, { - reduce: true, - group_level: 999 - }, function (err, res) { - var stats = res.rows[0].value; - stats.sum.should.equal(2); - stats.count.should.equal(2); - stats.min.should.equal(1); - stats.max.should.equal(1); - stats.sumsqr.should.equal(2); - done(); - }); - }); - }); - - it('No reduce function, passing just a function', function (done) { - var db = new PouchDB(dbs.name); - db.post({ foo: 'bar' }, function (err, res) { - var queryFun = function (doc) { - emit('key', 'val'); - }; - db.query(queryFun, function (err, res) { - done(); - }); - }); - }); - - it('Views should include _conflicts', function (done) { - var doc1 = { - _id: '1', - foo: 'bar' - }; - var doc2 = { - _id: '1', - foo: 'baz' - }; - var queryFun = function (doc) { - emit(doc._id, !!doc._conflicts); - }; - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - db.post(doc1, function (err, res) { - remote.post(doc2, function (err, res) { - db.replicate.from(remote, function (err, res) { - db.get(doc1._id, { conflicts: true }, function (err, res) { - res._conflicts.should.exist; - db.query(queryFun, function (err, res) { - res.rows[0].value.should.exist; - done(); - }); - }); - }); - }); - }); - }); - - it('Map only documents with _conflicts (#1000)', function (done) { - var docs1 = [ - { - _id: '1', - foo: 'bar' - }, - { - _id: '2', - name: 'two' - } - ]; - var doc2 = { - _id: '1', - foo: 'baz' - }; - var queryFun = function (doc) { - if (doc._conflicts) { - emit(doc._id, doc._conflicts); - } - }; - var db = new PouchDB(dbs.name); - var remote = new PouchDB(dbs.remote); - db.bulkDocs({ docs: docs1 }, function (err, res) { - var revId1 = res[0].rev; - remote.post(doc2, function (err, res) { - var revId2 = res.rev; - db.replicate.from(remote, function (err, res) { - db.get(docs1[0]._id, { conflicts: true }, function (err, res) { - var winner = res._rev; - var looser = winner === revId1 ? revId2 : revId1; - res._conflicts.should.exist; - db.query(queryFun, function (err, res) { - res.rows.should.have.length(1, 'One doc with conflicts'); - res.rows[0].key.should - .equal('1', 'Correct document with conflicts.'); - res.rows[0].value.should.deep - .equal([looser], 'Correct conflicts included.'); - done(); - }); - }); - }); - }); - }); - }); - - it('Test view querying with limit option', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs({ - docs: [ - { foo: 'bar' }, - { foo: 'bar' }, - { foo: 'baz' } - ] - }, null, function () { - db.query(function (doc) { - if (doc.foo === 'bar') { - emit(doc.foo); - } - }, { limit: 1 }, function (err, res) { - res.total_rows.should.equal(2, 'Correctly returns total rows'); - res.rows.should.have.length(1, 'Correctly limits returned rows'); - done(); - }); - }); - }); - - it('Query non existing view returns error', function (done) { - var db = new PouchDB(dbs.name); - var doc = { - _id: '_design/barbar', - views: - { scores: - { map: 'function (doc) { if (doc.score) ' + - '{ emit(null, doc.score); } }' } } - }; - db.post(doc, function (err, info) { - db.query('barbar/dontExist', { key: 'bar' }, function (err, res) { - if (!err.name) { - err.name = err.error; - err.message = err.reason; - } - err.name.should.be.a('string'); - err.message.should.be.a('string'); - done(); - }); - }); - }); - - it('Special document member _doc_id_rev', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs({ docs: [{ foo: 'bar' }] }, null, function () { - db.query(function (doc) { - if (doc.foo === 'bar') { - emit(doc.foo); - } - }, { include_docs: true }, function (err, res) { - should.not.exist(res.rows[0].doc._doc_id_rev); - done(); - }); - }); - }); - - it('If reduce function returns 0', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs({ docs: [{ foo: 'bar' }] }, null, function () { - db.query({ - map: function (doc) { - emit(doc.foo); - }, - reduce: function (key, values, rereduce) { - return 0; - } - }, function (err, data) { - should.not.equal(data.rows[0].value, null, 'value is null'); - done(); - }); - }); - }); - - it('Testing skip with a view', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs({ - docs: [ - { foo: 'bar' }, - { foo: 'baz' }, - { foo: 'baf' } - ] - }, null, function () { - db.query(function (doc) { - emit(doc.foo, null); - }, { skip: 1 }, function (err, data) { - should.not.exist(err); - data.rows.should.have.length(2); - done(); - }); - }); - }); - - it('Testing skip with allDocs', function (done) { - var db = new PouchDB(dbs.name); - db.bulkDocs({ - docs: [ - { foo: 'bar' }, - { foo: 'baz' }, - { foo: 'baf' } - ] - }, null, function () { - db.allDocs({ skip: 1 }, function (err, data) { - should.not.exist(err); - data.rows.should.have.length(2); - done(); - }); - }); - }); - - it('Map documents on 0/null/undefined/empty string', function (done) { - var db = new PouchDB(dbs.name); - var docs = [ - { - _id: 'doc0', - num: 0 - }, - { - _id: 'doc1', - num: 1 - }, - { _id: 'doc2' }, - { - _id: 'doc3', - num: null - }, - { - _id: 'doc4', - num: '' - } - ]; - db.bulkDocs({ docs: docs }, function (err) { - var mapFunction = function (doc) { - emit(doc.num, null); - }; - db.query(mapFunction, { - key: 0, - include_docs: true - }, function (err, data) { - data.rows.should.have.length(1); - data.rows[0].doc._id.should.equal('doc0'); - }); - db.query(mapFunction, { - key: null, - include_docs: true - }, function (err, data) { - data.rows.should.have.length(2); - data.rows[0].doc._id.should.equal('doc2'); - data.rows[1].doc._id.should.equal('doc3'); - }); - db.query(mapFunction, { - key: '', - include_docs: true - }, function (err, data) { - data.rows.should.have.length(1); - data.rows[0].doc._id.should.equal('doc4'); - }); - db.query(mapFunction, { - key: undefined, - include_docs: true - }, function (err, data) { - data.rows.should.have.length(5); - // everything - done(); - }); - }); - }); - if (typeof process !== 'undefined' && !process.browser) { - var fs = require('fs'); - it("destroy using prototype", function () { - return new PouchDB(dbs.name + 1).then(function (db) { - var doc = { - _id: '_design/barbar', - views: { - scores: { - map: function (doc) { - if (doc.score) { - emit(null, doc.score); - } - }.toString(), - reduce: '_sum' - }, - } - }; - return db.bulkDocs([doc, {score: 3}, {score: 5}]).then(function () { - return db.query('barbar/scores'); - }).then(function (a) { - a.rows[0].value.should.equal(8); - return db.destroy(); - }).then(function (a) { - fs.readdirSync('./tmp').should.have.length(0); - }); - }); - }); - } - }); -});
diff --git a/tests/integration/utils.js b/tests/integration/utils.js deleted file mode 100644 index a742451..0000000 --- a/tests/integration/utils.js +++ /dev/null
@@ -1,389 +0,0 @@ -/* global PouchDB */ -/* jshint -W079 */ -'use strict'; - -var testUtils = {}; - -function uniq(list) { - var map = {}; - list.forEach(function (item) { - map[item] = true; - }); - return Object.keys(map); -} - -testUtils.isCouchMaster = function () { - return 'SERVER' in testUtils.params() && - testUtils.params().SERVER === 'couchdb-master'; -}; - -testUtils.params = function () { - if (typeof module !== 'undefined' && module.exports) { - return process.env; - } - var paramStr = document.location.search.slice(1); - return paramStr.split('&').reduce(function (acc, val) { - if (!val) { - return acc; - } - var tmp = val.split('='); - acc[tmp[0]] = tmp[1] || true; - return acc; - }, {}); -}; - -testUtils.couchHost = function () { - if (typeof module !== 'undefined' && module.exports) { - return process.env.COUCH_HOST || 'http://localhost:5984'; - } else if (window && window.COUCH_HOST) { - return window.COUCH_HOST; - } else if (window && window.cordova) { - // magic route to localhost on android emulator - return 'http://10.0.2.2:2020'; - } - // In the browser we default to the CORS server, in future will change - return 'http://localhost:2020'; -}; - -testUtils.makeBlob = function (data, type) { - if (typeof module !== 'undefined' && module.exports) { - return new Buffer(data, 'binary'); - } else { - return PouchDB.utils.createBlob([data], { type: type }); - } -}; - -testUtils.readBlob = function (blob, callback) { - if (typeof module !== 'undefined' && module.exports) { - callback(blob.toString('binary')); - } else { - var reader = new FileReader(); - reader.onloadend = function (e) { - - var binary = ""; - var bytes = new Uint8Array(this.result || ''); - var length = bytes.byteLength; - - for (var i = 0; i < length; i++) { - binary += String.fromCharCode(bytes[i]); - } - - callback(binary); - }; - reader.readAsArrayBuffer(blob); - } -}; - -testUtils.base64Blob = function (blob, callback) { - if (typeof module !== 'undefined' && module.exports) { - callback(blob.toString('base64')); - } else { - testUtils.readBlob(blob, function (binary) { - callback(PouchDB.utils.btoa(binary)); - }); - } -}; - -// Prefix http adapter database names with their host and -// node adapter ones with a db location -testUtils.adapterUrl = function (adapter, name) { - if (adapter === 'http') { - return testUtils.couchHost() + '/' + name; - } - return name; -}; - -// Delete specified databases -testUtils.cleanup = function (dbs, done) { - - dbs = uniq(dbs); - - var deleted = 0; - var num = dbs.length; - var errors = []; - - function dbDeleted(err, res) { - // 400 is for an unexpected return from CouchDB, filed - // https://issues.apache.org/jira/browse/COUCHDB-2205 - if (err && (err.status !== 404 && err.status !== 400)) { - errors.push(err); - } - if (++deleted === num) { - if (errors.length > 0) { - // TODO: report all the errors - done(errors[0]); - } else { - done(); - } - } - } - - dbs.forEach(function (db) { - PouchDB.destroy(db, dbDeleted); - }); -}; - -// Put doc after prevRev (so that doc is a child of prevDoc -// in rev_tree). Doc must have _rev. If prevRev is not specified -// just insert doc with correct _rev (new_edits=false!) -testUtils.putAfter = function (db, doc, prevRev, callback) { - var newDoc = PouchDB.extend({}, doc); - if (!prevRev) { - db.put(newDoc, { new_edits: false }, callback); - return; - } - newDoc._revisions = { - start: +newDoc._rev.split('-')[0], - ids: [ - newDoc._rev.split('-')[1], - prevRev.split('-')[1] - ] - }; - db.put(newDoc, { new_edits: false }, callback); -}; - -// docs will be inserted one after another -// starting from root -testUtils.putBranch = function (db, docs, callback) { - function insert(i) { - var doc = docs[i]; - var prev = i > 0 ? docs[i - 1]._rev : null; - function next() { - if (i < docs.length - 1) { - insert(i + 1); - } else { - callback(); - } - } - db.get(doc._id, { rev: doc._rev }, function (err, ok) { - if (err) { - testUtils.putAfter(db, docs[i], prev, function (err, doc) { - next(); - }); - } else { - next(); - } - }); - } - insert(0); -}; - -testUtils.putTree = function (db, tree, callback) { - function insert(i) { - var branch = tree[i]; - testUtils.putBranch(db, branch, function () { - if (i < tree.length - 1) { - insert(i + 1); - } else { - callback(); - } - }); - } - insert(0); -}; - -testUtils.isCouchDB = function (cb) { - PouchDB.ajax({url: testUtils.couchHost() + '/' }, function (err, res) { - cb('couchdb' in res); - }); -}; - -testUtils.writeDocs = function (db, docs, callback, res) { - if (!res) { - res = []; - } - if (!docs.length) { - return callback(null, res); - } - var doc = docs.shift(); - db.put(doc, function (err, info) { - res.push(info); - testUtils.writeDocs(db, docs, callback, res); - }); -}; - -// Borrowed from: http://stackoverflow.com/a/840849 -testUtils.eliminateDuplicates = function (arr) { - var i, element, len = arr.length, out = [], obj = {}; - for (i = 0; i < len; i++) { - obj[arr[i]] = 0; - } - for (element in obj) { - if (obj.hasOwnProperty(element)) { - out.push(element); - } - } - return out; -}; - -// ---- CORS Specific Utils ---- // -//enable CORS on server -testUtils.enableCORS = function (dburl, callback) { - var host = 'http://' + dburl.split('/')[2] + '/'; - PouchDB.ajax({ - url: host + '_config/httpd/enable_cors', - json: false, - method: 'PUT', - body: '"true"' - }, function (err, resBody, req) { - PouchDB.ajax({ - url: host + '_config/cors/origins', - json: false, - method: 'PUT', - body: '"http://127.0.0.1:8000"' - }, function (err, resBody, req) { - callback(err, req); - }); - }); -}; -//enable CORS Credentials on server -testUtils.enableCORSCredentials = function (dburl, callback) { - var host = 'http://' + dburl.split('/')[2] + '/'; - PouchDB.ajax({ - url: host + '_config/cors/credentials', - method: 'PUT', - body: '"true"', - json: false - }, function (err, resBody, req) { - callback(err, req); - }); -}; -//disable CORS -testUtils.disableCORS = function (dburl, callback) { - var host = 'http://' + dburl.split('/')[2] + '/'; - PouchDB.ajax({ - url: host + '_config/cors/origins', - json: false, - method: 'PUT', - body: '"*"' - }, function (err, resBody, req) { - PouchDB.ajax({ - url: host + '_config/httpd/enable_cors', - json: false, - method: 'PUT', - body: '"false"' - }, function (err, resBody, req) { - callback(err, req); - }); - }); -}; -//disable CORS Credentials -testUtils.disableCORSCredentials = function (dburl, callback) { - var host = 'http://' + dburl.split('/')[2] + '/'; - PouchDB.ajax({ - url: host + '_config/cors/credentials', - method: 'PUT', - body: '"false"', - json: false - }, function (err, resBody, req) { - callback(err, req); - }); -}; -//create admin user and member user -testUtils.setupAdminAndMemberConfig = function (dburl, callback) { - var host = 'http://' + dburl.split('/')[2] + '/'; - PouchDB.ajax({ - url: host + '_users/org.couchdb.user:TestUser', - method: 'PUT', - body: { - _id: 'org.couchdb.user:TestUser', - name: 'TestUser', - password: 'user', - roles: [], - type: 'user' - } - }, function (err, resBody, req) { - PouchDB.ajax({ - url: host + '_config/admins/TestAdmin', - json: false, - method: 'PUT', - body: '"admin"' - }, function (err, resBody, req) { - callback(err, req); - }); - }); -}; -//delete admin and member user -testUtils.tearDownAdminAndMemberConfig = function (dburl, callback) { - var host = 'http://' + dburl.split('/')[2] + '/'; - var headers = {}; - var token = btoa('TestAdmin:admin'); - headers.Authorization = 'Basic ' + token; - PouchDB.ajax({ - url: host + '_config/admins/TestAdmin', - method: 'DELETE', - headers: headers, - json: false - }, function (err, resBody, req) { - PouchDB.ajax({ - url: host + '_users/org.couchdb.user:TestUser', - method: 'GET', - body: '"admin"' - }, function (err, resBody, req) { - if (resBody) { - PouchDB.ajax({ - url: host + '_users/org.couchdb.user:TestUser?rev=' + resBody._rev, - method: 'DELETE', - json: false - }, function (err, resBody, req) { - callback(err, req); - }); - } else { - callback(err, req); - } - }); - }); -}; -testUtils.deleteCookieAuth = function (dburl, callback_) { - var host = 'http://' + dburl.split('/')[2] + '/'; - PouchDB.ajax({ - method: 'DELETE', - url: host + '_session', - withCredentials: true, - json: false - }, callback_); -}; -testUtils.cleanUpCors = function (dburl, callback_) { - if (testUtils.PERSIST_DATABASES) { - return; - } - if (typeof module !== 'undefined' && module.exports) { - testUtils.disableCORS(dburl, function () { - PouchDB.destroy(dburl, callback_); - }); - } else { - testUtils.disableCORS(dburl.replace('5984', '2020'), function () { - PouchDB.destroy(dburl.replace('5984', '2020'), callback_); - }); - } -}; -var testDir; -if (typeof module !== 'undefined' && module.exports) { - global.PouchDB = require('../../lib'); - if (process.env.LEVEL_ADAPTER || process.env.LEVEL_PREFIX) { - var defaults = {}; - - if (process.env.LEVEL_ADAPTER) { - defaults.db = require(process.env.LEVEL_ADAPTER); - console.log('Using client-side leveldown adapter: ' + - process.env.LEVEL_ADAPTER); - } - if (process.env.LEVEL_PREFIX) { - defaults.prefix = process.env.LEVEL_PREFIX; - console.log('Using client-side leveldown prefix: ' + defaults.prefix); - } - global.PouchDB = global.PouchDB.defaults(defaults); - } else if (process.env.AUTO_COMPACTION) { - global.PouchDB = global.PouchDB.defaults({auto_compaction: true}); - } - if (typeof process !== 'undefined') { - testDir = process.env.TESTS_DIR ? process.env.TESTS_DIR : './tmp'; - testDir = testDir.slice(-1) === '/' ? testDir : testDir + '/'; - global.PouchDB.prefix = testDir + global.PouchDB.prefix; - require('../../lib/adapters/leveldb').use_prefix = true; - require('bluebird').onPossiblyUnhandledRejection(function (e, promise) { - throw e; - }); - } - module.exports = testUtils; -}
diff --git a/tests/integration/webrunner.js b/tests/integration/webrunner.js deleted file mode 100644 index 7049d67..0000000 --- a/tests/integration/webrunner.js +++ /dev/null
@@ -1,137 +0,0 @@ -/* global mocha: true */ - -'use strict'; - -// use query parameter pluginFile if present, -// eg: test.html?pluginFile=memory.pouchdb.js -var preferredAdapters = window.location.search.match(/[?&]adapters=([^&]+)/); -var scriptsToLoad = ['../../dist/pouchdb.js']; -if (preferredAdapters) { - preferredAdapters = preferredAdapters[1].split(','); - preferredAdapters.forEach(function (adapter) { - if (adapter !== 'websql' && adapter !== 'idb') { - // load from plugin - scriptsToLoad.push('../../dist/pouchdb.' + adapter + '.js'); - } - }); -} - -// Thanks to http://engineeredweb.com/blog/simple-async-javascript-loader/ -function asyncLoadScript(url, callback) { - - // Create a new script and setup the basics. - var script = document.createElement("script"), - firstScript = document.getElementsByTagName('script')[0]; - - script.async = true; - script.src = url; - - // Handle the case where an optional callback was passed in. - if ("function" === typeof(callback)) { - script.onload = function () { - callback(); - - // Clear it out to avoid getting called more than once or any - // memory leaks. - script.onload = script.onreadystatechange = undefined; - }; - script.onreadystatechange = function () { - if ("loaded" === script.readyState || "complete" === script.readyState) { - script.onload(); - } - }; - } - - // Attach the script tag to the page (before the first script) so the - //magic can happen. - firstScript.parentNode.insertBefore(script, firstScript); -} - -function modifyGlobals() { - if (preferredAdapters) { - window.PouchDB.preferredAdapters = preferredAdapters; - } - if (window.location.search.indexOf('autoCompaction') !== -1) { - window.PouchDB = window.PouchDB.defaults({auto_compaction: true}); - } -} - -function startTests() { - - function loadNext() { - if (scriptsToLoad.length) { - var script = scriptsToLoad.shift(); - asyncLoadScript(script, loadNext); - } else { - onReady(); - } - } - - function onReady() { - modifyGlobals(); - var runner = mocha.run(); - window.results = { - lastPassed: '', - passed: 0, - failed: 0, - failures: [] - }; - - runner.on('pass', function (e) { - window.results.lastPassed = e.title; - window.results.passed++; - }); - - runner.on('fail', function (e) { - window.results.failed++; - window.results.failures.push({ - title: e.title, - message: e.err.message, - stack: e.err.stack - }); - }); - - runner.on('end', function () { - window.results.completed = true; - window.results.passed++; - }); - } - - loadNext(); -} - -if (window.cordova) { - var hasGrep = window.GREP && - window.location.search.indexOf('grep=') === -1; - var hasEs5Shim = window.ES5_SHIM && - window.location.search.indexOf('es5Shim=') === -1; - var hasAutoCompaction = window.AUTO_COMPACTION && - window.location.search.indexOf('autoCompaction') === -1; - var hasAdapters = window.ADAPTERS && - window.location.search.indexOf('adapters=') === -1; - - if (hasGrep || hasEs5Shim || hasAutoCompaction || hasAdapters) { - var params = []; - if (hasGrep) { - params.push('grep=' + encodeURIComponent(window.GREP)); - } - if (hasEs5Shim) { - params.push('es5Shim=' + encodeURIComponent(window.ES5_SHIM)); - } - if (hasAutoCompaction) { - params.push('autoCompaction=' + - encodeURIComponent(window.AUTO_COMPACTION)); - } - if (hasAdapters) { - params.push('adapters=' + encodeURIComponent(window.ADAPTERS)); - } - window.location.search += (window.location.search ? '&' : '?') + - params.join('&'); - } else { - document.addEventListener("deviceready", startTests, false); - } -} else { - startTests(); -} - -
diff --git a/tests/integration/worker.js b/tests/integration/worker.js deleted file mode 100644 index 071c446..0000000 --- a/tests/integration/worker.js +++ /dev/null
@@ -1,40 +0,0 @@ -/* jshint worker: true */ -'use strict'; - -function bigTest(name) { - new PouchDB(name, function (err, db) { - if (err) { - throw err; - } - db.post({ - _id: 'blablah', - key: 'lala' - }, function (err) { - if (err) { - throw err; - } - db.get('blablah', function (err, doc) { - if (err) { - throw err; - } - self.postMessage(doc.key); - PouchDB.destroy(name); - }); - }); - }); -} - -self.addEventListener('message', function (e) { - if (typeof e.data === 'string' && e.data.indexOf('/dist/') > -1) { - importScripts(e.data); - } - if (e.data === 'ping') { - self.postMessage('pong'); - } - if (e.data === 'version') { - self.postMessage(PouchDB.version); - } - if (Array.isArray(e.data) && e.data[0] === 'create') { - bigTest(e.data[1]); - } -});
diff --git a/tests/misc/pouchdb-express-router.js b/tests/misc/pouchdb-express-router.js deleted file mode 100644 index 5923b7d..0000000 --- a/tests/misc/pouchdb-express-router.js +++ /dev/null
@@ -1,9 +0,0 @@ -'use strict'; - -var express = require('express'); -var app = express(); -var PouchDB = require('../../'); - -app.use(require('pouchdb-express-router')(PouchDB)); - -app.listen(3000);
diff --git a/tests/performance/index.html b/tests/performance/index.html deleted file mode 100644 index 8a233ee..0000000 --- a/tests/performance/index.html +++ /dev/null
@@ -1,14 +0,0 @@ -<!doctype html> -<html> - <head> - <meta charset="utf-8"> - </head> - <body> - <pre style="width: 100%; height: 100%;" id="output"></pre> - <script src="/dist/pouchdb.js"></script> - <script src="/dist/pouchdb.localstorage.js"></script> - <script src="/dist/pouchdb.idb-alt.js"></script> - <script src="/dist/pouchdb.memory.js"></script> - <script src="../performance-bundle.js"></script> - </body> -</html>
diff --git a/tests/performance/index.js b/tests/performance/index.js deleted file mode 100644 index 9e7b9ad..0000000 --- a/tests/performance/index.js +++ /dev/null
@@ -1,47 +0,0 @@ - -'use strict'; - -var opts = {}; - -function runTestSuites(PouchDB) { - var reporter = require('./perf.reporter'); - reporter.log('Testing PouchDB version ' + PouchDB.version + - (opts.adapter ? (', using adapter: ' + opts.adapter) : '') + - '\n\n'); - - require('./perf.basics')(PouchDB, opts); - require('./perf.views')(PouchDB, opts); -} -var startNow = true; -if (global.window && global.window.location && global.window.location.search) { - - var fragment = global.window.location.search.replace(/^\??/, '').split('&'); - var params = {}; - fragment.forEach(function (param) { - var keyValue = param.split('='); - params[keyValue[0]] = decodeURIComponent(keyValue[1]); - }); - - if ('adapter' in params) { - opts.adapter = params.adapter; - } - - if ('src' in params) { - - var script = global.document.createElement('script'); - script.src = params.src; - global.document.getElementsByTagName('body')[0].appendChild(script); - - var timeoutId = setInterval(function () { - if (global.window.PouchDB) { - clearInterval(timeoutId); - runTestSuites(global.window.PouchDB); - } - }, 100); - startNow = false; - } -} -if (startNow) { - var PouchDB = process.browser ? window.PouchDB : require('../..'); - runTestSuites(PouchDB); -}
diff --git a/tests/performance/perf.basics.js b/tests/performance/perf.basics.js deleted file mode 100644 index ff4fc39..0000000 --- a/tests/performance/perf.basics.js +++ /dev/null
@@ -1,110 +0,0 @@ -'use strict'; - -module.exports = function (PouchDB, opts) { - - // need to use bluebird for promises everywhere, so we're comparing - // apples to apples - var Promise = require('bluebird'); - - var utils = require('./utils'); - - function createDocId(i) { - var intString = i.toString(); - while (intString.length < 10) { - intString = '0' + intString; - } - return 'doc_' + intString; - } - - var testCases = [ - { - name: 'basic-inserts', - assertions: 1, - iterations: 1000, - setup: function (db, callback) { - callback(null, {'yo': 'dawg'}); - }, - test: function (db, itr, doc, done) { - db.post(doc, done); - } - }, { - name: 'bulk-inserts', - assertions: 1, - iterations: 100, - setup: function (db, callback) { - var docs = []; - for (var i = 0; i < 100; i++) { - docs.push({much : 'docs', very : 'bulk'}); - } - callback(null, {docs : docs}); - }, - test: function (db, itr, docs, done) { - db.bulkDocs(docs, done); - } - }, { - name: 'basic-gets', - assertions: 1, - iterations: 10000, - setup: function (db, callback) { - var docs = []; - for (var i = 0; i < 10000; i++) { - docs.push({_id : createDocId(i), foo : 'bar', baz : 'quux'}); - } - db.bulkDocs({docs : docs}, callback); - }, - test: function (db, itr, docs, done) { - db.get(createDocId(itr), done); - } - }, { - name: 'all-docs-skip-limit', - assertions: 1, - iterations: 50, - setup: function (db, callback) { - var docs = []; - for (var i = 0; i < 1000; i++) { - docs.push({_id : createDocId(i), foo : 'bar', baz : 'quux'}); - } - db.bulkDocs({docs : docs}, callback); - }, - test: function (db, itr, docs, done) { - var tasks = []; - for (var i = 0; i < 10; i++) { - tasks.push(i); - } - Promise.all(tasks.map(function (doc, i) { - return db.allDocs({skip : i * 100, limit : 10}); - })).then(function () { - done(); - }, done); - } - }, { - name: 'all-docs-startkey-endkey', - assertions: 1, - iterations: 50, - setup: function (db, callback) { - var docs = []; - for (var i = 0; i < 1000; i++) { - docs.push({_id : createDocId(i), foo : 'bar', baz : 'quux'}); - } - db.bulkDocs({docs : docs}, callback); - }, - test: function (db, itr, docs, done) { - var tasks = []; - for (var i = 0; i < 10; i++) { - tasks.push(i); - } - Promise.all(tasks.map(function (doc, i) { - return db.allDocs({ - startkey : createDocId(i * 100), - endkey : createDocId((i * 100) + 10) - }); - })).then(function () { - done(); - }, done); - } - } - ]; - - utils.runTests(PouchDB, 'basics', testCases, opts); - -}; \ No newline at end of file
diff --git a/tests/performance/perf.reporter.js b/tests/performance/perf.reporter.js deleted file mode 100644 index a44cb1c..0000000 --- a/tests/performance/perf.reporter.js +++ /dev/null
@@ -1,57 +0,0 @@ -'use strict'; -var isNode = process && !process.browser; -var UAParser = require('ua-parser-js'); -var ua = !isNode && new UAParser(navigator.userAgent); -global.results = {}; - -var pre = !isNode && global.document.getElementById('output'); - -function log(msg) { - if (pre) { - pre.innerHTML = pre.innerHTML + msg; - } else { - console.log(msg); - } -} - -exports.log = log; - -exports.startSuite = function (suiteName) { - log('Starting suite: ' + suiteName + '\n\n'); -}; - -exports.start = function (testCase) { - var key = testCase.name; - log('Starting test: ' + key + ' with ' + testCase.assertions + - ' assertions and ' + testCase.iterations + ' iterations... '); - global.results[key] = { - start: Date.now() - }; -}; - -exports.end = function (testCase) { - var key = testCase.name; - var obj = global.results[key]; - obj.end = Date.now(); - obj.duration = obj.end - obj.start; - log('done in ' + obj.duration + 'ms\n'); -}; - -exports.complete = function (suiteName) { - global.results.completed = true; - if (isNode) { - global.results.client = {node: process.version}; - } else { - global.results.client = { - browser: ua.getBrowser(), - device: ua.getDevice(), - engine: ua.getEngine(), - cpu: ua.getCPU(), - os : ua.getOS(), - userAgent: navigator.userAgent - }; - } - console.log(global.results); - log('\nTests Complete!\n\n'); -}; -
diff --git a/tests/performance/perf.views.js b/tests/performance/perf.views.js deleted file mode 100644 index d2aeaa9..0000000 --- a/tests/performance/perf.views.js +++ /dev/null
@@ -1,150 +0,0 @@ -'use strict'; - -module.exports = function (PouchDB, opts) { - - // need to use bluebird for promises everywhere, so we're comparing - // apples to apples - var Promise = require('bluebird'); - var utils = require('./utils'); - - function makeTestDocs() { - return [ - {key: null}, - {key: true}, - {key: false}, - {key: -1}, - {key: 0}, - {key: 1}, - {key: 2}, - {key: 3}, - {key: Math.random()}, - {key: 'bar' + Math.random()}, - {key: 'foo' + Math.random()}, - {key: 'foobar' + Math.random()} - ]; - } - - var testCases = [ - { - name: 'temp-views', - assertions: 1, - iterations: 1, - setup: function (db, callback) { - var tasks = []; - for (var i = 0; i < 100; i++) { - tasks.push(i); - } - Promise.all(tasks.map(function () { - return db.bulkDocs({docs : makeTestDocs()}); - })).then(function () { - callback(); - }, callback); - }, - test: function (db, itr, doc, done) { - var tasks = [ - {startkey: 'foo', limit: 5}, - {startkey: 'foobar', limit: 5}, - {startkey: 'foo', limit: 5}, - {startkey: -1, limit: 5}, - {startkey: null, limit: 5} - ]; - Promise.all(tasks.map(function (task) { - return db.query(function (doc) { - emit(doc.key); - }, task); - })).then(function (res) { - done(); - }, done); - } - }, - { - name: 'persisted-views', - assertions: 1, - iterations: 10, - setup: function (db, callback) { - var tasks = []; - for (var i = 0; i < 100; i++) { - tasks.push(i); - } - Promise.all(tasks.map(function () { - return db.bulkDocs({docs : makeTestDocs()}); - })).then(function () { - return db.put({ - _id : '_design/myview', - views : { - myview : { - map : function (doc) { - emit(doc.key); - }.toString() - } - } - }); - }).then(function () { - return db.query('myview/myview'); - }).then(function () { - callback(); - }, callback); - }, - test: function (db, itr, doc, done) { - var tasks = [ - {startkey: 'foo', limit: 5}, - {startkey: 'foobar', limit: 5}, - {startkey: 'foo', limit: 5}, - {startkey: -1, limit: 5}, - {startkey: null, limit: 5} - ]; - Promise.all(tasks.map(function (task) { - return db.query('myview/myview', task); - })).then(function (res) { - done(); - }, done); - } - }, - { - name: 'persisted-views-stale-ok', - assertions: 1, - iterations: 10, - setup: function (db, callback) { - var tasks = []; - for (var i = 0; i < 100; i++) { - tasks.push(i); - } - Promise.all(tasks.map(function () { - return db.bulkDocs({docs : makeTestDocs()}); - })).then(function () { - return db.put({ - _id : '_design/myview', - views : { - myview : { - map : function (doc) { - emit(doc.key); - }.toString() - } - } - }); - }).then(function () { - return db.query('myview/myview'); - }).then(function () { - callback(); - }, callback); - }, - test: function (db, itr, doc, done) { - var tasks = [ - {startkey: 'foo', limit: 5, stale : 'ok'}, - {startkey: 'foobar', limit: 5, stale : 'ok'}, - {startkey: 'foo', limit: 5, stale : 'ok'}, - {startkey: -1, limit: 5, stale : 'ok'}, - {startkey: null, limit: 5, stale : 'ok'} - ]; - Promise.all(tasks.map(function (task) { - return db.query('myview/myview', task); - })).then(function (res) { - done(); - }, done); - } - } - ]; - - utils.runTests(PouchDB, 'views', testCases, opts); - -};
diff --git a/tests/performance/utils.js b/tests/performance/utils.js deleted file mode 100644 index 956e532..0000000 --- a/tests/performance/utils.js +++ /dev/null
@@ -1,70 +0,0 @@ -'use strict'; - -var reporter = require('./perf.reporter'); -var test = require('tape'); - -var grep; -if (global.window && global.window.location && global.window.location.search) { - grep = global.window.location.search.match(/[&?]grep=([^&]+)/); - grep = grep && grep[1]; -} else if (process && process.env) { - grep = process.env.GREP; -} - -exports.runTests = function (PouchDB, suiteName, testCases, opts) { - testCases.forEach(function (testCase, i) { - if (grep && suiteName.indexOf(grep) === -1 && - testCase.name.indexOf(grep) === -1) { - return; - } - test('benchmarking', function (t) { - - var db; - var setupObj; - - var randomizer = Math.random(); - - t.test('setup', function (t) { - opts.size = 3000; - db = new PouchDB('test' + randomizer, opts); - testCase.setup(db, function (err, res) { - setupObj = res; - if (i === 0) { - reporter.startSuite(suiteName); - } - reporter.start(testCase); - t.end(); - }); - }); - - t.test(testCase.name, function (t) { - t.plan(testCase.assertions); - var num = 0; - function after(err) { - if (err) { - t.error(err); - reporter.log(testCase.name + ' errored: ' + err.message + '\n'); - } - if (++num < testCase.iterations) { - process.nextTick(function () { - testCase.test(db, num, setupObj, after); - }); - } else { - t.ok(testCase.name + ' completed'); - } - } - testCase.test(db, num, setupObj, after); - }); - t.test('teardown', function (t) { - reporter.end(testCase); - var opts = {adapter : db.adapter}; - PouchDB.destroy('test' + randomizer, opts, function () { - t.end(); - if (i === testCases.length - 1) { - reporter.complete(suiteName); - } - }); - }); - }); - }); -};
diff --git a/tests/stress/websql_storage_limit.html b/tests/stress/websql_storage_limit.html deleted file mode 100644 index f3e6fbe..0000000 --- a/tests/stress/websql_storage_limit.html +++ /dev/null
@@ -1,83 +0,0 @@ -<!doctype html> -<html> -<body> -<h1>WebSQL storage limit stress test</h1> - -<form action='#' id="myform" onsubmit="runTest();return false;"> - <h3>Choose size in MB:</h3> - <input type="radio" id="5" name="size" value="5"/> - <label for="5">5</label> - <input type="radio" id="10" name="size" value="10" checked="checked"/> - <label for="5">10</label> - <input type="radio" id="50" name="size" value="50"/> - <label for="5">50</label> - <input type="radio" id="100" name="size" value="100"/> - <label for="5">100</label> - <input type="radio" id="500" name="size" value="500"/> - <label for="5">500</label> - <input type="radio" id="1000" name="size" value="1000"/> - <label for="5">1000</label> - <p/> - <button>Run test</button> -</form> -<p/> -<pre id="log"> </pre> -<script src="../../dist/pouchdb.js"></script> -<script> - - function getRadioValue() { - var inputs = document.getElementsByName("size"); - for (var i = 0; i < inputs.length; i++) { - if (inputs[i].checked) { - return inputs[i].value; - } - } - } - - function log(text) { - document.getElementById('log').appendChild(document.createTextNode(text + '\n')); - } - - log('this is a load test designed to reproduce the 10MB size limit bug on Safari/iOS 7'); - log("if all's well, you should see a success message, else an error"); - log("you can use Safari's 'reset Safari' option to try again\n"); - - function runTest() { - - log('starting...'); - - var BATCH_SIZE = 1000; - var ITERATIONS = 1000; - var pouch = new PouchDB('websql_stress', {adapter: 'websql', size: getRadioValue()}); - var promise = PouchDB.utils.Promise.resolve(); - - function addDocs(i) { - promise = promise.then(function () { - var docs = []; - for (var j = 0; j < BATCH_SIZE; j++) { - docs.push({}); - } - return pouch.bulkDocs({docs: docs}).then(function () { - var numDone = (i + 1) * BATCH_SIZE; - var total = BATCH_SIZE * ITERATIONS; - var percent = (Math.round((numDone / total) * 10000) / 100).toFixed(2); - log('Added ' + numDone + '/' + total + ' (' + percent + '%) docs so far...'); - }); - }); - } - - for (var i = 0; i < ITERATIONS; i++) { - addDocs(i); - } - promise.then(function () { - log('Success!'); - }, function (err) { - log('Failure!'); - log(err); - }); - - return false; - } -</script> -</body> -</html>
diff --git a/tests/unit/test.merge.js b/tests/unit/test.merge.js deleted file mode 100644 index e42b1bd..0000000 --- a/tests/unit/test.merge.js +++ /dev/null
@@ -1,364 +0,0 @@ -'use strict'; - -// Porting tests from Apache CouchDB -// https://github.com/davisp/couchdb/blob/local_doc_revs/test/ -// etap/060-kt-merging.t - -var mergeJs = require('../../lib/merge.js'); -var merge = mergeJs.merge; -var winningRev = mergeJs.winningRev; - -describe('test.merge.js', function () { - - var simple = {pos: 1, ids: ['1', {}, []]}; - var two0 = {pos: 1, ids: ['1', {}, [['2_0', {}, []]]]}; - var two1 = {pos: 1, ids: ['1', {}, [['2_1', {}, []]]]}; - var newleaf = {pos: 2, ids: ['2_0', {}, [['3', {}, []]]]}; - var withnewleaf = {pos: 1, ids: ['1', {}, [['2_0', {}, [['3', {}, []]]]]]}; - var newbranch = {pos: 1, ids: ['1', {}, [['2_0', {}, []], ['2_1', {}, []]]]}; - var newdeepbranch = {pos: 2, ids: ['2_0', {}, [['3_1', {}, []]]]}; - - var stemmededit = {pos: 3, ids: ['3', {}, []]}; - var stemmedconflicts = [simple, stemmededit]; - - var newbranchleaf = { - pos: 1, - ids: ['1', {}, [['2_0', {}, [['3', {}, []]]], ['2_1', {}, []]]] - }; - - var newbranchleafbranch = { - pos: 1, - ids: ['1', {}, [ - ['2_0', {}, [['3', {}, []], ['3_1', {}, []]]], ['2_1', {}, []] - ]] - }; - - var stemmed2 = [ - {pos: 1, ids: ['1', {}, [['2_1', {}, []]]]}, - {pos: 2, ids: ['2_0', {}, [['3', {}, []], ['3_1', {}, []]]]} - ]; - - var stemmed3 = [ - {pos: 2, ids: ['2_1', {}, []]}, - {pos: 3, ids: ['3', {}, []]}, - {pos: 3, ids: ['3_1', {}, []]} - ]; - - var partialrecover = [ - {pos: 1, ids: ['1', {}, [['2_0', {}, [['3', {}, []]]]]]}, - {pos: 2, ids: ['2_1', {}, []]}, - {pos: 3, ids: ['3_1', {}, []]} - ]; - - it('Merging a path into an empty tree is the path', function () { - merge([], simple, 10).should.deep.equal({ - tree: [simple], - conflicts: 'new_leaf' - }); - }); - - it('Remerge path into path is reflexive', function () { - merge([simple], simple, 10).should.deep.equal({ - tree: [simple], - conflicts: 'internal_node' - }); - }); - - it('Merging a path with multiple entries is the path', function () { - merge([], two0, 10).should.deep.equal({ - tree: [two0], - conflicts: 'new_leaf' - }); - }); - - it('Merging a path with multiple entries is reflexive', function () { - merge([two0], two0, 10).should.deep.equal({ - tree: [two0], - conflicts: 'internal_node' - }); - }); - - it('Merging a subpath into a path results in the path', function () { - merge([two0], simple, 10).should.deep.equal({ - tree: [two0], - conflicts: 'internal_node' - }); - }); - - it('Merging a new leaf gives us a new leaf', function () { - merge([two0], newleaf, 10).should.deep.equal({ - tree: [withnewleaf], - conflicts: 'new_leaf' - }); - }); - - it('Merging a new branch returns a proper tree', function () { - merge([two0], two1, 10).should.deep.equal({ - tree: [newbranch], - conflicts: 'new_branch' - }); - }); - - it('Order of merging does not affect the resulting tree', function () { - merge([two1], two0, 10).should.deep.equal({ - tree: [newbranch], - conflicts: 'new_branch' - }); - }); - - it('Merging a new_leaf doesnt return new_branch when branches exist', - function () { - merge([newbranch], newleaf, 10).should.deep.equal({ - tree: [newbranchleaf], - conflicts: 'new_leaf' - }); - }); - - it('Merging a deep branch with branches works', function () { - merge([newbranchleaf], newdeepbranch, 10).should.deep.equal({ - tree: [newbranchleafbranch], - conflicts: 'new_branch' - }); - }); - - it('New information reconnects steming induced conflicts', function () { - merge(stemmedconflicts, withnewleaf, 10).should.deep.equal({ - tree: [withnewleaf], - conflicts: 'new_leaf' - }); - }); - - it('Simple stemming works', function () { - merge([two0], newleaf, 2).should.deep.equal({ - tree: [newleaf], - conflicts: 'new_leaf' - }); - }); - - it('Merge with stemming works correctly for branches', function () { - merge([newbranchleafbranch], simple, 2).should.deep.equal({ - tree: stemmed2, - conflicts: 'internal_node' - }); - }); - - it('Merge with stemming to leaves works fine', function () { - merge([newbranchleafbranch], simple, 1).should.deep.equal({ - tree: stemmed3, - conflicts: 'internal_node' - }); - }); - - it('Merging unstemmed recovers as much as possible without losing info', - function () { - merge(stemmed3, withnewleaf, 10).should.deep.equal({ - tree: partialrecover, - conflicts: 'internal_node' - }); - }); - - it('winningRev returns the longest leaf', function () { - var tree = [ - {"pos": 1, "ids": [ - "bfe70372c90ded1087239e5191984f76", {}, [ - ["44d71a718b90e4696c06a90e08912c8f", {}, []], - ["56e657612d55ab1a402dcb281c874f2a", {}, [ - ["93c3db16462f656f7172ccabd3cf6cd6", {}, []] - ]] - ] - ]} - ]; - winningRev({rev_tree: tree}) - .should.equal("3-93c3db16462f656f7172ccabd3cf6cd6"); - }); - - it('winningRev returns the longest leaf again', function () { - // this one is from issue #293 - var tree = [ - {"pos": 1, "ids": [ - "203db1a1810a838895d561f67b224b5d", {}, [ - ["bf5e08a4f9fa6d33a53f4a00ae3ea399", {}, [ - ["28cd77a3ca30f79e1cfffcd6a41ca308", {}, []] - ]] - ] - ]}, - {"pos": 1, "ids": [ - "c6d5cce35bcfbef90b20f140d723cbdb", {}, [ - ["1b8dfbb1267e213328920bae43f2f597", {}, []], - ["59ed830b84b276ab776c3c51aaf93a16", {}, [ - ["64a9842c6aea50bf24660378e496e853", {}, []] - ]] - ] - ]} - ]; - winningRev({rev_tree: tree}) - .should.equal("3-64a9842c6aea50bf24660378e496e853"); - }); - - // ///// These are tests from CouchDB's kt-merging.erl test suite - - var one = {pos: 1, ids: ['1', {}, []]}; - it('The empty tree is the identity for merge.', function () { - merge([], one, 10).should.deep.equal({ - tree: [one], - conflicts: 'new_leaf' - }); - }); - - it('Merging is reflexive', function () { - merge([one], one, 10).should.deep.equal({ - tree: [one], - conflicts: 'internal_node' - }); - }); - - var two = {pos: 1, ids: ['2', {}, []]}; - var twoSibs = [one, two]; - it('Merging a prefix of a tree with the tree yields the tree.', function () { - merge(twoSibs, one, 10).should.deep.equal({ - tree: twoSibs, - conflicts: 'internal_node' - }); - }); - - var three = {pos: 1, ids: ['3', {}, []]}; - var threeSibs = [one, two, three]; - it('Merging a third unrelated branch leads to a conflict.', function () { - merge(twoSibs, three, 10).should.deep.equal({ - tree: threeSibs, - conflicts: 'internal_node' - }); - }); - - var twoChild = {pos: 1, ids: ['1', {}, [ - ['1a', {}, [ - ['1aa', {}, []] - ]] - ]]}; - it('Merging two children is still reflexive.', function () { - merge([twoChild], twoChild, 10).should.deep.equal({ - tree: [twoChild], - conflicts: 'internal_node' - }); - }); - - var twoChildSibs = {pos: 1, ids: ['1', {}, [ - ['1a', {}, []], - ['1b', {}, []] - ]]}; - it('Merging a tree to itself is itself.', function () { - merge([twoChildSibs], twoChildSibs, 10).should.deep.equal({ - tree: [twoChildSibs], - conflicts: 'internal_node' - }); - }); - - var twoChildPlusSibs = {pos: 1, ids: ['1', {}, [ - ['1a', {}, [ - ['1aa', {}, []] - ]], - ['1b', {}, []] - ]]}; - it('Merging tree of uneven length at node 2.', function () { - merge([twoChild], twoChildSibs, 10).should.deep.equal({ - tree: [twoChildPlusSibs], - conflicts: 'new_branch' - }); - }); - - var stemmed1b = {pos: 2, ids: ['1a', {}, []]}; - it('Merging a tree with a stem.', function () { - merge([twoChildSibs], stemmed1b, 10).should.deep.equal({ - tree: [twoChildSibs], - conflicts: 'internal_node' - }); - }); - - var twoChildPlusSibs2 = {pos: 1, ids: ['1', {}, [ - ['1a', {}, []], - ['1b', {}, [ - ['1bb', {}, []] - ]] - ]]}; - var stemmed1bb = {pos: 3, ids: ['1bb', {}, []]}; - it('Merging a stem at a deeper level.', function () { - merge([twoChildPlusSibs2], stemmed1bb, 10).should.deep.equal({ - tree: [twoChildPlusSibs2], - conflicts: 'internal_node' - }); - }); - - var stemmedTwoChildSibs2 = [ - {pos: 2, ids: ['1a', {}, []]}, - {pos: 2, ids: ['1b', {}, [['1bb', {}, []]]]} - ]; - it('Merging a stem at a deeper level against paths at deeper levels.', - function () { - merge(stemmedTwoChildSibs2, stemmed1bb, 10).should.deep.equal({ - tree: stemmedTwoChildSibs2, - conflicts: 'internal_node' - }); - }); - - var stemmed1aa = {pos: 3, ids: ['1aa', {}, []]}; - it("Merging a single tree with a deeper stem.", function () { - merge([twoChild], stemmed1aa, 10).should.deep.equal({ - tree: [twoChild], - conflicts: 'internal_node' - }); - }); - - var stemmed1a = {pos: 2, ids: ['1a', {}, [['1aa', {}, []]]]}; - it('Merging a larger stem.', function () { - merge([twoChild], stemmed1a, 10).should.deep.equal({ - tree: [twoChild], - conflicts: 'internal_node' - }); - }); - - it('More merging.', function () { - merge([stemmed1a], stemmed1aa, 10).should.deep.equal({ - tree: [stemmed1a], - conflicts: 'internal_node' - }); - }); - - var oneChild = {pos: 1, ids: ['1', {}, [['1a', {}, []]]]}; - it('Merging should create conflicts.', function () { - merge([oneChild], stemmed1aa, 10).should.deep.equal({ - tree: [oneChild, stemmed1aa], - conflicts: 'internal_node' - }); - }); - - it('Merging should have no conflicts.', function () { - merge([oneChild, stemmed1aa], twoChild, 10).should.deep.equal({ - tree: [twoChild], - conflicts: 'new_leaf' - }); - }); - - var foo = {pos: 1, ids: ['foo', {}, [ - ['foo2', {}, []], - ['foo3', {}, []] - ]]}; - var bar = {pos: 1, ids: ['foo', {}, [ - ['foo3', {}, [ - ['foo4', {}, []] - ]] - ]]}; - var fooBar = {pos: 1, ids: ['foo', {}, [ - ['foo2', {}, []], - ['foo3', {}, [ - ['foo4', {}, []] - ]] - ]]}; - - it('Merging trees with conflicts ought to behave.', function () { - merge([foo], bar, 10).should.deep.equal({ - tree: [fooBar], - conflicts: 'new_leaf' - }); - }); - -});
diff --git a/tests/unit/test.once.js b/tests/unit/test.once.js deleted file mode 100644 index cb01ebd..0000000 --- a/tests/unit/test.once.js +++ /dev/null
@@ -1,26 +0,0 @@ - -'use strict'; - -var should = require('chai').should(); -var utils = require('../../lib/utils.js'); - -describe('test.once.js', function () { - - it('Only call once ... once', function () { - var myFun = utils.once(function () { }); - myFun(); - should.throw(myFun); - }); - - it('Once wrapped in a promise', function (done) { - var callback = function () {}; - var myFun = utils.toPromise(function (callback) { - setTimeout(function () { - callback(); - should.throw(callback); - done(); - }); - }); - myFun(callback); - }); -});
diff --git a/vendor/selenium-server-standalone-2.38.0.jar b/vendor/selenium-server-standalone-2.38.0.jar deleted file mode 100644 index 15048af..0000000 --- a/vendor/selenium-server-standalone-2.38.0.jar +++ /dev/null Binary files differ