snippets.browser.ts47 lines · main
| 1 | import { IS_PLATFORM } from 'common' |
| 2 | import { compact } from 'lodash' |
| 3 | import { v4 as uuidv4 } from 'uuid' |
| 4 | |
| 5 | /** |
| 6 | * Generates a UUID v4. If the platform is self-hosted, it will generate a deterministic UUID v4 from the inputs. |
| 7 | */ |
| 8 | export const generateUuid = (inputs: (string | undefined | null)[] = []) => { |
| 9 | const cleaned = compact(inputs) |
| 10 | if (!IS_PLATFORM && cleaned.length === 0) return uuidv4() |
| 11 | return IS_PLATFORM ? uuidv4() : generateDeterministicUuid(cleaned) |
| 12 | } |
| 13 | |
| 14 | /** |
| 15 | * Generates a deterministic UUID v4 from a string input |
| 16 | * @param inputs - The array of strings to generate a UUID from |
| 17 | * @returns A deterministic UUID v4 string |
| 18 | */ |
| 19 | export function generateDeterministicUuid(inputs: (string | undefined | null)[]): string { |
| 20 | const simpleHash = (str: string): number => { |
| 21 | let hash = 0 |
| 22 | if (str.length === 0) return hash |
| 23 | for (let i = 0; i < str.length; i++) { |
| 24 | const char = str.charCodeAt(i) |
| 25 | hash = (hash << 5) - hash + char |
| 26 | hash = hash & hash // Convert to 32-bit integer |
| 27 | } |
| 28 | return Math.abs(hash) |
| 29 | } |
| 30 | |
| 31 | const input = compact(inputs).join('_') |
| 32 | |
| 33 | // Create a deterministic random number generator using the hash as seed |
| 34 | let seed = simpleHash(input) |
| 35 | const rng = () => { |
| 36 | const bytes = new Uint8Array(16) |
| 37 | for (let i = 0; i < 16; i++) { |
| 38 | // Simple LCG (Linear Congruential Generator) for deterministic randomness |
| 39 | seed = (seed * 1103515245 + 12345) & 0x7fffffff |
| 40 | bytes[i] = (seed >>> 16) & 0xff |
| 41 | } |
| 42 | return bytes |
| 43 | } |
| 44 | |
| 45 | // Generate UUID v4 using the deterministic RNG |
| 46 | return uuidv4({ rng }) |
| 47 | } |