UNPKG

snowflakify

Version:

The most complete Snowflake ID generator in TypeScript

91 lines (90 loc) 2.84 kB
import FragmentBase from '../FragmentBase.js'; import SequenceFragment from './SequenceFragment.js'; import { DestructuredFragment } from '../@types/index.js'; /** * TimestampFragment class for timestamp IDs. * @public */ export default class TimestampFragment extends FragmentBase { /** * Reference to the SequenceFragment instance. * This is used to check for sequence collisions, * and to reset the sequence when necessary. */ private sequenceFragmentRef; /** * Value of the last timestamp. */ private lastTimestamp; /** * Epoch timestamp used to calculate the fragment's timestamps. * @readonly */ private readonly epoch; /** * Time unit used to convert the nanosecond timestamp to. * - `1`: nanosecond * - `10 ** 3`: microsecond * - `10 ** 6`: millisecond * @readonly */ private readonly timeUnit; /** * Nanosecond time reference. * * @remarks * Date.now() returns the number of milliseconds since the Unix epoch. * hrtime.bigint() returns a high-resolution time value in nanoseconds, * however it is relative to an arbitrary time in the past and not the Unix epoch. * * If `x` hrtime was taken at `y` Unix timestamp, then when we recapture a * hrttime at `x'` we can calculate the time with the following formula: * * `y + (x' - x)` or `(y - x) + x'` * @readonly */ private readonly nanoTimeAnchor; /** * @param bits - The number of bits for the fragment. * @param epoch - A custom epoch timestamp. * * Defaults to `1420070400000` (2015-01-01 00:00:00) if omitted. * * @throws `[TIMESTAMP_BITS_INVALID_RANGE]` If bits is less than 38 * @throws `[EPOCH_INVALID_TYPE]` If epoch is not a number * @throws `[EPOCH_INVALID_RANGE]` If epoch is not within 0 and Date.now() */ constructor(bits: number, epoch?: number); /** * @internal */ set sequenceFragmentReference(sequenceFragment: SequenceFragment); getValue(): bigint; destructure(snowflake: number | bigint | string): DestructuredFragment; /** * Returns a Unix timestamp. * * @remarks * The number of the fragment's bits defines the time unit. * This is done to avoid overflow when left shifting. * * @returns A Unix timestamp in the fragment's time unit. * @internal */ private unixNow; /** * Wait for the next timestamp. * @internal */ private waitForNextTimestamp; /** * Check for sequence collision. * * @remarks * If a sequence completes its cycle, and the timestamp * is still the same, an already generated snowflake will * be re-generated. * @internal */ private checkForSequenceCollision; }