import { createHash } from 'crypto'; /** * Generates a deterministic UUID v4 from a seed string. * * This is used for postgres seeding to ensure all IDs are valid UUIDs * while maintaining determinism across runs (important for tests and reproducible seeds). * * The function uses SHA-256 hash of the seed, then formats it as a UUID v4 * with proper version (0100) and variant (10xx) bits. * * @param seedKey - The deterministic seed string (e.g., "team-3", "driver-1") * @returns A valid UUID v4 string * * @example * stableUuidFromSeedKey("team-3") * // Returns: "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d" (deterministic) */ export function stableUuidFromSeedKey(seedKey: string): string { // Create a deterministic hash from the seed const hash = createHash('sha256').update(seedKey).digest('hex'); // Take first 32 characters for UUID const uuidHex = hash.substring(0, 32); // Format as UUID v4 with proper version and variant bits // UUID v4 format: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx // where x is any hex digit, y is one of [8, 9, a, b] // Build the UUID step by step const part1 = uuidHex.substring(0, 8); const part2 = uuidHex.substring(8, 12); const part3 = '4' + uuidHex.substring(13, 16); // Version 4 const variantChar = ['8', '9', 'a', 'b'][parseInt(uuidHex.charAt(16), 16) % 4]; const part4 = variantChar + uuidHex.substring(17, 20); const part5 = uuidHex.substring(20, 32); return `${part1}-${part2}-${part3}-${part4}-${part5}`; } /** * Returns an ID appropriate for the current persistence mode. * * For postgres mode: returns a deterministic UUID * For inmemory mode: returns the original deterministic string ID * * @param seedKey - The deterministic seed string (e.g., "team-3") * @param mode - The persistence mode * @returns Either a UUID (postgres) or the original string (inmemory) * * @example * seedId("team-3", "postgres") // Returns UUID * seedId("team-3", "inmemory") // Returns "team-3" */ export function seedId(seedKey: string, mode: 'postgres' | 'inmemory'): string { if (mode === 'postgres') { return stableUuidFromSeedKey(seedKey); } return seedKey; } /** * Returns a UUID for postgres seeding. * * Convenience wrapper around seedId with mode already set to 'postgres'. * Use this when you know you're in postgres mode. * * @param seedKey - The deterministic seed string * @returns A valid UUID v4 string * * @example * seedUuid("driver-1") // Returns UUID */ export function seedUuid(seedKey: string): string { return stableUuidFromSeedKey(seedKey); }