pouchdb-collate
Advanced tools
Comparing version 1.1.0 to 1.1.1
!function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.pouchCollate=e():"undefined"!=typeof global?global.pouchCollate=e():"undefined"!=typeof self&&(self.pouchCollate=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){ | ||
'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 = require('./utils'); | ||
exports.collate = function (a, b) { | ||
@@ -15,18 +21,12 @@ a = exports.normalizeKey(a); | ||
} | ||
if (typeof a === 'number') { | ||
return a - b; | ||
switch (typeof a) { | ||
case 'number': | ||
return a - b; | ||
case 'boolean': | ||
return a === b ? 0 : (a < b ? -1 : 1); | ||
case 'string': | ||
return stringCollate(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); | ||
} | ||
} | ||
return Array.isArray(a) ? arrayCollate(a, b) : objectCollate(a, b); | ||
}; | ||
@@ -36,14 +36,63 @@ // couch considers null/NaN/Infinity/-Infinity === undefined, | ||
exports.normalizeKey = function (key) { | ||
if (typeof key === 'undefined') { | ||
return null; | ||
} else if (typeof key === 'number') { | ||
if (key === Infinity || key === -Infinity || isNaN(key)) { | ||
switch (typeof key) { | ||
case 'undefined': | ||
return null; | ||
case 'number': | ||
if (key === Infinity || key === -Infinity || isNaN(key)) { | ||
return null; | ||
} | ||
return key; | ||
} | ||
return key instanceof Date ? key.toJSON() : 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; | ||
} | ||
} else if (key instanceof Date) { | ||
return key.toJSON(); | ||
} | ||
return key; | ||
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) { | ||
@@ -91,13 +140,132 @@ var len = Math.min(a.length, b.length); | ||
var id = ['boolean', 'number', 'string', 'object']; | ||
if (id.indexOf(typeof x) !== -1) { | ||
var idx = id.indexOf(typeof x); | ||
//false if -1 otherwise true, but fast!!!!1 | ||
if (~idx) { | ||
if (x === null) { | ||
return 1; | ||
} | ||
return id.indexOf(typeof x) + 2; | ||
if (Array.isArray(x)) { | ||
return 5; | ||
} | ||
return idx < 3 ? (idx + 2) : (idx + 3); | ||
} | ||
if (Array.isArray(x)) { | ||
return 4.5; | ||
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) { | ||
// 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; | ||
if (num === 0) { | ||
return '1'; | ||
} | ||
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":2}],2:[function(require,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; | ||
}; | ||
},{}]},{},[1]) | ||
@@ -104,0 +272,0 @@ (1) |
115
lib/index.js
@@ -5,3 +5,3 @@ 'use strict'; | ||
var MAGNITUDE_DIGITS = 3; // ditto | ||
var SEP = '_'; // TODO: in production it should be empty | ||
var SEP = ''; // set to '_' for easier debugging | ||
@@ -21,15 +21,11 @@ var utils = require('./utils'); | ||
} | ||
if (typeof a === 'number') { | ||
return a - b; | ||
switch (typeof a) { | ||
case 'number': | ||
return a - b; | ||
case 'boolean': | ||
return a === b ? 0 : (a < b ? -1 : 1); | ||
case 'string': | ||
return stringCollate(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); | ||
} | ||
return objectCollate(a, b); | ||
return Array.isArray(a) ? arrayCollate(a, b) : objectCollate(a, b); | ||
}; | ||
@@ -40,14 +36,54 @@ | ||
exports.normalizeKey = function (key) { | ||
if (typeof key === 'undefined') { | ||
return null; | ||
} else if (typeof key === 'number') { | ||
if (key === Infinity || key === -Infinity || isNaN(key)) { | ||
switch (typeof key) { | ||
case 'undefined': | ||
return null; | ||
} | ||
} else if (key instanceof Date) { | ||
return key.toJSON(); | ||
case 'number': | ||
if (key === Infinity || key === -Infinity || isNaN(key)) { | ||
return null; | ||
} | ||
return key; | ||
} | ||
return key; | ||
return key instanceof Date ? key.toJSON() : 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 | ||
@@ -58,39 +94,4 @@ // for lexical sorting, e.g. within a database, where the | ||
var zero = '\u0000'; | ||
key = exports.normalizeKey(key); | ||
var result = collationIndex(key) + SEP; | ||
if (key !== null) { | ||
if (typeof key === 'boolean') { | ||
result += (key ? 1 : 0); | ||
} else if (typeof key === 'number') { | ||
result += numToIndexableString(key) + zero; | ||
} else if (typeof key === '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 | ||
key = key.replace(/\u0002/g, '\u0002\u0002'); | ||
key = key.replace(/\u0001/g, '\u0001\u0002'); | ||
key = key.replace(/\u0000/g, '\u0001\u0001'); | ||
result += key + zero; | ||
} else if (Array.isArray(key)) { | ||
key.forEach(function (element) { | ||
result += exports.toIndexableString(element); | ||
}); | ||
result += zero; | ||
} else if (typeof key === 'object') { | ||
var arr = []; | ||
var keys = Object.keys(key); | ||
keys.forEach(function (objKey) { | ||
arr.push([objKey, key[objKey]]); | ||
}); | ||
result += exports.toIndexableString(arr); | ||
} | ||
} | ||
return result; | ||
return collationIndex(key) + SEP + indexify(key) + zero; | ||
}; | ||
@@ -97,0 +98,0 @@ |
{ | ||
"name": "pouchdb-collate", | ||
"version": "1.1.0", | ||
"version": "1.1.1", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
23917
764
0