/** * UUID v4 generator. * * Uses crypto.getRandomValues when available (React Native / modern browsers) * and falls back to Math.random otherwise. */ export function uuid(): string { if (typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function') { // Native crypto path const bytes = new Uint8Array(16); crypto.getRandomValues(bytes); // Set version 4 bits bytes[6] = (bytes[6] & 0x0f) | 0x40; // Set variant bits (RFC 4122) bytes[8] = (bytes[8] & 0x3f) | 0x80; return formatBytes(bytes); } // Fallback: Math.random based return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { const r = (Math.random() * 16) | 0; const v = c === 'x' ? r : (r & 0x3) | 0x8; return v.toString(16); }); } function formatBytes(bytes: Uint8Array): string { const hex: string[] = []; for (let i = 0; i < bytes.length; i++) { hex.push(bytes[i].toString(16).padStart(2, '0')); } return [ hex.slice(0, 4).join(''), hex.slice(4, 6).join(''), hex.slice(6, 8).join(''), hex.slice(8, 10).join(''), hex.slice(10, 16).join(''), ].join('-'); }