All files / app/assets/javascripts/lib/utils uuids.js

100% Statements 22/22
88.88% Branches 8/9
100% Functions 6/6
100% Lines 21/21

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77                                      37x 122x   122x 18x 104x 104x     122x             233x 37x   196x     233x       261x   261x 1044x 1044x   1044x   1044x     261x                     233x 233x         261x      
/**
 * @module uuids
 */
 
/**
 * A string or number representing a start state for a random generator
 * @typedef {(Number|String)} Seed
 */
/**
 * A UUIDv4 string in the format <code>Hex{8}-Hex{4}-4Hex{3}-[89ab]Hex{3}-Hex{12}</code>
 * @typedef {String} UUIDv4
 */
 
import { MersenneTwister } from 'fast-mersenne-twister';
import { isString } from 'lodash';
import stringHash from 'string-hash';
import { v4 } from 'uuid';
 
function getSeed(seeds) {
  return seeds.reduce((seedling, seed, i) => {
    let thisSeed = 0;
 
    if (Number.isInteger(seed)) {
      thisSeed = seed;
    } else Eif (isString(seed)) {
      thisSeed = stringHash(seed);
    }
 
    return seedling + (seeds.length - i) * thisSeed;
  }, 0);
}
 
function getPseudoRandomNumberGenerator(...seeds) {
  let seedNumber;
 
  if (seeds.length) {
    seedNumber = getSeed(seeds);
  } else {
    seedNumber = Math.floor(Math.random() * 10 ** 15);
  }
 
  return new MersenneTwister(seedNumber);
}
 
function randomValuesForUuid(prng) {
  const randomValues = [];
 
  for (let i = 0; i <= 3; i += 1) {
    const buffer = new ArrayBuffer(4);
    const view = new DataView(buffer);
 
    view.setUint32(0, prng.randomNumber());
 
    randomValues.push(view.getUint8(0), view.getUint8(1), view.getUint8(2), view.getUint8(3));
  }
 
  return randomValues;
}
 
/**
 * Get an array of UUIDv4s
 * @param {Object} [options={}]
 * @param {Seed[]} [options.seeds=[]] - A list of mixed strings or numbers to seed the UUIDv4 generator
 * @param {Number} [options.count=1] - A total number of UUIDv4s to generate
 * @returns {UUIDv4[]} An array of UUIDv4s
 */
export function uuids({ seeds = [], count = 1 } = {}) {
  const rng = getPseudoRandomNumberGenerator(...seeds);
  return (
    // Create an array the same size as the number of UUIDs requested
    Array(count)
      .fill(0)
      // Replace each slot in the array with a UUID which needs 16 (pseudo)random values to generate
      .map(() => v4({ random: randomValuesForUuid(rng) }))
  );
}