import dayjs from "dayjs"; // For loading dayjs plugins, don't remove event though it is not used in this file import timezone from "dayjs/plugin/timezone"; import utc from "dayjs/plugin/utc"; import { randomBytes } from "crypto"; export const isDev = process.env.NODE_ENV === "development"; /** * Generate a decimal integer number from a string * @param str Input * @param length Default is 10 which means 0 - 9 */ export function intHash(str : string, length = 10) : number { // A simple hashing function (you can use more complex hash functions if needed) let hash = 0; for (let i = 0; i < str.length; i++) { hash += str.charCodeAt(i); } // Normalize the hash to the range [0, 10] return (hash % length + length) % length; // Ensure the result is non-negative } /** * Delays for specified number of seconds * @param ms Number of milliseconds to sleep for */ export function sleep(ms: number) { return new Promise(resolve => setTimeout(resolve, ms)); } /** * Generate a random alphanumeric string of fixed length * @param length Length of string to generate * @returns string */ export function genSecret(length = 64) { let secret = ""; const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; const charsLength = chars.length; for ( let i = 0; i < length; i++ ) { secret += chars.charAt(getCryptoRandomInt(0, charsLength - 1)); } return secret; } /** * Get a random integer suitable for use in cryptography between upper * and lower bounds. * @param min Minimum value of integer * @param max Maximum value of integer * @returns Cryptographically suitable random integer */ export function getCryptoRandomInt(min: number, max: number):number { // synchronous version of: https://github.com/joepie91/node-random-number-csprng const range = max - min; if (range >= Math.pow(2, 32)) { console.log("Warning! Range is too large."); } let tmpRange = range; let bitsNeeded = 0; let bytesNeeded = 0; let mask = 1; while (tmpRange > 0) { if (bitsNeeded % 8 === 0) { bytesNeeded += 1; } bitsNeeded += 1; mask = mask << 1 | 1; tmpRange = tmpRange >>> 1; } const randomBytes = getRandomBytes(bytesNeeded); let randomValue = 0; for (let i = 0; i < bytesNeeded; i++) { randomValue |= randomBytes[i] << 8 * i; } randomValue = randomValue & mask; if (randomValue <= range) { return min + randomValue; } else { return getCryptoRandomInt(min, max); } } /** * Returns either the NodeJS crypto.randomBytes() function or its * browser equivalent implemented via window.crypto.getRandomValues() */ const getRandomBytes = ( (typeof window !== "undefined" && window.crypto) // Browsers ? function () { return (numBytes: number) => { const randomBytes = new Uint8Array(numBytes); for (let i = 0; i < numBytes; i += 65536) { window.crypto.getRandomValues(randomBytes.subarray(i, i + Math.min(numBytes - i, 65536))); } return randomBytes; }; } // Node : function () { // eslint-disable-next-line @typescript-eslint/no-var-requires return randomBytes; } )();