export class SnowflakeGenerator { private epoch: bigint; private workerId: bigint; private processId: bigint; private sequence: bigint; private lastTimestamp: bigint; constructor(workerId: bigint = 1n, processId: bigint = 1n, epoch: bigint = 1766617200000n) { // dec 1 2025 (creation of this) this.epoch = epoch; this.workerId = workerId; this.processId = processId; this.sequence = 0n; this.lastTimestamp = -1n; } private getCurrentTimestamp(): bigint { return BigInt(Date.now()); } private waitForNextMillisecond(lastTimestamp: bigint): bigint { let timestamp = this.getCurrentTimestamp(); while (timestamp <= lastTimestamp) { timestamp = this.getCurrentTimestamp(); } return timestamp; } public generateSnowflake(): number { const timestamp = this.getCurrentTimestamp() - this.epoch; if (timestamp === this.lastTimestamp) { this.sequence += 1n; if (this.sequence > 4095n) { // max sequence value (12 bits) // Wait for the next millisecond if we've reached the max sequence value const newTimestamp = this.waitForNextMillisecond(this.lastTimestamp); this.sequence = 0n; return Number.parseInt(String(this.createSnowflake(newTimestamp))); } } else { this.sequence = 0n; } this.lastTimestamp = timestamp; return Number.parseInt(String(this.createSnowflake(timestamp))); } private createSnowflake(timestamp: bigint): bigint { return (timestamp << 22n) | (BigInt(this.workerId) << 18n) | (BigInt(this.processId) << 12n) | BigInt(this.sequence); } public decodeSnowflake(id: bigint | number) { const snowflake = BigInt(id); const sequence = snowflake & (1n << 6n) - 1n; const processId = (snowflake >> 6n) & ((1n << 6n) - 1n); const workerId = (snowflake >> 12n) & ((1n << 10n) - 1n); const timestamp = (snowflake >> 22n) + this.epoch; return { timestamp, // bigint (ms since Unix epoch) date: new Date(Number(timestamp)), workerId, processId, sequence, }; } }