@tanstack/db
Version:
A reactive client store for building super fast apps on sync
46 lines (41 loc) • 1.41 kB
text/typescript
/**
* Returns a RFC 4122 version 4 UUID.
*
* Prefers `crypto.randomUUID()` when available. In non-secure browser contexts
* (e.g. a dev server accessed via a LAN IP over HTTP) `crypto.randomUUID` is
* `undefined`, so this falls back to building a UUIDv4 from
* `crypto.getRandomValues`. Throws if neither API is available.
*
* See https://github.com/TanStack/db/issues/1541.
*/
export function safeRandomUUID(): string {
const c: Crypto | undefined =
typeof globalThis !== `undefined` ? (globalThis as any).crypto : undefined
if (c && typeof c.randomUUID === `function`) {
return c.randomUUID()
}
if (c && typeof c.getRandomValues === `function`) {
const bytes = c.getRandomValues(new Uint8Array(16))
// Per RFC 4122 §4.4: set version (4) and variant (10xx) bits.
bytes[6] = (bytes[6]! & 0x0f) | 0x40
bytes[8] = (bytes[8]! & 0x3f) | 0x80
const hex: Array<string> = []
for (let i = 0; i < 16; 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(``)
)
}
throw new Error(
`No secure random number generator available: neither crypto.randomUUID nor crypto.getRandomValues is defined in this environment.`,
)
}