UNPKG

@febkosq8/local-save

Version:

Lightweight wrapper around IndexedDB for secure and structured client-side data storage.

202 lines (200 loc) 7.96 kB
declare class LocalSave { dbName: DBName; encryptionKey?: EncryptionKey; categories: Category[]; expiryThreshold: number; clearOnDecryptError: boolean; printLogs: boolean; constructor(config?: Config); /** * Opens a connection to the IndexedDB database. * It handles the database versioning and ensures that the required object stores are created if they do not exist. * * @internal * * @param version - The version of the database to open. Optional. * * @returns A promise that resolves to the opened 'IDBDatabase' instance. */ private openDB; /** * Retrieves an object store from the IndexedDB database. * It handles the transaction mode and ensures that the requested object store is returned. * * 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. * * @internal * * @param category - The name of the object store to retrieve. * @param mode - The mode for the transaction (default is "readonly"). * * @returns A promise that resolves to the requested object store. * * @throws {LocalSaveError} Will throw an error if the object store does not exist in the database and the category is invalid */ private getStore; /** * Retrieves the encryption key as a CryptoKey object. * * @internal * @returns A promise that resolves to a CryptoKey object. * * @throws {LocalSaveEncryptionKeyError} If the encryption key is not configured. * @throws {LocalSaveEncryptionKeyError} If the encryption key length is not 16, 24, or 32 characters. */ private getEncryptKey; /** * Encrypts the provided data using AES-GCM encryption with the help of SubtleCrypto API. * Refer to https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/encrypt for more technical details. * * Generates a random 12-byte IV for each encryption. * Base64 encodes the IV and the encrypted data and returns the result as a string. * * If no encryption key is configured, it returns the data as is. * * @internal * * @param data The data to be encrypted. Should be an instance of DBItem. * * @returns A promise that resolves to the encrypted data as a base64 encoded string. * * @throws {LocalSaveEncryptionKeyError} If the encryption key is not configured. * @throws {LocalSaveError} If the encryption process fails. */ private encryptData; /** * Decrypts the provided data using the configured encryption key. * If no encryption key is configured, it returns the data as is. * * @param encryptedBase64Data The data to decrypt, as a string. * * @returns The decrypted data as an object. * * @throws {LocalSaveEncryptionKeyError} If the encryption key is not configured. * @throws {LocalSaveError} If the decryption process fails. */ decryptData(encryptedBase64Data: string): Promise<DBItem>; /** * Stores data in the specified category with the given item key. * If encryption key is configured, the data is encrypted first before being stored. * * @param category The category under which the data should be stored. * @param itemKey The key to identify the stored data. * @param data The data to be stored. * * @returns A promise that resolves to `true` if the operation was successful. * * @throws {LocalSaveError} Will reject the promise if an error occurs during the saving process. */ set(category: Category, itemKey: string, data: unknown): Promise<true>; /** * Retrieves an item from the specified category in the IndexedDB. * If the item is not found, the promise resolves to 'null'. * If an encryption key is configured, the data is decrypted before being returned. * * @param category The category from which to retrieve the item. * @param itemKey The key of the item to retrieve. * * @returns A promise that resolves to the retrieved item or null if not found. * * @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. * @throws {LocalSaveError} Will reject the promise if an error occurs during the retrieval process. */ get(category: Category, itemKey: string): Promise<DBItem | null>; /** * Removes an entry from the specified category and the specific itemKey in the IndexedDB store. * * @param category The category from which the item should be removed. * @param itemKey The key of the item to be removed. * * @returns A promise that resolves to `true` if the operation was successful. * * @throws {LocalSaveError} Will reject the promise if an error occurs during the removal process. */ remove(category: Category, itemKey: string): Promise<true>; /** * Clears all entries in the specified category. * * @param category - The category to clear. * * @returns A promise that resolves to `true` if the operation was successful. * * @throws {LocalSaveError} Will reject the promise if an error occurs during the clearing process. */ clear(category: Category): Promise<true>; /** * Expires data older than the specified number of days. * * This method iterates through all categories and removes items that have a timestamp * older than the specified number of days from the current date. * * @param {number} [days=this.expiryThreshold] The number of days to use as the threshold for expiring data. * Defaults to expiryThreshold from config if not provided. * * @returns A promise that resolves to `true` if the operation was successful. * * @throws {LocalSaveError} - Throws an error if there is an issue accessing the store or removing items. */ expire(days?: number): Promise<true>; /** * Asynchronously destroys the database by deleting it from IndexedDB. * * @returns A promise that resolves to `true` if the operation was successful. * * @throws {LocalSaveError} Will reject the promise if an error occurs during the deletion process. */ destroy(): Promise<true>; } type DBName = string; type EncryptionKey = string; type Category = string; interface DBItem { timestamp: number; data: unknown; } type DBItemEncryptedBase64 = string; interface Config { /** * The name of the database to use for local save * * @default "LocalSave" */ dbName?: DBName; /** * The key to use for encrypting and decrypting data * Not providing this will store data in plain text * Should be a string without spaces of length 16, 24, or 32 characters * * @default undefined */ encryptionKey?: EncryptionKey; /** * The categories to use for storing data * You can use these to separate different types of data * No spaces are allowed in the key * * @default ["userData"] */ categories?: Category[]; /** * The number of days to use as the threshold for expiring data * * @default '30' days */ expiryThreshold?: number; /** * Whether to clear all data for a category if an error occurs while decrypting data * Most likely reason of error is due to an incorrect encryption key * * @default true */ clearOnDecryptError?: boolean; /** * Whether to print logs * Includes debug and errors logs * * @default false */ printLogs?: boolean; } export { type Category, type Config, type DBItem, type DBItemEncryptedBase64, type DBName, type EncryptionKey, LocalSave as default };