Files
gridpilot.gg/adapters/bootstrap/racing/SeedIdHelper.ts
2025-12-29 19:44:11 +01:00

76 lines
2.5 KiB
TypeScript

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);
}