Last active
November 10, 2025 20:38
-
-
Save jamesperrin/37a5879005d3b4c360076380e99597c9 to your computer and use it in GitHub Desktop.
Generates a RFC 4122 version 4 UUID using cryptographically secure random numbers.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * @file uuidv4.js | |
| * @description | |
| * Generates an RFC 4122 version 4 UUID using cryptographically secure random numbers. | |
| * Works in modern browsers and Node.js environments that support the global `crypto` object. | |
| * | |
| * @example | |
| * import { uuidv4 } from './uuidv4.js'; | |
| * console.log(uuidv4()); // "e7b4a2c1-4f6e-4cbb-8a14-9e7bcd84f96b" | |
| */ | |
| /** | |
| * Generates cryptographically secure random bytes. | |
| * Falls back to Node.js `crypto.randomFillSync` if `crypto.getRandomValues` is not available. | |
| * | |
| * @param {Uint8Array} arr - A typed array to fill with random values. | |
| * @returns {Uint8Array} The filled array of random bytes. | |
| * @throws {Error} If no cryptographically secure random number generator is available. | |
| */ | |
| function getSecureRandomValues(arr) { | |
| if (typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function') { | |
| // Browser or modern Node.js | |
| return crypto.getRandomValues(arr); | |
| } else if (typeof require === 'function') { | |
| // Fallback for older Node.js versions | |
| try { | |
| const { randomFillSync } = require('crypto'); | |
| return randomFillSync(arr); | |
| } catch { | |
| throw new Error('No cryptographically secure random number generator available.'); | |
| } | |
| } else { | |
| throw new Error('No cryptographically secure random number generator available.'); | |
| } | |
| } | |
| /** | |
| * Generates a Version 4 (random) UUID as defined in RFC 4122. | |
| * | |
| * The UUID format is `xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`, where: | |
| * - `x` is any hexadecimal digit. | |
| * - `y` is one of `8`, `9`, `A`, or `B`. | |
| * | |
| * @returns {string} A randomly generated UUIDv4 string. | |
| */ | |
| export function uuidv4() { | |
| const bytes = getSecureRandomValues(new Uint8Array(16)); | |
| // Set version (4) and variant (10xx) | |
| bytes[6] = (bytes[6] & 0x0f) | 0x40; | |
| bytes[8] = (bytes[8] & 0x3f) | 0x80; | |
| const hex = Array.from(bytes, (b) => b.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).join('')}` | |
| ); | |
| } | |
| export default uuidv4; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * @file uuidv4.mjs | |
| * @description | |
| * Generates an RFC 4122 version 4 UUID using cryptographically secure random numbers. | |
| * Works in modern browsers and Node.js environments that support the global `crypto` object. | |
| * | |
| * @example | |
| * import { uuidv4 } from './uuidv4.mjs'; | |
| * console.log(uuidv4()); // "e7b4a2c1-4f6e-4cbb-8a14-9e7bcd84f96b" | |
| */ | |
| /** | |
| * Generates cryptographically secure random bytes. | |
| * Falls back to Node.js `crypto.randomFillSync` if `crypto.getRandomValues` is not available. | |
| * | |
| * @param {Uint8Array} arr - A typed array to fill with random values. | |
| * @returns {Uint8Array} The filled array of random bytes. | |
| * @throws {Error} If no cryptographically secure random number generator is available. | |
| */ | |
| function getSecureRandomValues(arr) { | |
| if (typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function') { | |
| return crypto.getRandomValues(arr); // Browser or modern Node | |
| } else if (typeof require === 'function') { | |
| // Fallback for older Node.js versions | |
| try { | |
| const { randomFillSync } = require('crypto'); | |
| return randomFillSync(arr); | |
| } catch { | |
| throw new Error('No cryptographically secure random number generator available.'); | |
| } | |
| } else { | |
| throw new Error('No cryptographically secure random number generator available.'); | |
| } | |
| } | |
| /** | |
| * Generates a Version 4 (random) UUID as defined in RFC 4122. | |
| * | |
| * The UUID format is 8-4-4-4-12 hexadecimal digits, such as: | |
| * `xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx` | |
| * | |
| * @returns {string} A randomly generated UUIDv4 string. | |
| */ | |
| export function uuidv4() { | |
| const bytes = getSecureRandomValues(new Uint8Array(16)); | |
| // Set version (4) and variant (10xx) | |
| bytes[6] = (bytes[6] & 0x0f) | 0x40; | |
| bytes[8] = (bytes[8] & 0x3f) | 0x80; | |
| const hex = Array.from(bytes, b => b.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).join('')}` | |
| ); | |
| } | |
| export default uuidv4; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * @file uuidv4.ts | |
| * @description | |
| * Generates an RFC 4122 version 4 UUID using cryptographically secure random numbers. | |
| * Works in modern browsers and Node.js environments that support the global `crypto` object. | |
| * | |
| * @example | |
| * import { uuidv4 } from './uuidv4'; | |
| * console.log(uuidv4()); // "e7b4a2c1-4f6e-4cbb-8a14-9e7bcd84f96b" | |
| */ | |
| /** | |
| * Generates cryptographically secure random bytes. | |
| * Falls back to Node.js `crypto.randomFillSync` if `crypto.getRandomValues` is not available. | |
| * | |
| * @param arr - A typed array to fill with random values. | |
| * @returns The filled array of random bytes. | |
| * @throws {Error} If no cryptographically secure random number generator is available. | |
| */ | |
| function getSecureRandomValues(arr: Uint8Array): Uint8Array { | |
| if (typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function') { | |
| // Browser or modern Node.js | |
| return crypto.getRandomValues(arr); | |
| } else if (typeof require === 'function') { | |
| // Fallback for older Node.js versions | |
| try { | |
| const { randomFillSync } = require('crypto') as typeof import('crypto'); | |
| return randomFillSync(arr); | |
| } catch { | |
| throw new Error('No cryptographically secure random number generator available.'); | |
| } | |
| } else { | |
| throw new Error('No cryptographically secure random number generator available.'); | |
| } | |
| } | |
| /** | |
| * Generates a Version 4 (random) UUID as defined in RFC 4122. | |
| * | |
| * The UUID format is `xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`, where: | |
| * - `x` is any hexadecimal digit. | |
| * - `y` is one of `8`, `9`, `A`, or `B`. | |
| * | |
| * @returns A randomly generated UUIDv4 string. | |
| */ | |
| export function uuidv4(): string { | |
| const bytes = getSecureRandomValues(new Uint8Array(16)); | |
| // Set version (4) and variant (10xx) | |
| bytes[6] = (bytes[6] & 0x0f) | 0x40; | |
| bytes[8] = (bytes[8] & 0x3f) | 0x80; | |
| const hex = Array.from(bytes, (b) => b.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).join('')}` | |
| ); | |
| } | |
| export default uuidv4; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * | |
| * @file uuidv4.js | |
| * @description* | |
| * Generates a RFC 4122 version 4 UUID using cryptographically secure random numbers. | |
| * Falls back to Node.js crypto if not in a browser. | |
| * Throws if no cryptographically secure PRNG is available. | |
| * | |
| * Vibe coding using GitHub CoPilot and ChatGPT. | |
| * | |
| * @example | |
| * import { uuidv4 } from './uuidv4.js'; | |
| * console.log(uuidv4()); // "e7b4a2c1-4f6e-4cbb-8a14-9e7bcd84f96b" | |
| * | |
| * @returns {string} The generated UUID string in the standard 8-4-4-4-12 format. // "e7b4a2c1-4f6e-4cbb-8a14-9e7bcd84f96b" | |
| */ | |
| (function (global, factory) { | |
| if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { | |
| // CommonJS (Node.js) | |
| module.exports = factory(require('crypto')); | |
| } else if (typeof define === 'function' && define.amd) { | |
| // AMD (if needed) | |
| define(['crypto'], factory); | |
| } else { | |
| // Browser global | |
| global.uuidv4 = factory(global.crypto); | |
| } | |
| })(typeof globalThis !== 'undefined' ? globalThis : this, function (cryptoSource) { | |
| function getSecureRandomValues(arr) { | |
| if (cryptoSource && typeof cryptoSource.getRandomValues === 'function') { | |
| return cryptoSource.getRandomValues(arr); // Browser | |
| } else if (cryptoSource && typeof cryptoSource.randomFillSync === 'function') { | |
| return cryptoSource.randomFillSync(arr); // Node.js | |
| } else { | |
| throw new Error('No cryptographically secure random number generator available.'); | |
| } | |
| } | |
| function uuidv4() { | |
| const bytes = getSecureRandomValues(new Uint8Array(16)); | |
| // Set version and variant bits | |
| bytes[6] = (bytes[6] & 0x0f) | 0x40; // Version 4 | |
| bytes[8] = (bytes[8] & 0x3f) | 0x80; // Variant 10xx | |
| const hex = Array.from(bytes, (b) => b.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).join('')}` | |
| ); | |
| } | |
| return uuidv4; | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment