UNPKG

mobdb

Version:

MarsDB is a lightweight client-side MongoDB-like database, Promise based, written in ES6

248 lines (216 loc) 8.15 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); exports._getBrowserSeeds = _getBrowserSeeds; var _try2 = require('fast.js/function/try'); var _try3 = _interopRequireDefault(_try2); var _invariant = require('invariant'); var _invariant2 = _interopRequireDefault(_invariant); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } // Intarnals var _defaultRandomGenerator = void 0; var RANDOM_GENERATOR_TYPE = { NODE_CRYPTO: 'NODE_CRYPTO', BROWSER_CRYPTO: 'BROWSER_CRYPTO', ALEA: 'ALEA' }; var UNMISTAKABLE_CHARS = '23456789ABCDEFGHJKLMNPQRSTWXYZabcdefghijkmnopqrstuvwxyz'; var BASE64_CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' + '0123456789-_'; // see http://baagoe.org/en/wiki/Better_random_numbers_for_javascript // for a full discussion and Alea implementation. var Alea = function Alea() { function Mash() { var n = 0xefc8249d; var mash = function mash(data) { data = data.toString(); for (var i = 0; i < data.length; i++) { n += data.charCodeAt(i); var h = 0.02519603282416938 * n; n = h >>> 0; h -= n; h *= n; n = h >>> 0; h -= n; n += h * 0x100000000; // 2^32 } return (n >>> 0) * 2.3283064365386963e-10; // 2^-32 }; mash.version = 'Mash 0.9'; return mash; } return function (args) { var s0 = 0; var s1 = 0; var s2 = 0; var c = 1; if (args.length == 0) { args = [+new Date()]; } var mash = Mash(); s0 = mash(' '); s1 = mash(' '); s2 = mash(' '); for (var i = 0; i < args.length; i++) { s0 -= mash(args[i]); if (s0 < 0) { s0 += 1; } s1 -= mash(args[i]); if (s1 < 0) { s1 += 1; } s2 -= mash(args[i]); if (s2 < 0) { s2 += 1; } } mash = null; var random = function random() { var t = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32 s0 = s1; s1 = s2; return s2 = t - (c = t | 0); }; random.uint32 = function () { return random() * 0x100000000; // 2^32 }; random.fract53 = function () { return random() + (random() * 0x200000 | 0) * 1.1102230246251565e-16; // 2^-53 }; random.version = 'Alea 0.9'; random.args = args; return random; }(Array.prototype.slice.call(arguments)); }; /** * Create seeds array for a browser based on window sizes, * Date and some random number. * @return {Arrat} */ function _getBrowserSeeds() { var height = typeof window !== 'undefined' && window.innerHeight || typeof document !== 'undefined' && document.documentElement && document.documentElement.clientHeight || typeof document !== 'undefined' && document.body && document.body.clientHeight || 1; var width = typeof window !== 'undefined' && window.innerWidth || typeof document !== 'undefined' && document.documentElement && document.documentElement.clientWidth || typeof document !== 'undefined' && document.body && document.body.clientWidth || 1; var agent = typeof navigator !== 'undefined' && navigator.userAgent || ''; return [new Date(), height, width, agent, Math.random()]; } /** * Random string generator copied from Meteor * with minor modifications and refactoring. */ var Random = function () { function Random(type) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; _classCallCheck(this, Random); this.type = type; (0, _invariant2.default)(RANDOM_GENERATOR_TYPE[type], 'Random(...): no generator type %s', type); if (type === RANDOM_GENERATOR_TYPE.ALEA) { (0, _invariant2.default)(options.seeds, 'Random(...): seed is not provided for ALEA seeded generator'); this.alea = Alea.apply(null, options.seeds); } } _createClass(Random, [{ key: 'fraction', value: function fraction() { if (this.type === RANDOM_GENERATOR_TYPE.ALEA) { return this.alea(); } else if (this.type === RANDOM_GENERATOR_TYPE.NODE_CRYPTO) { var numerator = parseInt(this.hexString(8), 16); return numerator * 2.3283064365386963e-10; // 2^-32 } else if (this.type === RANDOM_GENERATOR_TYPE.BROWSER_CRYPTO) { var array = new Uint32Array(1); window.crypto.getRandomValues(array); return array[0] * 2.3283064365386963e-10; // 2^-32 } else { throw new Error('Unknown random generator type: ' + this.type); } } }, { key: 'hexString', value: function hexString(digits) { if (this.type === RANDOM_GENERATOR_TYPE.NODE_CRYPTO) { var nodeCrypto = require('crypto'); var numBytes = Math.ceil(digits / 2); // Try to get cryptographically strong randomness. Fall back to // non-cryptographically strong if not available. var bytes = (0, _try3.default)(function () { return nodeCrypto.randomBytes(numBytes); }); if (bytes instanceof Error) { bytes = nodeCrypto.pseudoRandomBytes(numBytes); } var result = bytes.toString('hex'); // If the number of digits is odd, we'll have generated an extra 4 bits // of randomness, so we need to trim the last digit. return result.substring(0, digits); } else { return this._randomString(digits, '0123456789abcdef'); } } }, { key: '_randomString', value: function _randomString(charsCount, alphabet) { var digits = []; for (var i = 0; i < charsCount; i++) { digits[i] = this.choice(alphabet); } return digits.join(''); } }, { key: 'id', value: function id(charsCount) { // 17 characters is around 96 bits of entropy, which is the amount of // state in the Alea PRNG. if (charsCount === undefined) { charsCount = 17; } return this._randomString(charsCount, UNMISTAKABLE_CHARS); } }, { key: 'secret', value: function secret(charsCount) { // Default to 256 bits of entropy, or 43 characters at 6 bits per // character. if (charsCount === undefined) { charsCount = 43; } return this._randomString(charsCount, BASE64_CHARS); } }, { key: 'choice', value: function choice(arrayOrString) { var index = Math.floor(this.fraction() * arrayOrString.length); if (typeof arrayOrString === 'string') { return arrayOrString.substr(index, 1); } else { return arrayOrString[index]; } } }], [{ key: 'default', value: function _default() { if (!_defaultRandomGenerator) { if (typeof window !== 'undefined') { if (window.crypto && window.crypto.getRandomValues) { return new Random(RANDOM_GENERATOR_TYPE.BROWSER_CRYPTO); } else { return new Random(RANDOM_GENERATOR_TYPE.ALEA, { seeds: _getBrowserSeeds() }); } } else { return new Random(RANDOM_GENERATOR_TYPE.NODE_CRYPTO); } } return _defaultRandomGenerator; } }, { key: 'createWithSeeds', value: function createWithSeeds() { (0, _invariant2.default)(arguments.length, 'Random.createWithSeeds(...): no seeds were provided'); return new Random(RANDOM_GENERATOR_TYPE.ALEA, { seeds: arguments }); } }]); return Random; }(); exports.default = Random;