UNPKG

@tangential/core

Version:

Core types and support code for Tangential

60 lines 8.44 kB
/** * From https://gist.github.com/mikelehen/3596a30bd69384624c11, via Firebase blog at * https://firebase.googleblog.com/2015/02/the-2120-ways-to-ensure-unique_68.html * With minor tweaks for use with TypeScript **/ /** * Fancy ID generator that creates 20-character string identifiers with the following properties: * * 1. They're based on timestamp so that they sort *after* any existing ids. * 2. They contain 72-bits of random data after the timestamp so that IDs won't collide with other clients' IDs. * 3. They sort *lexicographically* (so the timestamp is converted to characters that will sort properly). * 4. They're monotonically increasing. Even if you generate more than one in the same timestamp, the * latter ones will sort after the former ones. We do this by using the previous random bits * but "incrementing" them by 1 (only in the case of a timestamp collision). */ // Modeled after base64 web-safe chars, but ordered by ASCII. const PUSH_CHARS = '-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz'; // Timestamp of last push, used to prevent local collisions if you push twice in one ms. let lastPushTime = 0; // We generate 72-bits of randomness which get turned into 12 characters and appended to the // timestamp to prevent collisions with other clients. We store the last characters we // generated because in the event of a collision, we'll use those same characters except // "incremented" by one. const lastRandChars = []; export const generatePushID = function () { let i; let now = Date.now(); const duplicateTime = (now === lastPushTime); lastPushTime = now; const timeStampChars = new Array(8); for (i = 7; i >= 0; i--) { timeStampChars[i] = PUSH_CHARS.charAt(now % 64); // NOTE: Can't use << here because javascript will convert to int and lose the upper bits. now = Math.floor(now / 64); } if (now !== 0) { throw new Error('We should have converted the entire timestamp.'); } let id = timeStampChars.join(''); if (!duplicateTime) { for (i = 0; i < 12; i++) { lastRandChars[i] = Math.floor(Math.random() * 64); } } else { // If the timestamp hasn't changed since last push, use the same random number, except incremented by 1. for (i = 11; i >= 0 && lastRandChars[i] === 63; i--) { lastRandChars[i] = 0; } lastRandChars[i]++; } for (i = 0; i < 12; i++) { id += PUSH_CHARS.charAt(lastRandChars[i]); } if (id.length !== 20) { throw new Error('Length should be 20.'); } return id; }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXJhdGUtcHVzaC1pZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3RhbmdlbnRpYWwvY29yZS9zcmMvbGliL3V0aWwvZ2VuZXJhdGUtcHVzaC1pZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztJQUlJO0FBR0o7Ozs7Ozs7OztHQVNHO0FBRUgsNkRBQTZEO0FBQzdELE1BQU0sVUFBVSxHQUFHLGtFQUFrRSxDQUFDO0FBQ3RGLHdGQUF3RjtBQUN4RixJQUFJLFlBQVksR0FBVyxDQUFDLENBQUM7QUFFN0IsNEZBQTRGO0FBQzVGLHVGQUF1RjtBQUN2Rix3RkFBd0Y7QUFDeEYsd0JBQXdCO0FBQ3hCLE1BQU0sYUFBYSxHQUFhLEVBQUUsQ0FBQztBQUVuQyxNQUFNLENBQUMsTUFBTSxjQUFjLEdBQWlCO0lBQzFDLElBQUksQ0FBUyxDQUFDO0lBQ2QsSUFBSSxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBQ3JCLE1BQU0sYUFBYSxHQUFHLENBQUMsR0FBRyxLQUFLLFlBQVksQ0FBQyxDQUFDO0lBQzdDLFlBQVksR0FBRyxHQUFHLENBQUM7SUFFbkIsTUFBTSxjQUFjLEdBQUcsSUFBSSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDcEMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7UUFDdkIsY0FBYyxDQUFDLENBQUMsQ0FBQyxHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQyxDQUFDO1FBQ2hELDBGQUEwRjtRQUMxRixHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDLENBQUM7S0FDNUI7SUFDRCxJQUFJLEdBQUcsS0FBSyxDQUFDLEVBQUU7UUFDYixNQUFNLElBQUksS0FBSyxDQUFDLGdEQUFnRCxDQUFDLENBQUM7S0FDbkU7SUFHRCxJQUFJLEVBQUUsR0FBRyxjQUFjLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBRWpDLElBQUksQ0FBQyxhQUFhLEVBQUU7UUFDbEIsS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDdkIsYUFBYSxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDO1NBQ25EO0tBQ0Y7U0FBTTtRQUNMLHdHQUF3RztRQUN4RyxLQUFLLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxhQUFhLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQ25ELGFBQWEsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7U0FDdEI7UUFDRCxhQUFhLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztLQUNwQjtJQUNELEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFO1FBQ3ZCLEVBQUUsSUFBSSxVQUFVLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0tBQzNDO0lBQ0QsSUFBSSxFQUFFLENBQUMsTUFBTSxLQUFLLEVBQUUsRUFBRTtRQUNwQixNQUFNLElBQUksS0FBSyxDQUFDLHNCQUFzQixDQUFDLENBQUM7S0FDekM7SUFFRCxPQUFPLEVBQUUsQ0FBQztBQUNaLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogRnJvbSBodHRwczovL2dpc3QuZ2l0aHViLmNvbS9taWtlbGVoZW4vMzU5NmEzMGJkNjkzODQ2MjRjMTEsIHZpYSBGaXJlYmFzZSBibG9nIGF0XG4gKiBodHRwczovL2ZpcmViYXNlLmdvb2dsZWJsb2cuY29tLzIwMTUvMDIvdGhlLTIxMjAtd2F5cy10by1lbnN1cmUtdW5pcXVlXzY4Lmh0bWxcbiAqIFdpdGggbWlub3IgdHdlYWtzIGZvciB1c2Ugd2l0aCBUeXBlU2NyaXB0XG4gKiovXG5cblxuLyoqXG4gKiBGYW5jeSBJRCBnZW5lcmF0b3IgdGhhdCBjcmVhdGVzIDIwLWNoYXJhY3RlciBzdHJpbmcgaWRlbnRpZmllcnMgd2l0aCB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXM6XG4gKlxuICogMS4gVGhleSdyZSBiYXNlZCBvbiB0aW1lc3RhbXAgc28gdGhhdCB0aGV5IHNvcnQgKmFmdGVyKiBhbnkgZXhpc3RpbmcgaWRzLlxuICogMi4gVGhleSBjb250YWluIDcyLWJpdHMgb2YgcmFuZG9tIGRhdGEgYWZ0ZXIgdGhlIHRpbWVzdGFtcCBzbyB0aGF0IElEcyB3b24ndCBjb2xsaWRlIHdpdGggb3RoZXIgY2xpZW50cycgSURzLlxuICogMy4gVGhleSBzb3J0ICpsZXhpY29ncmFwaGljYWxseSogKHNvIHRoZSB0aW1lc3RhbXAgaXMgY29udmVydGVkIHRvIGNoYXJhY3RlcnMgdGhhdCB3aWxsIHNvcnQgcHJvcGVybHkpLlxuICogNC4gVGhleSdyZSBtb25vdG9uaWNhbGx5IGluY3JlYXNpbmcuICBFdmVuIGlmIHlvdSBnZW5lcmF0ZSBtb3JlIHRoYW4gb25lIGluIHRoZSBzYW1lIHRpbWVzdGFtcCwgdGhlXG4gKiAgICBsYXR0ZXIgb25lcyB3aWxsIHNvcnQgYWZ0ZXIgdGhlIGZvcm1lciBvbmVzLiAgV2UgZG8gdGhpcyBieSB1c2luZyB0aGUgcHJldmlvdXMgcmFuZG9tIGJpdHNcbiAqICAgIGJ1dCBcImluY3JlbWVudGluZ1wiIHRoZW0gYnkgMSAob25seSBpbiB0aGUgY2FzZSBvZiBhIHRpbWVzdGFtcCBjb2xsaXNpb24pLlxuICovXG5cbi8vIE1vZGVsZWQgYWZ0ZXIgYmFzZTY0IHdlYi1zYWZlIGNoYXJzLCBidXQgb3JkZXJlZCBieSBBU0NJSS5cbmNvbnN0IFBVU0hfQ0hBUlMgPSAnLTAxMjM0NTY3ODlBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWl9hYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5eic7XG4vLyBUaW1lc3RhbXAgb2YgbGFzdCBwdXNoLCB1c2VkIHRvIHByZXZlbnQgbG9jYWwgY29sbGlzaW9ucyBpZiB5b3UgcHVzaCB0d2ljZSBpbiBvbmUgbXMuXG5sZXQgbGFzdFB1c2hUaW1lOiBudW1iZXIgPSAwO1xuXG4vLyBXZSBnZW5lcmF0ZSA3Mi1iaXRzIG9mIHJhbmRvbW5lc3Mgd2hpY2ggZ2V0IHR1cm5lZCBpbnRvIDEyIGNoYXJhY3RlcnMgYW5kIGFwcGVuZGVkIHRvIHRoZVxuLy8gdGltZXN0YW1wIHRvIHByZXZlbnQgY29sbGlzaW9ucyB3aXRoIG90aGVyIGNsaWVudHMuICBXZSBzdG9yZSB0aGUgbGFzdCBjaGFyYWN0ZXJzIHdlXG4vLyBnZW5lcmF0ZWQgYmVjYXVzZSBpbiB0aGUgZXZlbnQgb2YgYSBjb2xsaXNpb24sIHdlJ2xsIHVzZSB0aG9zZSBzYW1lIGNoYXJhY3RlcnMgZXhjZXB0XG4vLyBcImluY3JlbWVudGVkXCIgYnkgb25lLlxuY29uc3QgbGFzdFJhbmRDaGFyczogbnVtYmVyW10gPSBbXTtcblxuZXhwb3J0IGNvbnN0IGdlbmVyYXRlUHVzaElEOiAoKSA9PiBzdHJpbmcgPSBmdW5jdGlvbiAoKSB7XG4gIGxldCBpOiBudW1iZXI7XG4gIGxldCBub3cgPSBEYXRlLm5vdygpO1xuICBjb25zdCBkdXBsaWNhdGVUaW1lID0gKG5vdyA9PT0gbGFzdFB1c2hUaW1lKTtcbiAgbGFzdFB1c2hUaW1lID0gbm93O1xuXG4gIGNvbnN0IHRpbWVTdGFtcENoYXJzID0gbmV3IEFycmF5KDgpO1xuICBmb3IgKGkgPSA3OyBpID49IDA7IGktLSkge1xuICAgIHRpbWVTdGFtcENoYXJzW2ldID0gUFVTSF9DSEFSUy5jaGFyQXQobm93ICUgNjQpO1xuICAgIC8vIE5PVEU6IENhbid0IHVzZSA8PCBoZXJlIGJlY2F1c2UgamF2YXNjcmlwdCB3aWxsIGNvbnZlcnQgdG8gaW50IGFuZCBsb3NlIHRoZSB1cHBlciBiaXRzLlxuICAgIG5vdyA9IE1hdGguZmxvb3Iobm93IC8gNjQpO1xuICB9XG4gIGlmIChub3cgIT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1dlIHNob3VsZCBoYXZlIGNvbnZlcnRlZCB0aGUgZW50aXJlIHRpbWVzdGFtcC4nKTtcbiAgfVxuXG5cbiAgbGV0IGlkID0gdGltZVN0YW1wQ2hhcnMuam9pbignJyk7XG5cbiAgaWYgKCFkdXBsaWNhdGVUaW1lKSB7XG4gICAgZm9yIChpID0gMDsgaSA8IDEyOyBpKyspIHtcbiAgICAgIGxhc3RSYW5kQ2hhcnNbaV0gPSBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiA2NCk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIC8vIElmIHRoZSB0aW1lc3RhbXAgaGFzbid0IGNoYW5nZWQgc2luY2UgbGFzdCBwdXNoLCB1c2UgdGhlIHNhbWUgcmFuZG9tIG51bWJlciwgZXhjZXB0IGluY3JlbWVudGVkIGJ5IDEuXG4gICAgZm9yIChpID0gMTE7IGkgPj0gMCAmJiBsYXN0UmFuZENoYXJzW2ldID09PSA2MzsgaS0tKSB7XG4gICAgICBsYXN0UmFuZENoYXJzW2ldID0gMDtcbiAgICB9XG4gICAgbGFzdFJhbmRDaGFyc1tpXSsrO1xuICB9XG4gIGZvciAoaSA9IDA7IGkgPCAxMjsgaSsrKSB7XG4gICAgaWQgKz0gUFVTSF9DSEFSUy5jaGFyQXQobGFzdFJhbmRDaGFyc1tpXSk7XG4gIH1cbiAgaWYgKGlkLmxlbmd0aCAhPT0gMjApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0xlbmd0aCBzaG91bGQgYmUgMjAuJyk7XG4gIH1cblxuICByZXR1cm4gaWQ7XG59O1xuIl19