Skip to content

Commit 123cc54

Browse files
committed
fix: add fallback for crypto.randomUUID browser compatibility
Implemented multi-tier UUID generation strategy to support older browsers and environments that don't have native crypto.randomUUID support. Includes RFC4122 v4 compliant fallback using Crypto API and Math.random() for maximum compatibility.
1 parent bf26874 commit 123cc54

2 files changed

Lines changed: 44 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Fixed
11+
- **Browser Compatibility**
12+
- Fixed "crypto.randomUUID is not a function" error in POS Events Store
13+
- Added robust UUID generation with multi-tier fallback strategy (native API → Crypto API → Math.random)
14+
- Implemented RFC4122 v4 compliant UUID generation for older browsers and environments
15+
- Performance optimization with pre-computed byte-to-hex lookup table
16+
- Support for globalThis, window.crypto, and legacy environments
17+
1018
## [1.7.1] - 2025-11-13
1119

1220
### Added

POS/src/stores/posEvents.js

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,41 @@ import { ref, computed } from 'vue'
1717
import { logger } from '@/utils/logger'
1818

1919
const log = logger.create('POSEvents')
20+
const byteToHex = Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'))
21+
22+
/**
23+
* Generate a UUID with fallback for environments that don't support crypto.randomUUID
24+
* @returns {string} - A unique identifier
25+
*/
26+
function generateUUID() {
27+
const cryptoSource = typeof globalThis !== 'undefined' && globalThis.crypto
28+
? globalThis.crypto
29+
: (typeof window !== 'undefined' ? window.crypto : undefined)
30+
31+
if (cryptoSource?.randomUUID) {
32+
try {
33+
return cryptoSource.randomUUID()
34+
} catch (error) {
35+
log.warn('crypto.randomUUID failed, falling back to manual generation', error)
36+
}
37+
}
38+
39+
const getRandomValues = cryptoSource?.getRandomValues?.bind(cryptoSource)
40+
if (getRandomValues && typeof Uint8Array !== 'undefined') {
41+
const bytes = getRandomValues(new Uint8Array(16))
42+
bytes[6] = bytes[6] & 0x0f | 0x40
43+
bytes[8] = bytes[8] & 0x3f | 0x80
44+
45+
const hex = Array.from(bytes, byte => byteToHex[byte]).join('')
46+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`
47+
}
48+
49+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
50+
const r = Math.random() * 16 | 0
51+
const v = c === 'x' ? r : (r & 0x3 | 0x8)
52+
return v.toString(16)
53+
})
54+
}
2055

2156
export const usePOSEventsStore = defineStore('posEvents', () => {
2257
// ========================================================================
@@ -82,7 +117,7 @@ export const usePOSEventsStore = defineStore('posEvents', () => {
82117
type: eventType,
83118
payload,
84119
timestamp: Date.now(),
85-
id: crypto.randomUUID()
120+
id: generateUUID()
86121
}
87122

88123
// Add to history

0 commit comments

Comments
 (0)