snowflakify
Version:
The most complete Snowflake ID generator in TypeScript
54 lines (53 loc) • 1.78 kB
JavaScript
import { randomInt } from 'crypto';
import FragmentBase from '../FragmentBase.js';
/**
* RandomFragment class for random IDs.
* @public
*/
export default class RandomFragment extends FragmentBase {
/**
* @remarks
* When using a custom random function, please ensure it returns a positive number
* no greater than `2 ** bits - 1`.
*
* @param bits - The number of bits for the fragment.
* @param fn - Optional custom random function.
*
* @throws `[RND_FUNCTION_RETURN_TYPE]` If custom function does not return number or bigint.
*/
constructor(bits, fn) {
super(bits);
this.fn = fn;
if (fn && !['number', 'bigint'].includes(typeof fn()))
throw new TypeError(
`[RND_FUNCTION_RETURN_TYPE]: RandomFragment custom function return is of type: ${typeof fn()}; Expected number or bigint.`,
);
}
getValue() {
if (this.fn) {
const rndNum = BigInt(this.fn());
if (rndNum >= BigInt(1 << this.bits))
throw new TypeError(
`[RND_FUNCTION_BAD_RETURN]: RandomFragment custom function returned a value bigger than 2 ** ${this.bits} - 1.`,
);
return rndNum;
}
if (this.bits <= 48) return BigInt(randomInt(1, 1 << 48)) - BigInt(1);
// 48 bit parts due to randomInt range limitation
// max param limit of Number.MAX_SAFE_INTEGER
let rndNum = BigInt(1);
for (let i = 1; i < this.bits / 48; i += 1) {
rndNum *= BigInt(randomInt(1, 1 << 48));
}
rndNum *= BigInt(randomInt(1, 1 << this.bits % 48));
return rndNum - BigInt(1);
}
destructure(snowflake) {
const bits = BigInt(snowflake) & this.bitMask;
return {
identifier: this.identifier,
value: bits >> this.bitShift,
};
}
}
//# sourceMappingURL=RandomFragment.js.map