//#region src/storage-listener.d.ts /** * Type for storage change events */ interface StorageChange { /** The old value (undefined if the item was just created) */ oldValue?: T$1; /** The new value (undefined if the item was just deleted) */ newValue?: T$1; } /** * Callback function for storage changes */ type StorageChangeCallback = (change: StorageChange, key: string, area: StorageArea) => void; /** * Storage Listener Manager * Manages key-specific listeners for chrome.storage.onChanged events * * This class provides a higher-level abstraction over chrome.storage.onChanged * that allows you to listen to changes for specific keys instead of all changes. * * @example * ```typescript * const listener = new StorageListener(); * * // Listen to a specific key * const unsubscribe = listener.addListener('username', (change, key, area) => { * console.log(`${key} changed from ${change.oldValue} to ${change.newValue}`); * }); * * // Later, remove the listener * unsubscribe(); * ``` */ declare class StorageListener { private listeners; private chromeListener; /** * Add a listener for a specific key * * @param key - The storage key to watch * @param callback - Function to call when the key changes * @param area - Optional storage area to filter by ('local' or 'sync'). If not provided, listens to both areas. * @returns A function to remove the listener * * @example * ```typescript * const listener = new StorageListener(); * * // Listen to username changes in local storage only * const unsubscribe = listener.addListener('username', (change, key, area) => { * console.log(`Username changed to: ${change.newValue}`); * }, 'local'); * * // Remove listener when done * unsubscribe(); * ``` */ addListener(key: string, callback: StorageChangeCallback, area?: StorageArea): () => void; /** * Remove a specific listener registration */ private removeListener; /** * Initialize the underlying chrome.storage.onChanged listener */ private initializeChromeListener; /** * Clean up the chrome listener when no more listeners exist */ private cleanupChromeListener; /** * Remove all listeners and clean up */ removeAllListeners(): void; /** * Get the number of active listeners * Useful for testing and debugging */ get listenerCount(): number; } //#endregion //#region src/chrome-storage.d.ts type StorageArea = 'local' | 'sync'; interface StorageOptions { area?: StorageArea; encrypted?: boolean; } interface StorageGetResult { [key: string]: T$1; } interface EncryptionProvider { encrypt: (key: string, value: string) => Promise; decrypt: (key: string) => Promise; remove: (key: string) => Promise; has: (key: string) => Promise; } interface GenericChromeStorageOptions { /** Function to generate a prefixed key for development or namespacing */ keyTransformer?: (key: string) => string; /** * Optional encryption provider for secure storage * REQUIRED for encryption support - you must provide an encryption provider * with a key (use DefaultEncryptionProvider with a derived key) * Set to null to disable encryption support entirely * * @example * ```typescript * import { deriveKeyFromPassword } from './secure-storage'; * import { DefaultEncryptionProvider } from './default-encryption-provider'; * * const { key } = await deriveKeyFromPassword('user-password'); * const provider = new DefaultEncryptionProvider({ key }); * const manager = new ChromeStorage({ encryptionProvider: provider }); * ``` */ encryptionProvider?: EncryptionProvider | null; } /** * Generic Chrome Storage Manager * All methods throw errors on failure for clean error handling * @template TSchema Optional schema object type for type-safe keys and values * @example * ```typescript * type MyStorage = { * username: string; * settings: { theme: string }; * count: number; * }; * const storage = new ChromeStorage(); * // Now get('username') returns string | undefined * // and get('invalid') causes a TypeScript error * ``` */ declare class ChromeStorage> { private keyTransformer; private encryptionProvider?; private storageListener; constructor(options?: GenericChromeStorageOptions); /** * Get a single item from storage * @throws Error if operation fails or encryption provider not configured */ get(key: K, options?: StorageOptions): Promise; /** * Get a single item from storage and immediately remove it * Useful for one-time tokens, temporary data, or message passing * @throws Error if operation fails or encryption provider not configured */ getOnce(key: K, options?: StorageOptions): Promise; /** * Get multiple items from storage * @throws Error if operation fails */ getMultiple(keys: readonly K[], options?: StorageOptions): Promise>>; /** * Set a single item in storage * @throws Error if operation fails */ set(key: K, value: TSchema[K], options?: StorageOptions): Promise; /** * Set multiple items in storage * @throws Error if operation fails */ setMultiple(items: Partial>, options?: StorageOptions): Promise; /** * Remove items from storage * @throws Error if operation fails */ remove(keys: keyof TSchema | (keyof TSchema)[], options?: StorageOptions): Promise; /** * Clear all data from storage area * @throws Error if operation fails */ clear(options?: StorageOptions): Promise; /** * Check if a key exists in storage * @throws Error if operation fails */ has(key: keyof TSchema | string, options?: StorageOptions): Promise; /** * Get all items from storage area * @throws Error if operation fails */ getAll(options?: StorageOptions): Promise>; /** * Get storage usage information * @throws Error if operation fails */ getBytesInUse(keys?: keyof TSchema | (keyof TSchema)[], options?: StorageOptions): Promise; /** * Watch for changes to a specific storage key * Returns an unsubscribe function to stop listening * * @param key - The storage key to watch * @param callback - Function called when the key changes * @param options - Storage options (area filter) * @returns A function to remove the listener * * @example * ```typescript * // Watch for username changes * const unsubscribe = storage.watch('username', (change, key, area) => { * console.log(`${key} changed from ${change.oldValue} to ${change.newValue}`); * console.log(`Changed in ${area} storage`); * }); * * // Later, stop watching * unsubscribe(); * ``` * * @example * ```typescript * // Watch only local storage changes * const unsubscribe = storage.watch( * 'settings', * (change) => { * console.log('Settings updated:', change.newValue); * }, * { area: 'local' } * ); * ``` */ watch(key: K, callback: StorageChangeCallback, options?: Pick): () => void; } //#endregion //#region src/secure-storage.d.ts /** * Generic secure storage utilities for Chrome extension * Uses Web Crypto API for encryption and Chrome storage API for persistence * * SECURITY NOTICE: * This module requires users to provide their own encryption keys. * Keys are NEVER stored - they must be derived from user passwords or * managed by the calling application. This ensures that access to * chrome.storage alone is not sufficient to decrypt the data. * * RECOMMENDED USAGE: * 1. Use `deriveKeyFromPassword()` to create a key from user input * 2. Store the salt securely (it's not secret, but needed for key derivation) * 3. Pass the derived key to encryption/decryption functions * 4. Clear the key from memory when done * * @example * ```typescript * // Derive key from user password * const { key, salt } = await deriveKeyFromPassword('user-password'); * * // Store encrypted data * await storeEncrypted('myKey', 'secret data', key); * * // Retrieve encrypted data (requires same key) * const data = await getEncrypted('myKey', key); * ``` */ /** * Stored encrypted data format using base64 encoding for efficiency */ interface StoredEncryptedData { /** Base64-encoded encrypted data */ encryptedData: string; /** Base64-encoded initialization vector */ iv: string; } /** * Result of key derivation from password */ interface DerivedKeyResult { /** The derived CryptoKey (keep in memory, never store) */ key: CryptoKey; /** Base64-encoded salt (safe to store, needed for re-derivation) */ salt: string; } /** * Options for secure storage operations */ interface SecureStorageOptions { /** * Storage area to use ('local' or 'sync') * @default 'local' * * WARNING: 'sync' has a 100KB limit per item. Encrypted data is larger * than plaintext, so consider this when choosing storage area. */ area?: 'local' | 'sync'; } /** * Derive a cryptographic key from a password using PBKDF2 * * This is the RECOMMENDED way to create encryption keys. The derived key * should be kept in memory and never stored. Store only the salt, which * is needed to re-derive the same key from the password later. * * @param password - User's password (will be used to derive the key) * @param existingSalt - Optional base64-encoded salt for re-deriving a key * @returns Promise with the derived key and salt * * @example * ```typescript * // First time: generate new key and salt * const { key, salt } = await deriveKeyFromPassword('user-password'); * // Store salt somewhere (it's safe to store, not the key!) * * // Later: re-derive the same key using stored salt * const { key: sameKey } = await deriveKeyFromPassword('user-password', storedSalt); * ``` */ declare function deriveKeyFromPassword(password: string, existingSalt?: string): Promise; /** * Generate a random encryption key (alternative to password-based derivation) * * Use this if you want to generate a random key instead of deriving from password. * WARNING: You are responsible for securely managing this key. Consider using * deriveKeyFromPassword() instead for better security. * * @returns Promise with a CryptoKey suitable for AES-GCM encryption * * @example * ```typescript * const key = await generateEncryptionKey(); * // You must handle key storage/management yourself * ``` */ declare function generateEncryptionKey(): Promise; /** * Encrypt data using AES-GCM with a user-provided key * * @param data - The string data to encrypt * @param key - The CryptoKey to use for encryption (from deriveKeyFromPassword or generateEncryptionKey) * @returns Promise that resolves to the encrypted data with IV (both base64-encoded) * * @example * ```typescript * const { key } = await deriveKeyFromPassword('user-password'); * const encrypted = await encryptData('secret data', key); * ``` */ declare function encryptData(data: string, key: CryptoKey): Promise; /** * Decrypt data using AES-GCM with a user-provided key * * @param encryptedData - The base64-encoded encrypted data * @param iv - The base64-encoded initialization vector * @param key - The CryptoKey to use for decryption (must be the same key used for encryption) * @returns Promise that resolves to the decrypted string * @throws Error if decryption fails (wrong key or corrupted data) * * @example * ```typescript * const { key } = await deriveKeyFromPassword('user-password', storedSalt); * const decrypted = await decryptData(encrypted.encryptedData, encrypted.iv, key); * ``` */ declare function decryptData(encryptedData: string, iv: string, key: CryptoKey): Promise; /** * Store encrypted data in Chrome storage * * @param storageKey - The key to store the data under * @param data - The string data to encrypt and store * @param key - The CryptoKey to use for encryption * @param options - Options for storage (area: 'local' or 'sync') * @returns Promise that resolves when storage is complete * * @example * ```typescript * const { key } = await deriveKeyFromPassword('user-password'); * await storeEncrypted('myData', 'secret value', key); * ``` */ declare function storeEncrypted(storageKey: string, data: string, key: CryptoKey, options?: SecureStorageOptions): Promise; /** * Retrieve and decrypt data from Chrome storage * * @param storageKey - The key to retrieve the data from * @param key - The CryptoKey to use for decryption (must match the key used for encryption) * @param options - Options for retrieval (area: 'local' or 'sync') * @returns Promise that resolves to the decrypted string or null if not found * @throws Error if decryption fails (wrong key or corrupted data) * * @example * ```typescript * const { key } = await deriveKeyFromPassword('user-password', storedSalt); * const data = await getEncrypted('myData', key); * ``` */ declare function getEncrypted(storageKey: string, key: CryptoKey, options?: SecureStorageOptions): Promise; /** * Check if encrypted data exists in storage * * @param storageKey - The key to check * @param options - Options for checking (area: 'local' or 'sync') * @returns Promise that resolves to true if the key exists * * @example * ```typescript * const exists = await hasEncrypted('myData'); * if (exists) { * const data = await getEncrypted('myData', key); * } * ``` */ declare function hasEncrypted(storageKey: string, options?: SecureStorageOptions): Promise; /** * Remove encrypted data from storage * * @param storageKey - The key to remove * @param options - Options for removal (area: 'local' or 'sync') * @returns Promise that resolves when removal is complete * * @example * ```typescript * await removeEncrypted('myData'); * ``` */ declare function removeEncrypted(storageKey: string, options?: SecureStorageOptions): Promise; //#endregion //#region src/default-encryption-provider.d.ts /** * Options for configuring the DefaultEncryptionProvider */ interface DefaultEncryptionProviderOptions extends SecureStorageOptions { /** * Prefix to add to all storage keys * Useful for namespacing encrypted data */ keyPrefix?: string; /** * The encryption key to use for all operations * REQUIRED: Must be provided (typically derived from user password) * * @example * ```typescript * import { deriveKeyFromPassword } from './secure-storage'; * * const { key } = await deriveKeyFromPassword('user-password'); * const provider = new DefaultEncryptionProvider({ key }); * ``` */ key: CryptoKey; } /** * Default implementation of EncryptionProvider using secure-storage utilities * * This provider uses AES-GCM encryption with a user-provided 256-bit key. * Each encrypted value has its own initialization vector (IV). * * The encryption key is NEVER stored - it must be provided by the application * and is typically derived from a user password. * * @example * ```typescript * import { deriveKeyFromPassword } from './secure-storage'; * * // Derive key from user password * const { key, salt } = await deriveKeyFromPassword('user-password'); * // Store salt for later (it's safe to store, not the key!) * * // Create provider with the derived key * const provider = new DefaultEncryptionProvider({ key }); * await provider.encrypt('myKey', 'sensitive data'); * const data = await provider.decrypt('myKey'); * ``` * * @example With custom options * ```typescript * const { key } = await deriveKeyFromPassword('user-password', storedSalt); * const provider = new DefaultEncryptionProvider({ * key, * area: 'sync', * keyPrefix: 'app_', * }); * ``` */ declare class DefaultEncryptionProvider implements EncryptionProvider { private options; private key; constructor(options: DefaultEncryptionProviderOptions); /** * Get the storage key with optional prefix */ private getStorageKey; /** * Encrypt and store a value * * @param key - The key to store the encrypted value under * @param value - The string value to encrypt * @throws Error if encryption or storage fails */ encrypt(key: string, value: string): Promise; /** * Retrieve and decrypt a value * * @param key - The key to retrieve the encrypted value from * @returns The decrypted value, or null if not found * @throws Error if decryption fails (wrong key or corrupted data) */ decrypt(key: string): Promise; /** * Remove an encrypted value from storage * * @param key - The key to remove * @throws Error if removal fails */ remove(key: string): Promise; /** * Check if an encrypted value exists in storage * * @param key - The key to check * @returns True if the key exists, false otherwise */ has(key: string): Promise; } //#endregion export { ChromeStorage, DefaultEncryptionProvider, DefaultEncryptionProviderOptions, DerivedKeyResult, EncryptionProvider, GenericChromeStorageOptions, SecureStorageOptions, StorageArea, StorageChange, StorageChangeCallback, StorageGetResult, StorageListener, StorageOptions, StoredEncryptedData, decryptData, deriveKeyFromPassword, encryptData, generateEncryptionKey, getEncrypted, hasEncrypted, removeEncrypted, storeEncrypted };