blob: dab8d9e5d4c887b5bcad832941a30190a32c8f7d [file] [log] [blame]
import {
getFieldFromDoc,
setFieldInDoc,
parseField
} from 'pouchdb-selector-core';
import { nextTick } from 'pouchdb-utils';
function once(fun) {
var called = false;
return getArguments(function (args) {
if (called) {
console.trace();
throw new Error('once called more than once');
} else {
called = true;
fun.apply(this, args);
}
});
}
function getArguments(fun) {
return function () {
var len = arguments.length;
var args = new Array(len);
var i = -1;
while (++i < len) {
args[i] = arguments[i];
}
return fun.call(this, args);
};
}
function toPromise(func) {
//create the function we will be returning
return 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) {
nextTick(function () {
tempCB(err, resp);
});
};
}
var promise = new Promise(function (fulfill, reject) {
try {
var callback = 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);
func.apply(self, args);
} 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;
});
}
function callbackify(fun) {
return getArguments(function (args) {
var cb = args.pop();
var promise = fun.apply(this, args);
promisedCallback(promise, cb);
return promise;
});
}
function promisedCallback(promise, callback) {
promise.then(function (res) {
nextTick(function () {
callback(null, res);
});
}, function (reason) {
nextTick(function () {
callback(reason);
});
});
return promise;
}
var flatten = getArguments(function (args) {
var res = [];
for (var i = 0, len = args.length; i < len; i++) {
var subArr = args[i];
if (Array.isArray(subArr)) {
res = res.concat(flatten.apply(null, subArr));
} else {
res.push(subArr);
}
}
return res;
});
function mergeObjects(arr) {
var res = {};
for (var i = 0, len = arr.length; i < len; i++) {
res = Object.assign(res, arr[i]);
}
return res;
}
// Selects a list of fields defined in dot notation from one doc
// and copies them to a new doc. Like underscore _.pick but supports nesting.
function pick(obj, arr) {
var res = {};
for (var i = 0, len = arr.length; i < len; i++) {
var parsedField = parseField(arr[i]);
var value = getFieldFromDoc(obj, parsedField);
if (typeof value !== 'undefined') {
setFieldInDoc(res, parsedField, value);
}
}
return res;
}
// e.g. ['a'], ['a', 'b'] is true, but ['b'], ['a', 'b'] is false
function oneArrayIsSubArrayOfOther(left, right) {
for (var i = 0, len = Math.min(left.length, right.length); i < len; i++) {
if (left[i] !== right[i]) {
return false;
}
}
return true;
}
// e.g.['a', 'b', 'c'], ['a', 'b'] is false
function oneArrayIsStrictSubArrayOfOther(left, right) {
if (left.length > right.length) {
return false;
}
return oneArrayIsSubArrayOfOther(left, right);
}
// same as above, but treat the left array as an unordered set
// e.g. ['b', 'a'], ['a', 'b', 'c'] is true, but ['c'], ['a', 'b', 'c'] is false
function oneSetIsSubArrayOfOther(left, right) {
left = left.slice();
for (var i = 0, len = right.length; i < len; i++) {
var field = right[i];
if (!left.length) {
break;
}
var leftIdx = left.indexOf(field);
if (leftIdx === -1) {
return false;
} else {
left.splice(leftIdx, 1);
}
}
return true;
}
function arrayToObject(arr) {
var res = {};
for (var i = 0, len = arr.length; i < len; i++) {
res[arr[i]] = true;
}
return res;
}
function max(arr, fun) {
var max = null;
var maxScore = -1;
for (var i = 0, len = arr.length; i < len; i++) {
var element = arr[i];
var score = fun(element);
if (score > maxScore) {
maxScore = score;
max = element;
}
}
return max;
}
function arrayEquals(arr1, arr2) {
if (arr1.length !== arr2.length) {
return false;
}
for (var i = 0, len = arr1.length; i < len; i++) {
if (arr1[i] !== arr2[i]) {
return false;
}
}
return true;
}
function uniq(arr) {
var obj = {};
for (var i = 0; i < arr.length; i++) {
obj['$' + arr[i]] = true;
}
return Object.keys(obj).map(function (key) {
return key.substring(1);
});
}
export {
arrayEquals,
arrayToObject,
callbackify,
flatten,
getArguments,
max,
mergeObjects,
once,
oneArrayIsStrictSubArrayOfOther,
oneArrayIsSubArrayOfOther,
oneSetIsSubArrayOfOther,
pick,
promisedCallback,
toPromise,
uniq
};