houser-js-utils
Version:
A comprehensive collection of TypeScript utility functions for common development tasks including array manipulation, string processing, date handling, random number generation, validation, and much more.
1 lines • 30.6 kB
Source Map (JSON)
{"version":3,"file":"StorageUtils.mjs","sources":["../src/StorageUtils.ts"],"sourcesContent":["/**\n * @module StorageUtils\n * @description Utility functions for managing browser storage (localStorage, sessionStorage, cookies) with support for encryption, expiration, and type-safe operations. Includes methods for getting, setting, and removing values, as well as managing storage quotas and handling storage availability.\n * @example\n * ```typescript\n * import { StorageUtils } from 'houser-js-utils';\n *\n * // Set and get values from localStorage\n * StorageUtils.setLocal('user', { id: 1, name: 'John' });\n * const user = StorageUtils.getLocal<{ id: number; name: string }>('user');\n *\n * // Set and get values from sessionStorage with encryption\n * StorageUtils.setSession('token', 'secret-token', { encrypt: true });\n * const token = StorageUtils.getSession<string>('token', { decrypt: true });\n *\n * // Set and get cookies with options\n * StorageUtils.setCookie('theme', 'dark', { expires: 86400000, secure: true });\n * const theme = StorageUtils.getCookie('theme');\n *\n * // Check storage availability\n * if (StorageUtils.isStorageAvailable('localStorage')) {\n * // Use localStorage\n * }\n * ```\n */\nexport const StorageUtils = {\n /**\n * Clears all cookies.\n * @param options - Clear options\n * @param options.exclude - Cookie names to exclude from clearing\n * @param options.path - Cookie path\n * @param options.domain - Cookie domain\n * @example\n * ```typescript\n * // Clear all cookies\n * StorageUtils.clearCookies();\n *\n * // Clear cookies except 'session'\n * StorageUtils.clearCookies({ exclude: ['session'] });\n * ```\n */\n clearCookies(\n options: {\n exclude?: string[];\n path?: string;\n domain?: string;\n } = {}\n ): void {\n try {\n const { exclude = [], path = \"/\", domain } = options;\n const cookies = this.getAllCookies();\n Object.keys(cookies).forEach((name) => {\n if (!exclude.includes(name)) {\n this.removeCookie(name, { path, domain });\n }\n });\n } catch (error) {\n console.error(\"Error clearing cookies:\", error);\n }\n },\n\n /**\n * Clears all values from localStorage.\n * @param options - Clear options\n * @param options.exclude - Keys to exclude from clearing\n * @example\n * ```typescript\n * // Clear all localStorage\n * StorageUtils.clearLocal();\n *\n * // Clear localStorage except 'settings'\n * StorageUtils.clearLocal({ exclude: ['settings'] });\n * ```\n */\n clearLocal(\n options: {\n exclude?: string[];\n } = {}\n ): void {\n try {\n const { exclude = [] } = options;\n if (exclude.length === 0) {\n localStorage.clear();\n } else {\n Object.keys(localStorage).forEach((key) => {\n if (!exclude.includes(key)) {\n localStorage.removeItem(key);\n }\n });\n }\n } catch (error) {\n console.error(\"Error clearing localStorage:\", error);\n }\n },\n\n /**\n * Clears all values from sessionStorage.\n * @param options - Clear options\n * @param options.exclude - Keys to exclude from clearing\n * @example\n * ```typescript\n * // Clear all sessionStorage\n * StorageUtils.clearSession();\n *\n * // Clear sessionStorage except 'temp'\n * StorageUtils.clearSession({ exclude: ['temp'] });\n * ```\n */\n clearSession(\n options: {\n exclude?: string[];\n } = {}\n ): void {\n try {\n const { exclude = [] } = options;\n if (exclude.length === 0) {\n sessionStorage.clear();\n } else {\n Object.keys(sessionStorage).forEach((key) => {\n if (!exclude.includes(key)) {\n sessionStorage.removeItem(key);\n }\n });\n }\n } catch (error) {\n console.error(\"Error clearing sessionStorage:\", error);\n }\n },\n\n /**\n * Decrypts an encrypted string value.\n * @param value - Value to decrypt\n * @param key - Optional encryption key (defaults to a secure key)\n * @returns Promise resolving to decrypted value\n * @throws Error if decryption fails\n * @example\n * ```typescript\n * const decrypted = await StorageUtils.decrypt(encryptedValue);\n * ```\n */\n async decrypt(value: string, key?: string): Promise<string> {\n try {\n const encryptedData = JSON.parse(atob(value));\n const { iv, data } = encryptedData;\n\n const cryptoKey = await this.getCryptoKey(key);\n\n const encryptedBuffer = new Uint8Array(data.split(\",\").map(Number));\n const ivBuffer = new Uint8Array(iv.split(\",\").map(Number));\n\n const decryptedBuffer = await window.crypto.subtle.decrypt(\n {\n name: \"AES-GCM\",\n iv: ivBuffer,\n },\n cryptoKey,\n encryptedBuffer\n );\n\n return new TextDecoder().decode(decryptedBuffer);\n } catch (error) {\n console.error(\"Error decrypting value:\", error);\n throw new Error(\"Failed to decrypt value\");\n }\n },\n\n /**\n * Encrypts a string value.\n * @param value - Value to encrypt\n * @param key - Optional encryption key (defaults to a secure key)\n * @returns Promise resolving to encrypted value\n * @throws Error if encryption fails\n * @example\n * ```typescript\n * const encrypted = await StorageUtils.encrypt('sensitive-data');\n * ```\n */\n async encrypt(value: string, key?: string): Promise<string> {\n try {\n const cryptoKey = await this.getCryptoKey(key);\n const iv = window.crypto.getRandomValues(new Uint8Array(12));\n const dataBuffer = new TextEncoder().encode(value);\n\n const encryptedBuffer = await window.crypto.subtle.encrypt(\n {\n name: \"AES-GCM\",\n iv,\n },\n cryptoKey,\n dataBuffer\n );\n\n const encryptedData = {\n iv: Array.from(iv),\n data: Array.from(new Uint8Array(encryptedBuffer)),\n };\n\n return btoa(JSON.stringify(encryptedData));\n } catch (error) {\n console.error(\"Error encrypting value:\", error);\n throw new Error(\"Failed to encrypt value\");\n }\n },\n\n /**\n * Gets all cookies.\n * @param options - Cookie options\n * @param options.decrypt - Whether to decrypt the values\n * @returns Object containing all cookies\n * @example\n * ```typescript\n * // Get all cookies\n * const cookies = StorageUtils.getAllCookies();\n *\n * // Get all cookies with decryption\n * const decryptedCookies = await StorageUtils.getAllCookies({ decrypt: true });\n * ```\n */\n async getAllCookies(\n options: {\n decrypt?: boolean;\n } = {}\n ): Promise<Record<string, string>> {\n try {\n const { decrypt = false } = options;\n const cookies: Record<string, string> = {};\n const cookiePromises = document.cookie.split(\";\").map(async (cookie) => {\n const [name, value] = cookie.trim().split(\"=\");\n const decodedName = decodeURIComponent(name);\n const decodedValue = decodeURIComponent(value);\n cookies[decodedName] = decrypt\n ? await this.decrypt(decodedValue)\n : decodedValue;\n });\n await Promise.all(cookiePromises);\n return cookies;\n } catch (error) {\n console.error(\"Error getting all cookies:\", error);\n return {};\n }\n },\n\n /**\n * Gets a cookie value.\n * @param name - Cookie name\n * @param options - Cookie options\n * @param options.decrypt - Whether to decrypt the value\n * @returns Cookie value or null if not found\n * @example\n * ```typescript\n * // Get a cookie\n * const value = StorageUtils.getCookie('theme');\n *\n * // Get and decrypt a cookie\n * const decryptedValue = await StorageUtils.getCookie('token', { decrypt: true });\n * ```\n */\n async getCookie(\n name: string,\n options: {\n decrypt?: boolean;\n } = {}\n ): Promise<string | null> {\n try {\n const { decrypt = false } = options;\n const cookies = document.cookie.split(\";\");\n const cookie = cookies.find((c) => c.trim().startsWith(`${name}=`));\n\n if (!cookie) return null;\n\n const value = decodeURIComponent(cookie.split(\"=\")[1]);\n return decrypt ? await this.decrypt(value) : value;\n } catch (error) {\n console.error(\"Error getting cookie:\", error);\n return null;\n }\n },\n\n /**\n * Gets or generates a crypto key for encryption/decryption.\n * @param key - Optional encryption key\n * @returns Promise resolving to CryptoKey\n * @private\n */\n async getCryptoKey(key?: string): Promise<CryptoKey> {\n try {\n const keyMaterial = key\n ? await window.crypto.subtle.importKey(\n \"raw\",\n new TextEncoder().encode(key),\n { name: \"PBKDF2\" },\n false,\n [\"deriveBits\", \"deriveKey\"]\n )\n : await window.crypto.subtle.generateKey(\n {\n name: \"AES-GCM\",\n length: 256,\n },\n true,\n [\"encrypt\", \"decrypt\"]\n );\n\n if (key) {\n return window.crypto.subtle.deriveKey(\n {\n name: \"PBKDF2\",\n salt: new TextEncoder().encode(\"storage-salt\"),\n iterations: 100000,\n hash: \"SHA-256\",\n },\n keyMaterial,\n { name: \"AES-GCM\", length: 256 },\n false,\n [\"encrypt\", \"decrypt\"]\n );\n }\n\n return keyMaterial as CryptoKey;\n } catch (error) {\n console.error(\"Error getting crypto key:\", error);\n throw new Error(\"Failed to get encryption key\");\n }\n },\n\n /**\n * Gets a value from localStorage.\n * @template T\n * @param key - Storage key\n * @param options - Storage options\n * @param options.decrypt - Whether to decrypt the value\n * @param options.defaultValue - Default value if not found/expired\n * @returns Stored value or null if not found/expired\n * @example\n * ```typescript\n * // Get a value\n * const value = StorageUtils.getLocal<string>('name');\n *\n * // Get and decrypt a value with default\n * const decryptedValue = await StorageUtils.getLocal<string>('token', {\n * decrypt: true,\n * defaultValue: 'default-token'\n * });\n * ```\n */\n async getLocal<T>(\n key: string,\n options: {\n decrypt?: boolean;\n defaultValue?: T;\n } = {}\n ): Promise<T | null> {\n try {\n const { decrypt = false, defaultValue = null } = options;\n const item = localStorage.getItem(key);\n\n if (!item) return defaultValue;\n\n const serialized = decrypt ? await this.decrypt(item) : item;\n const data = JSON.parse(serialized);\n\n if (data.expires && Date.now() > data.expires) {\n localStorage.removeItem(key);\n return defaultValue;\n }\n\n return data.value as T;\n } catch (error) {\n console.error(\"Error getting localStorage item:\", error);\n return options.defaultValue ?? null;\n }\n },\n\n /**\n * Gets a value from sessionStorage.\n * @template T\n * @param key - Storage key\n * @param options - Storage options\n * @param options.decrypt - Whether to decrypt the value\n * @param options.defaultValue - Default value if not found/expired\n * @returns Stored value or null if not found/expired\n * @example\n * ```typescript\n * // Get a value\n * const value = StorageUtils.getSession<string>('temp');\n *\n * // Get and decrypt a value with default\n * const decryptedValue = await StorageUtils.getSession<string>('token', {\n * decrypt: true,\n * defaultValue: 'default-token'\n * });\n * ```\n */\n async getSession<T>(\n key: string,\n options: {\n decrypt?: boolean;\n defaultValue?: T;\n } = {}\n ): Promise<T | null> {\n try {\n const { decrypt = false, defaultValue = null } = options;\n const item = sessionStorage.getItem(key);\n\n if (!item) return defaultValue;\n\n const serialized = decrypt ? await this.decrypt(item) : item;\n const data = JSON.parse(serialized);\n\n if (data.expires && Date.now() > data.expires) {\n sessionStorage.removeItem(key);\n return defaultValue;\n }\n\n return data.value as T;\n } catch (error) {\n console.error(\"Error getting sessionStorage item:\", error);\n return options.defaultValue ?? null;\n }\n },\n\n /**\n * Gets the storage quota and usage.\n * @returns Promise resolving to object containing quota and usage information\n * @example\n * ```typescript\n * const quota = await StorageUtils.getStorageQuota();\n * console.log(`Usage: ${quota?.usage} / ${quota?.quota}`);\n * ```\n */\n async getStorageQuota(): Promise<{\n quota: number;\n usage: number;\n remaining: number;\n } | null> {\n try {\n if (\"storage\" in navigator && \"estimate\" in navigator.storage) {\n const { quota, usage } = await navigator.storage.estimate();\n return {\n quota: quota ?? 0,\n usage: usage ?? 0,\n remaining: (quota ?? 0) - (usage ?? 0),\n };\n }\n return null;\n } catch (error) {\n console.error(\"Error getting storage quota:\", error);\n return null;\n }\n },\n\n /**\n * Gets the size of a stored value.\n * @param value - Value to measure\n * @returns Size in bytes\n * @example\n * ```typescript\n * const size = StorageUtils.getStorageSize({ data: 'large' });\n * console.log(`Size: ${size} bytes`);\n * ```\n */\n getStorageSize(value: unknown): number {\n try {\n const serialized = JSON.stringify(value);\n return new Blob([serialized]).size;\n } catch (error) {\n console.error(\"Error getting storage size:\", error);\n return 0;\n }\n },\n\n /**\n * Gets the total size of all stored values.\n * @param type - Storage type ('localStorage' or 'sessionStorage')\n * @returns Total size in bytes\n * @example\n * ```typescript\n * const totalSize = StorageUtils.getTotalStorageSize('localStorage');\n * console.log(`Total size: ${totalSize} bytes`);\n * ```\n */\n getTotalStorageSize(type: \"localStorage\" | \"sessionStorage\"): number {\n try {\n const storage = type === \"localStorage\" ? localStorage : sessionStorage;\n let total = 0;\n for (let i = 0; i < storage.length; i++) {\n const key = storage.key(i);\n if (key) {\n const value = storage.getItem(key);\n if (value) {\n total += this.getStorageSize(value);\n }\n }\n }\n return total;\n } catch (error) {\n console.error(\"Error getting total storage size:\", error);\n return 0;\n }\n },\n\n /**\n * Checks if storage is available.\n * @param type - Storage type ('localStorage', 'sessionStorage', or 'cookie')\n * @returns True if storage is available\n * @example\n * ```typescript\n * if (StorageUtils.isStorageAvailable('localStorage')) {\n * // Use localStorage\n * }\n * ```\n */\n isStorageAvailable(\n type: \"localStorage\" | \"sessionStorage\" | \"cookie\"\n ): boolean {\n try {\n switch (type) {\n case \"localStorage\":\n localStorage.setItem(\"test\", \"test\");\n localStorage.removeItem(\"test\");\n return true;\n case \"sessionStorage\":\n sessionStorage.setItem(\"test\", \"test\");\n sessionStorage.removeItem(\"test\");\n return true;\n case \"cookie\":\n document.cookie = \"test=test\";\n document.cookie = \"test=; expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n return true;\n default:\n return false;\n }\n } catch (error) {\n return false;\n }\n },\n\n /**\n * Removes a cookie.\n * @param name - Cookie name\n * @param options - Cookie options\n * @param options.path - Cookie path\n * @param options.domain - Cookie domain\n * @example\n * ```typescript\n * StorageUtils.removeCookie('session');\n * ```\n */\n removeCookie(\n name: string,\n options: {\n path?: string;\n domain?: string;\n } = {}\n ): void {\n try {\n const { path = \"/\", domain } = options;\n this.setCookie(name, \"\", {\n expires: new Date(0),\n path,\n domain,\n });\n } catch (error) {\n console.error(\"Error removing cookie:\", error);\n }\n },\n\n /**\n * Removes a value from localStorage.\n * @param key - Storage key\n * @example\n * ```typescript\n * StorageUtils.removeLocal('user');\n * ```\n */\n removeLocal(key: string): void {\n try {\n localStorage.removeItem(key);\n } catch (error) {\n console.error(\"Error removing localStorage item:\", error);\n }\n },\n\n /**\n * Removes a value from sessionStorage.\n * @param key - Storage key\n * @example\n * ```typescript\n * StorageUtils.removeSession('temp');\n * ```\n */\n removeSession(key: string): void {\n try {\n sessionStorage.removeItem(key);\n } catch (error) {\n console.error(\"Error removing sessionStorage item:\", error);\n }\n },\n\n /**\n * Sets a cookie.\n * @param name - Cookie name\n * @param value - Cookie value\n * @param options - Cookie options\n * @param options.expires - Expiration time in milliseconds or Date\n * @param options.path - Cookie path\n * @param options.domain - Cookie domain\n * @param options.secure - Whether the cookie requires HTTPS\n * @param options.sameSite - SameSite attribute\n * @param options.encrypt - Whether to encrypt the value\n * @example\n * ```typescript\n * // Set a basic cookie\n * StorageUtils.setCookie('theme', 'dark');\n *\n * // Set a secure cookie with expiration\n * StorageUtils.setCookie('token', 'secret', {\n * expires: 86400000,\n * secure: true,\n * sameSite: 'Strict'\n * });\n * ```\n */\n async setCookie(\n name: string,\n value: string,\n options: {\n expires?: number | Date;\n path?: string;\n domain?: string;\n secure?: boolean;\n sameSite?: \"Strict\" | \"Lax\" | \"None\";\n encrypt?: boolean;\n } = {}\n ): Promise<void> {\n try {\n const {\n expires,\n path = \"/\",\n domain,\n secure = false,\n sameSite = \"Lax\",\n encrypt = false,\n } = options;\n\n const finalValue = encrypt ? await this.encrypt(value) : value;\n let cookie = `${encodeURIComponent(name)}=${encodeURIComponent(\n finalValue\n )}`;\n\n if (expires) {\n const date =\n expires instanceof Date ? expires : new Date(Date.now() + expires);\n cookie += `; expires=${date.toUTCString()}`;\n }\n\n if (path) cookie += `; path=${path}`;\n if (domain) cookie += `; domain=${domain}`;\n if (secure) cookie += \"; secure\";\n if (sameSite) cookie += `; samesite=${sameSite}`;\n\n document.cookie = cookie;\n } catch (error) {\n console.error(\"Error setting cookie:\", error);\n }\n },\n\n /**\n * Sets a value in localStorage.\n * @param key - Storage key\n * @param value - Value to store\n * @param options - Storage options\n * @param options.expires - Expiration time in milliseconds\n * @param options.encrypt - Whether to encrypt the value\n * @example\n * ```typescript\n * // Set a basic value\n * StorageUtils.setLocal('user', { id: 1, name: 'John' });\n *\n * // Set an encrypted value with expiration\n * StorageUtils.setLocal('token', 'secret', {\n * expires: 3600000,\n * encrypt: true\n * });\n * ```\n */\n async setLocal(\n key: string,\n value: unknown,\n options: {\n expires?: number;\n encrypt?: boolean;\n } = {}\n ): Promise<void> {\n try {\n const { expires, encrypt = false } = options;\n const data = {\n value,\n timestamp: Date.now(),\n expires: expires ? Date.now() + expires : undefined,\n };\n\n const serialized = JSON.stringify(data);\n const finalValue = encrypt ? await this.encrypt(serialized) : serialized;\n localStorage.setItem(key, finalValue);\n } catch (error) {\n console.error(\"Error setting localStorage item:\", error);\n }\n },\n\n /**\n * Sets a value in sessionStorage.\n * @param key - Storage key\n * @param value - Value to store\n * @param options - Storage options\n * @param options.expires - Expiration time in milliseconds\n * @param options.encrypt - Whether to encrypt the value\n * @example\n * ```typescript\n * // Set a basic value\n * StorageUtils.setSession('temp', { id: 1 });\n *\n * // Set an encrypted value with expiration\n * StorageUtils.setSession('token', 'secret', {\n * expires: 3600000,\n * encrypt: true\n * });\n * ```\n */\n async setSession(\n key: string,\n value: unknown,\n options: {\n expires?: number;\n encrypt?: boolean;\n } = {}\n ): Promise<void> {\n try {\n const { expires, encrypt = false } = options;\n const data = {\n value,\n timestamp: Date.now(),\n expires: expires ? Date.now() + expires : undefined,\n };\n\n const serialized = JSON.stringify(data);\n const finalValue = encrypt ? await this.encrypt(serialized) : serialized;\n sessionStorage.setItem(key, finalValue);\n } catch (error) {\n console.error(\"Error setting sessionStorage item:\", error);\n }\n },\n};\n"],"names":[],"mappings":"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"}