UNPKG

id-shorter

Version:

A little module that replaces a long ObjectId value with short one keeping uniqueness. A charset for conversion is fully configurable and does not depend on requirement of 64 symbols. So it is possible to use only letters, letters+digits, digits etc.

115 lines (89 loc) 2.54 kB
var ObjectId = require('bson').ObjectId; exports.BaseCharSet = function(str) { this.set = str; this.bits = (this.set.length - 1).toString(2).length; this.map = {}; for (var i = 0; i < this.set.length; i++) { var char = this.set.charAt(i); this.map[char] = i; } } exports.EncodingCharSet = function(str) { var isSetAtPowerOf2 = false; this.set = str.substring(0, str.length); this.bits = (this.set.length - 1).toString(2).length; this.po2 = Math.pow(2, this.bits); if (this.set.length < this.po2) { // Use last symbol as escape char for encoding (like UTF-8) this.escapeChar = str.charAt(str.length - 1); // Recalculating set this.set = str.substring(0, str.length - 1); this.bits = (this.set.length - 1).toString(2).length; this.po2 = Math.pow(2, this.bits); } else { // No need for escapeChar - set length is power of 2 this.escapeChar = ''; isSetAtPowerOf2 = true; } this.map = {}; for (var i = 0; i < this.set.length; i++) { var char = this.set.charAt(i); this.map[char] = i; } this.encode = function(value) { if (isNaN(value)) { console.error('Value ' + value + ' is not a number'); return ''; } if (value > this.po2 - 1) { console.error('Value cannot be decoded with given bit length. Try less bits.'); return ''; } var result = ''; // Need to escape a char if (value > this.set.length - 1) { result = this.escapeChar; value -= this.set.length; } result += this.set.charAt(value); return result; } } exports.getObjectIdTime = function(id) { var str = ""; // make sure it's an ObjectId, not just a string id = new ObjectId(String(id)); // creation date var date = id.getTimestamp(); // time in milliseconds (with precision in seconds) var time = date.getTime(); if (time < 0) { time = 0; } // hexadecimal counter converted to a decimal var counter = parseInt(id.toHexString().slice(-6), 16); // only use the last 3 digits of the counter to serve as our "milliseconds" counter = parseInt(counter.toString().slice(-3), 10); // add counter as our millisecond precision to our time time = time + counter; str += time; return str; } exports.padLeft = function(number, width, char) { char = char || '0'; width -= number.toString().length; if (width > 0) { return new Array(width + (/\./.test(number) ? 2 : 1)).join(char) + number; } return number + ""; // always return a string }