snowflakify
Version:
The most complete Snowflake ID generator in TypeScript
91 lines (90 loc) • 2.84 kB
TypeScript
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;
}