diff --git a/client/package.json b/client/package.json index 200a300..cdf50b7 100644 --- a/client/package.json +++ b/client/package.json @@ -81,7 +81,6 @@ "ts-pnp": "1.1.5", "uifx": "^2.0.7", "url-loader": "2.3.0", - "uuid": "7.0.3", "webpack": "4.41.2", "webpack-dev-server": "^3.11.2", "webpack-manifest-plugin": "2.2.0", diff --git a/client/src/lib/utils.js b/client/src/lib/utils.js index 60a1d56..146bfd7 100644 --- a/client/src/lib/utils.js +++ b/client/src/lib/utils.js @@ -102,3 +102,51 @@ export const clearInterval = (interval) => { export const now = () => (window.performance && window.performance.now ? window.performance.now.bind(window.performance) : Date.now)(); + +const uuidByteToHex = Array.from( + { length: 256 }, + (_, index) => (index + 0x100).toString(16).slice(1), +); + +export const uuid = () => { + const crypto = window.crypto || window.msCrypto; + + if (crypto && crypto.getRandomValues) { + const bytes = new Uint8Array(16); + crypto.getRandomValues(bytes); + + /* eslint-disable no-bitwise */ + bytes[6] = (bytes[6] & 0x0f) | 0x40; + bytes[8] = (bytes[8] & 0x3f) | 0x80; + /* eslint-enable no-bitwise */ + + return [ + uuidByteToHex[bytes[0]], + uuidByteToHex[bytes[1]], + uuidByteToHex[bytes[2]], + uuidByteToHex[bytes[3]], + '-', + uuidByteToHex[bytes[4]], + uuidByteToHex[bytes[5]], + '-', + uuidByteToHex[bytes[6]], + uuidByteToHex[bytes[7]], + '-', + uuidByteToHex[bytes[8]], + uuidByteToHex[bytes[9]], + '-', + uuidByteToHex[bytes[10]], + uuidByteToHex[bytes[11]], + uuidByteToHex[bytes[12]], + uuidByteToHex[bytes[13]], + uuidByteToHex[bytes[14]], + uuidByteToHex[bytes[15]], + ].join(''); + } + + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (char) => { + const random = Math.floor(Math.random() * 16); + const value = char === 'x' ? random : ((random % 4) + 8); + return value.toString(16); + }); +}; diff --git a/client/src/lib/utils.test.js b/client/src/lib/utils.test.js index 6c732c7..87c5229 100644 --- a/client/src/lib/utils.test.js +++ b/client/src/lib/utils.test.js @@ -1,4 +1,4 @@ -import { formatTime, parseTime } from './utils'; +import { formatTime, parseTime, uuid } from './utils'; test('Handles DNF input', () => { expect(formatTime(undefined)).toBe('DNF'); @@ -46,3 +46,7 @@ test('Parser handles wrong input', () => { expect(parseTime()).toBe(undefined); expect(parseTime('a')).toBe(undefined); }); + +test('Generates v4 UUIDs', () => { + expect(uuid()).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/); +}); diff --git a/client/src/store/middlewares/rooms.js b/client/src/store/middlewares/rooms.js index dc8a02a..7155296 100644 --- a/client/src/store/middlewares/rooms.js +++ b/client/src/store/middlewares/rooms.js @@ -1,9 +1,9 @@ import { push } from 'connected-react-router'; -import { v4 as uuid } from 'uuid'; import UIfx from 'uifx'; import notificationAsset from '../../assets/notification.mp3'; import * as Protocol from '../../lib/protocol'; import Namespace from '../../lib/Namespace'; +import { uuid } from '../../lib/utils'; import { DELETE_ROOM, JOIN_ROOM, diff --git a/yarn.lock b/yarn.lock index fe89a3b..e9281c2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15558,11 +15558,6 @@ utils-merge@1.0.1, utils-merge@1.x.x, utils-merge@^1.0.1: resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== -uuid@7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b" - integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg== - uuid@^11.1.1: version "11.1.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-11.1.1.tgz#f6d81d2e1c65d00762e5e29b16c5d2d995e208ad"