@febkosq8/local-save
Version:
Lightweight wrapper around IndexedDB for secure and structured client-side data storage.
1 lines • 43.9 kB
Source Map (JSON)
{"version":3,"sources":["../src/utils/errors/LocalSaveEncryptionKeyError.ts","../src/utils/errors/LocalSaveError.ts","../src/utils/logger.ts","../src/utils/utils.ts","../src/index.ts"],"names":["LocalSaveEncryptionKeyError","message","options","LocalSaveError","Logger","args","isEncryptionKeyDefined","key","isValidEncryptionKey","arrayBufferToBase64","buffer","binary","bytes","len","i","base64ToArrayBuffer","base64","binary_string","LocalSave","config","version","resolve","reject","openRequest","db","category","mode","currVersion","store","keyBytes","data","iv","generatedKey","dataBuffer","encryptedData","ivUint8","encryptedDataUint8","concatenatedArray","base64Data","error","encryptedBase64Data","arrayBuffer","decryptedBufferData","decryptedData","itemKey","payload","putRequest","getRequest","result","deleteRequest","clearRequest","days","checkDate","keys","keysRequest","item","src_default"],"mappings":"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","file":"index.cjs","sourcesContent":["export default class LocalSaveEncryptionKeyError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'LocalSaveEncryptionKeyError';\n }\n}\n","export default class LocalSaveError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'LocalSaveError';\n }\n}\n","export default class Logger {\n constructor() {\n throw new Error('This class cannot be instantiated.');\n }\n static log(message: string, ...args: unknown[]) {\n console.log(`[LocalSave | LOG] ${message}\\n`, ...args);\n }\n static warn(message: string, ...args: unknown[]) {\n console.warn(`[LocalSave | WARN] ${message}\\n`, ...args);\n }\n static error(message: string, ...args: unknown[]) {\n console.error(`[LocalSave | ERROR] ${message}\\n`, ...args);\n }\n static info(message: string, ...args: unknown[]) {\n console.info(`[LocalSave | INFO] ${message}\\n`, ...args);\n }\n static debug(message: string, ...args: unknown[]) {\n console.debug(`[LocalSave | DEBUG] ${message}\\n`, ...args);\n }\n}\n","/**\n * Validates the encryption key.\n * This function checks if the provided key is defined and has a length.\n *\n * @param key - The encryption key to validate.\n * @returns `true` if the key is defined.\n */\nexport function isEncryptionKeyDefined(key: string | undefined | null) {\n return !!key && key != '' && key.length > 0;\n}\n\n/**\n * Validates the encryption key.\n *\n * This function checks if the provided key has a valid length.\n * The valid lengths for the encryption key are 16, 24, or 32 characters.\n *\n * @param key - The encryption key to validate.\n * @returns `true` if the key length is valid, otherwise `false`.\n */\nexport function isValidEncryptionKey(key: string) {\n return key.length > 0 && [16, 24, 32].includes(key.length);\n}\n\n/**\n * Converts an ArrayBuffer to a Base64 encoded string.\n *\n * @internal\n *\n * @param ArrayBuffer - The ArrayBuffer to convert.\n *\n * @returns The Base64 encoded string representation of the ArrayBuffer.\n */\nexport function arrayBufferToBase64(buffer: ArrayBuffer) {\n let binary = '';\n const bytes = new Uint8Array(buffer);\n const len = bytes.byteLength;\n for (let i = 0; i < len; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return window.btoa(binary);\n}\n\n/**\n * Converts a base64 encoded string to an ArrayBuffer.\n *\n * @internal\n *\n * @param base64 - The base64 encoded string to convert.\n *\n * @returns The resulting ArrayBuffer.\n */\nexport function base64ToArrayBuffer(base64: string) {\n const binary_string = window.atob(base64);\n const len = binary_string.length;\n const bytes = new Uint8Array(len);\n for (let i = 0; i < len; i++) {\n bytes[i] = binary_string.charCodeAt(i);\n }\n return bytes.buffer as ArrayBuffer;\n}\n","import LocalSaveEncryptionKeyError from 'src/utils/errors/LocalSaveEncryptionKeyError';\r\nimport LocalSaveError from 'src/utils/errors/LocalSaveError';\r\nimport Logger from 'src/utils/logger';\r\nimport {\r\n arrayBufferToBase64,\r\n base64ToArrayBuffer,\r\n isEncryptionKeyDefined,\r\n isValidEncryptionKey,\r\n} from 'src/utils/utils';\r\n\r\nclass LocalSave {\r\n dbName: DBName = 'LocalSave';\r\n encryptionKey?: EncryptionKey;\r\n categories: Category[] = ['userData'];\r\n expiryThreshold: number = 30;\r\n clearOnDecryptError: boolean = true;\r\n printLogs: boolean = false;\r\n constructor(config?: Config) {\r\n this.dbName = config?.dbName ?? this.dbName;\r\n this.encryptionKey = config?.encryptionKey;\r\n this.categories = config?.categories ?? this.categories;\r\n this.expiryThreshold = config?.expiryThreshold ?? this.expiryThreshold;\r\n this.clearOnDecryptError = config?.clearOnDecryptError ?? this.clearOnDecryptError;\r\n this.printLogs = config?.printLogs ?? this.printLogs;\r\n\r\n if (!!config?.encryptionKey && !isValidEncryptionKey(config?.encryptionKey)) {\r\n Logger.warn(`Encryption key should be of length 16, 24, or 32 characters`, {\r\n keyLength: config.encryptionKey.length,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Opens a connection to the IndexedDB database.\r\n * It handles the database versioning and ensures that the required object stores are created if they do not exist.\r\n *\r\n * @internal\r\n *\r\n * @param version - The version of the database to open. Optional.\r\n *\r\n * @returns A promise that resolves to the opened 'IDBDatabase' instance.\r\n */\r\n private openDB(version?: number) {\r\n return new Promise<IDBDatabase>((resolve, reject) => {\r\n const openRequest = indexedDB.open(this.dbName, version);\r\n openRequest.onupgradeneeded = () => {\r\n const db = openRequest.result;\r\n if (this.printLogs) {\r\n Logger.debug(`Database upgrade triggered`, {\r\n dbName: this.dbName,\r\n version: db.version,\r\n });\r\n }\r\n for (const category of this.categories) {\r\n if (!db.objectStoreNames.contains(category)) {\r\n if (this.printLogs) {\r\n Logger.debug(`Creating object store`, {\r\n category,\r\n });\r\n }\r\n db.createObjectStore(category);\r\n }\r\n }\r\n };\r\n openRequest.onsuccess = () => {\r\n if (this.printLogs) {\r\n Logger.debug(`Database opened successfully`, {\r\n dbName: this.dbName,\r\n version: openRequest.result.version,\r\n });\r\n }\r\n return resolve(openRequest.result);\r\n };\r\n openRequest.onerror = () => {\r\n if (this.printLogs) {\r\n Logger.error(`LocalSaveError opening database [dbName:${this.dbName}]`, openRequest.error);\r\n }\r\n return reject(new LocalSaveError(openRequest.error?.message ?? 'Error opening database'));\r\n };\r\n });\r\n }\r\n\r\n /**\r\n * Retrieves an object store from the IndexedDB database.\r\n * It handles the transaction mode and ensures that the requested object store is returned.\r\n *\r\n * If the object store does not exist in the database and the category is valid, it will create a new version of the database with the object store.\r\n *\r\n * @internal\r\n *\r\n * @param category - The name of the object store to retrieve.\r\n * @param mode - The mode for the transaction (default is \"readonly\").\r\n *\r\n * @returns A promise that resolves to the requested object store.\r\n *\r\n * @throws {LocalSaveError} Will throw an error if the object store does not exist in the database and the category is invalid\r\n */\r\n private async getStore(category: Category, mode: IDBTransactionMode = 'readonly') {\r\n let db = await this.openDB();\r\n if (!db.objectStoreNames.contains(category) && this.categories.includes(category)) {\r\n if (this.printLogs) {\r\n Logger.debug(\r\n `Requested object store not found in current database version.\\nTriggering database upgrade to create object store.`,\r\n {\r\n category,\r\n dbName: this.dbName,\r\n version: db.version,\r\n },\r\n );\r\n }\r\n const currVersion = db.version;\r\n db.close();\r\n db = await this.openDB(currVersion + 1);\r\n } else if (!db.objectStoreNames.contains(category)) {\r\n throw new LocalSaveError(\r\n `Requested object store not found in current database version [category:${category} / dbName:${this.dbName} / version:${db.version}].`,\r\n );\r\n }\r\n const transaction = db.transaction(category, mode);\r\n const store = transaction.objectStore(category);\r\n if (this.printLogs) {\r\n Logger.debug(`Object store retrieved from database`, {\r\n category,\r\n mode,\r\n dbName: this.dbName,\r\n version: db.version,\r\n });\r\n }\r\n return store;\r\n }\r\n\r\n /**\r\n * Retrieves the encryption key as a CryptoKey object.\r\n *\r\n * @internal\r\n * @returns A promise that resolves to a CryptoKey object.\r\n *\r\n * @throws {LocalSaveEncryptionKeyError} If the encryption key is not configured.\r\n * @throws {LocalSaveEncryptionKeyError} If the encryption key length is not 16, 24, or 32 characters.\r\n */\r\n private async getEncryptKey() {\r\n if (!isEncryptionKeyDefined(this.encryptionKey)) {\r\n throw new LocalSaveEncryptionKeyError(`Encryption key is not configured`);\r\n }\r\n if (!!this.encryptionKey && !isValidEncryptionKey(this.encryptionKey)) {\r\n throw new LocalSaveEncryptionKeyError('Encryption key should be of length 16, 24, or 32 characters');\r\n }\r\n const encoder = new TextEncoder();\r\n const keyBytes = encoder.encode(this.encryptionKey);\r\n const key = await crypto.subtle.importKey('raw', keyBytes, { name: 'AES-GCM' }, false, ['encrypt', 'decrypt']);\r\n if (this.printLogs) {\r\n Logger.debug(`Encryption key retrieved successfully`, {\r\n keyLength: this.encryptionKey?.length,\r\n keyBytesLength: keyBytes.length,\r\n });\r\n }\r\n return key;\r\n }\r\n\r\n /**\r\n * Encrypts the provided data using AES-GCM encryption with the help of SubtleCrypto API.\r\n * Refer to https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/encrypt for more technical details.\r\n *\r\n * Generates a random 12-byte IV for each encryption.\r\n * Base64 encodes the IV and the encrypted data and returns the result as a string.\r\n *\r\n * If no encryption key is configured, it returns the data as is.\r\n *\r\n * @internal\r\n *\r\n * @param data The data to be encrypted. Should be an instance of DBItem.\r\n *\r\n * @returns A promise that resolves to the encrypted data as a base64 encoded string.\r\n *\r\n * @throws {LocalSaveEncryptionKeyError} If the encryption key is not configured.\r\n * @throws {LocalSaveError} If the encryption process fails.\r\n */\r\n private async encryptData(data: DBItem) {\r\n try {\r\n if (!isEncryptionKeyDefined(this.encryptionKey)) {\r\n throw new LocalSaveEncryptionKeyError(`Encryption key is not configured`);\r\n }\r\n const iv = window.crypto.getRandomValues(new Uint8Array(12));\r\n const generatedKey = await this.getEncryptKey();\r\n const dataBuffer = new TextEncoder().encode(JSON.stringify(data));\r\n const encryptedData = await window.crypto.subtle.encrypt(\r\n {\r\n name: 'AES-GCM',\r\n iv: iv,\r\n },\r\n generatedKey,\r\n dataBuffer,\r\n );\r\n const ivUint8 = new Uint8Array(iv);\r\n const encryptedDataUint8 = new Uint8Array(encryptedData);\r\n const concatenatedArray = new Uint8Array(ivUint8.byteLength + encryptedDataUint8.byteLength);\r\n concatenatedArray.set(ivUint8, 0);\r\n concatenatedArray.set(encryptedDataUint8, ivUint8.byteLength);\r\n const base64Data = arrayBufferToBase64(concatenatedArray.buffer);\r\n if (this.printLogs) {\r\n Logger.debug(`Data encrypted successfully`, {\r\n base64DataLength: base64Data.length,\r\n });\r\n }\r\n return base64Data;\r\n } catch (error) {\r\n if (this.printLogs) {\r\n Logger.error(`Data encryption failed`, error);\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Decrypts the provided data using the configured encryption key.\r\n * If no encryption key is configured, it returns the data as is.\r\n *\r\n * @param encryptedBase64Data The data to decrypt, as a string.\r\n *\r\n * @returns The decrypted data as an object.\r\n *\r\n * @throws {LocalSaveEncryptionKeyError} If the encryption key is not configured.\r\n * @throws {LocalSaveError} If the decryption process fails.\r\n */\r\n async decryptData(encryptedBase64Data: string) {\r\n try {\r\n if (!isEncryptionKeyDefined(this.encryptionKey)) {\r\n throw new LocalSaveEncryptionKeyError(`Encryption key is not configured`);\r\n }\r\n const arrayBuffer = base64ToArrayBuffer(encryptedBase64Data);\r\n const iv = new Uint8Array(arrayBuffer, 0, 12);\r\n const generatedKey = await this.getEncryptKey();\r\n const encryptedData = new Uint8Array(arrayBuffer, 12);\r\n const decryptedBufferData = await window.crypto.subtle.decrypt(\r\n {\r\n name: 'AES-GCM',\r\n iv,\r\n },\r\n generatedKey,\r\n encryptedData,\r\n );\r\n const decryptedData = JSON.parse(new TextDecoder().decode(decryptedBufferData)) as DBItem;\r\n if (this.printLogs) {\r\n Logger.debug(`Data decrypted successfully`, {\r\n timestamp: decryptedData.timestamp,\r\n });\r\n }\r\n return decryptedData;\r\n } catch (error) {\r\n if (this.printLogs) {\r\n Logger.error(`Data decryption failed`, error);\r\n }\r\n throw new LocalSaveError(`Data decryption failed`);\r\n }\r\n }\r\n\r\n /**\r\n * Stores data in the specified category with the given item key.\r\n * If encryption key is configured, the data is encrypted first before being stored.\r\n *\r\n * @param category The category under which the data should be stored.\r\n * @param itemKey The key to identify the stored data.\r\n * @param data The data to be stored.\r\n *\r\n * @returns A promise that resolves to `true` if the operation was successful.\r\n *\r\n * @throws {LocalSaveError} Will reject the promise if an error occurs during the saving process.\r\n */\r\n async set(category: Category, itemKey: string, data: unknown) {\r\n if (this.printLogs) {\r\n Logger.debug(`set() called to store data with following props`, {\r\n category,\r\n itemKey,\r\n });\r\n }\r\n let payload: DBItem | DBItemEncryptedBase64 = {\r\n timestamp: Date.now(),\r\n data,\r\n };\r\n try {\r\n if (this.encryptionKey) {\r\n payload = await this.encryptData(payload);\r\n }\r\n const store = await this.getStore(category, 'readwrite');\r\n return new Promise<true>((resolve, reject) => {\r\n const putRequest = store.put(payload, itemKey);\r\n putRequest.onsuccess = () => {\r\n if (this.printLogs) {\r\n Logger.debug(`Data stored successfully`, {\r\n category,\r\n itemKey,\r\n });\r\n }\r\n resolve(true);\r\n };\r\n putRequest.onerror = () => {\r\n if (this.printLogs) {\r\n Logger.error(\r\n `LocalSaveError storing data [category:${category} / key:${itemKey}]`,\r\n putRequest.error,\r\n );\r\n }\r\n reject(new LocalSaveError(putRequest.error?.message ?? 'Error storing data'));\r\n };\r\n });\r\n } catch (error) {\r\n if (this.printLogs) {\r\n Logger.error(`Data storing failed`, error);\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Retrieves an item from the specified category in the IndexedDB.\r\n * If the item is not found, the promise resolves to 'null'.\r\n * If an encryption key is configured, the data is decrypted before being returned.\r\n *\r\n * @param category The category from which to retrieve the item.\r\n * @param itemKey The key of the item to retrieve.\r\n *\r\n * @returns A promise that resolves to the retrieved item or null if not found.\r\n *\r\n * @throws {LocalSaveError} Will reject the promise if an error occurs while decrypting the data. Depending on the 'clearOnDecryptError' configuration, all data for the category can be cleared.\r\n * @throws {LocalSaveError} Will reject the promise if an error occurs during the retrieval process.\r\n */\r\n async get(category: Category, itemKey: string) {\r\n if (this.printLogs) {\r\n Logger.debug(`get() called to retrieve data with following props`, {\r\n category,\r\n itemKey,\r\n });\r\n }\r\n const store = await this.getStore(category);\r\n return new Promise<DBItem | null>((resolve, reject) => {\r\n const getRequest = store.get(itemKey);\r\n getRequest.onsuccess = async () => {\r\n let result = getRequest.result as DBItemEncryptedBase64 | DBItem | null;\r\n if (!result) {\r\n if (this.printLogs) {\r\n Logger.debug(`No data was found`, {\r\n category,\r\n itemKey,\r\n });\r\n }\r\n return resolve(null);\r\n }\r\n if (typeof result === 'string') {\r\n try {\r\n result = await this.decryptData(result);\r\n } catch (error) {\r\n if (this.printLogs) {\r\n Logger.error(`Failed to get data`, error);\r\n }\r\n if (this.clearOnDecryptError) {\r\n if (this.printLogs) {\r\n Logger.error(`Triggering clear for all data for category since decryption failed`);\r\n }\r\n void this.clear(category);\r\n }\r\n return reject(\r\n new LocalSaveError(error instanceof Error ? error.message : 'Failed to decrypt data'),\r\n );\r\n }\r\n }\r\n if (this.printLogs) {\r\n Logger.debug(`Data retrieved successfully`, {\r\n category,\r\n itemKey,\r\n timestamp: result.timestamp,\r\n });\r\n }\r\n return resolve(result);\r\n };\r\n getRequest.onerror = () => {\r\n return reject(new LocalSaveError(getRequest.error?.message ?? 'Error getting data'));\r\n };\r\n });\r\n }\r\n\r\n /**\r\n * Removes an entry from the specified category and the specific itemKey in the IndexedDB store.\r\n *\r\n * @param category The category from which the item should be removed.\r\n * @param itemKey The key of the item to be removed.\r\n *\r\n * @returns A promise that resolves to `true` if the operation was successful.\r\n *\r\n * @throws {LocalSaveError} Will reject the promise if an error occurs during the removal process.\r\n */\r\n async remove(category: Category, itemKey: string) {\r\n if (this.printLogs) {\r\n Logger.debug(`remove() called to remove data with following props`, {\r\n category,\r\n itemKey,\r\n });\r\n }\r\n const store = await this.getStore(category, 'readwrite');\r\n return new Promise<true>((resolve, reject) => {\r\n const deleteRequest = store.delete(itemKey);\r\n deleteRequest.onsuccess = () => {\r\n if (this.printLogs) {\r\n Logger.debug(`Data removed successfully`, {\r\n category,\r\n itemKey,\r\n });\r\n }\r\n return resolve(true);\r\n };\r\n deleteRequest.onerror = () => {\r\n if (this.printLogs) {\r\n Logger.error(\r\n `Failed to remove data from [category:${category} / key:${itemKey}]`,\r\n deleteRequest.error,\r\n );\r\n }\r\n return reject(new LocalSaveError(deleteRequest.error?.message ?? 'Error removing data'));\r\n };\r\n });\r\n }\r\n\r\n /**\r\n * Clears all entries in the specified category.\r\n *\r\n * @param category - The category to clear.\r\n *\r\n * @returns A promise that resolves to `true` if the operation was successful.\r\n *\r\n * @throws {LocalSaveError} Will reject the promise if an error occurs during the clearing process.\r\n */\r\n async clear(category: Category) {\r\n if (this.printLogs) {\r\n Logger.debug(`clear() called to store all data under '${category}' category`);\r\n }\r\n const store = await this.getStore(category, 'readwrite');\r\n return new Promise<true>((resolve, reject) => {\r\n const clearRequest = store.clear();\r\n clearRequest.onsuccess = () => {\r\n if (this.printLogs) {\r\n Logger.debug(`Data cleared successfully`, {\r\n category,\r\n dbName: this.dbName,\r\n version: store.transaction.db.version,\r\n });\r\n }\r\n return resolve(true);\r\n };\r\n clearRequest.onerror = () => {\r\n if (this.printLogs) {\r\n Logger.error(\r\n `LocalSaveError clearing data [category:${category} / dbName:${this.dbName} / version:${store.transaction.db.version}]`,\r\n clearRequest.error,\r\n );\r\n }\r\n return reject(new LocalSaveError(clearRequest.error?.message ?? 'Error clearing data'));\r\n };\r\n });\r\n }\r\n\r\n /**\r\n * Expires data older than the specified number of days.\r\n *\r\n * This method iterates through all categories and removes items that have a timestamp\r\n * older than the specified number of days from the current date.\r\n *\r\n * @param {number} [days=this.expiryThreshold] The number of days to use as the threshold for expiring data.\r\n * Defaults to expiryThreshold from config if not provided.\r\n *\r\n * @returns A promise that resolves to `true` if the operation was successful.\r\n *\r\n * @throws {LocalSaveError} - Throws an error if there is an issue accessing the store or removing items.\r\n */\r\n async expire(days: number = this.expiryThreshold): Promise<true> {\r\n if (this.printLogs) {\r\n Logger.debug(`expire() called to expire data older than ${days} days`);\r\n }\r\n const checkDate = Date.now() - days * 86400000;\r\n for (const category of this.categories) {\r\n const store = await this.getStore(category);\r\n try {\r\n const keys = await new Promise<IDBValidKey[]>((resolve, reject) => {\r\n const keysRequest = store.getAllKeys();\r\n keysRequest.onsuccess = () => {\r\n if (this.printLogs) {\r\n Logger.debug(`Keys retrieved successfully for expiring data`, {\r\n category,\r\n keys: keysRequest.result,\r\n });\r\n }\r\n resolve(keysRequest.result);\r\n };\r\n keysRequest.onerror = () => {\r\n if (this.printLogs) {\r\n Logger.error(\r\n `LocalSaveError getting keys for expiring data [category:${category}]`,\r\n keysRequest.error,\r\n );\r\n }\r\n reject(new LocalSaveError(keysRequest.error?.message ?? 'Error getting keys'));\r\n };\r\n });\r\n for (const key of keys) {\r\n if (typeof key !== 'string') continue;\r\n const item = await this.get(category, key);\r\n if (item && item.timestamp < checkDate) {\r\n if (this.printLogs) {\r\n Logger.debug(`Removing expired data`, {\r\n category,\r\n key,\r\n timestamp: item.timestamp,\r\n });\r\n }\r\n await this.remove(category, key);\r\n }\r\n }\r\n } catch (error) {\r\n if (this.printLogs) {\r\n Logger.error(`Expiring data older than '${days}' days failed`, error);\r\n }\r\n throw error;\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n /**\r\n * Asynchronously destroys the database by deleting it from IndexedDB.\r\n *\r\n * @returns A promise that resolves to `true` if the operation was successful.\r\n *\r\n * @throws {LocalSaveError} Will reject the promise if an error occurs during the deletion process.\r\n */\r\n async destroy() {\r\n if (this.printLogs) {\r\n Logger.debug(`destroy() called to wipe all data under all categories`);\r\n }\r\n return new Promise<true>((resolve, reject) => {\r\n const deleteRequest = indexedDB.deleteDatabase(this.dbName);\r\n deleteRequest.onsuccess = () => {\r\n if (this.printLogs) {\r\n Logger.debug(`Database deleted successfully`, {\r\n dbName: this.dbName,\r\n version: deleteRequest.result,\r\n });\r\n }\r\n resolve(true);\r\n };\r\n deleteRequest.onerror = () => {\r\n if (this.printLogs) {\r\n Logger.error(`Error deleting database [dbName:${this.dbName}]`);\r\n }\r\n reject(new LocalSaveError(deleteRequest.error?.message ?? 'Error deleting database'));\r\n };\r\n });\r\n }\r\n}\r\nexport type DBName = string;\r\nexport type EncryptionKey = string;\r\nexport type Category = string;\r\nexport interface DBItem {\r\n timestamp: number;\r\n data: unknown;\r\n}\r\nexport type DBItemEncryptedBase64 = string;\r\n\r\nexport interface Config {\r\n /**\r\n * The name of the database to use for local save\r\n *\r\n * @default \"LocalSave\"\r\n */\r\n dbName?: DBName;\r\n /**\r\n * The key to use for encrypting and decrypting data\r\n * Not providing this will store data in plain text\r\n * Should be a string without spaces of length 16, 24, or 32 characters\r\n *\r\n * @default undefined\r\n */\r\n encryptionKey?: EncryptionKey;\r\n /**\r\n * The categories to use for storing data\r\n * You can use these to separate different types of data\r\n * No spaces are allowed in the key\r\n *\r\n * @default [\"userData\"]\r\n */\r\n categories?: Category[];\r\n /**\r\n * The number of days to use as the threshold for expiring data\r\n *\r\n * @default '30' days\r\n */\r\n expiryThreshold?: number;\r\n /**\r\n * Whether to clear all data for a category if an error occurs while decrypting data\r\n * Most likely reason of error is due to an incorrect encryption key\r\n *\r\n * @default true\r\n */\r\n clearOnDecryptError?: boolean;\r\n /**\r\n * Whether to print logs\r\n * Includes debug and errors logs\r\n *\r\n * @default false\r\n */\r\n printLogs?: boolean;\r\n}\r\nexport default LocalSave;\r\n"]}