/** * UUID v7 Generator for Node.js * Generates time-ordered UUIDs per RFC 9562 * * Format: tttttttt-tttt-7xxx-yxxx-xxxxxxxxxxxx * - t = timestamp (48 bits) * - 7 = version * - x = random * - y = variant (8, 9, a, or b) */ import crypto from 'crypto'; /** * Generate a UUID v7 (time-ordered) * @returns {string} UUID v7 string */ export function uuidv7() { // Get current timestamp in milliseconds const timestamp = Date.now(); // Generate random bytes const randomBytes = crypto.randomBytes(10); // Build UUID bytes (16 total) const bytes = Buffer.alloc(16); // First 6 bytes: timestamp (48 bits, big-endian) bytes.writeUInt32BE(Math.floor(timestamp / 0x10000), 0); bytes.writeUInt16BE(timestamp & 0xFFFF, 4); // Next 2 bytes: version (4 bits = 7) + random (12 bits) bytes[6] = 0x70 | (randomBytes[0] & 0x0F); // version 7 bytes[7] = randomBytes[1]; // Last 8 bytes: variant (2 bits = 10) + random (62 bits) bytes[8] = 0x80 | (randomBytes[2] & 0x3F); // variant RFC 4122 randomBytes.copy(bytes, 9, 3, 10); // Format as UUID string const hex = bytes.toString('hex'); return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`; } /** * Validate if a string is a valid UUID (any version) * @param {string} uuid * @returns {boolean} */ export function isValidUUID(uuid) { const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; return uuidRegex.test(uuid); } /** * Get UUID version from a UUID string * @param {string} uuid * @returns {number} version (1-7) or 0 if invalid */ export function getUUIDVersion(uuid) { if (!isValidUUID(uuid)) return 0; return parseInt(uuid.charAt(14), 16); } // Export default for convenience export default { uuidv7, isValidUUID, getUUIDVersion };