Fast and simple storage library for JavaScript with localStorage-like API that uses asynchronous storage (IndexedDB or WebSQL).
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Advanced functionality for defining custom storage drivers and inspecting driver capabilities. This enables extending localForage with custom storage backends and provides tools for understanding the current storage environment.
Registers a custom storage driver that implements the localForage storage interface. Custom drivers allow integration with specialized storage systems or services.
/**
* Defines a custom storage driver
* @param driver - Driver implementation object
* @param callback - Optional success callback
* @param errorCallback - Optional error callback
* @returns Promise resolving when driver is defined
*/
function defineDriver(
driver: LocalForageDriver,
callback?: () => void,
errorCallback?: (error: any) => void
): Promise<void>;Usage Examples:
import localforage from 'localforage';
// Define a simple in-memory storage driver
const memoryDriver = {
_driver: 'memoryStorageDriver',
_initStorage: function(options) {
const dbInfo = {};
dbInfo.db = {};
this._dbInfo = dbInfo;
},
_support: true,
async getItem(key) {
return this._dbInfo.db[key] || null;
},
async setItem(key, value) {
this._dbInfo.db[key] = value;
return value;
},
async removeItem(key) {
delete this._dbInfo.db[key];
},
async clear() {
this._dbInfo.db = {};
},
async length() {
return Object.keys(this._dbInfo.db).length;
},
async key(n) {
const keys = Object.keys(this._dbInfo.db);
return keys[n] || null;
},
async keys() {
return Object.keys(this._dbInfo.db);
},
async iterate(iteratee) {
const keys = Object.keys(this._dbInfo.db);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
const value = this._dbInfo.db[key];
const result = iteratee(value, key, i);
if (result !== undefined) {
return result;
}
}
}
};
// Register the custom driver
await localforage.defineDriver(memoryDriver);
// Use the custom driver
await localforage.setDriver('memoryStorageDriver');
// Define a driver with async support detection
const customAsyncDriver = {
_driver: 'customAsyncStorageDriver',
_support: async function() {
// Check if the storage backend is available
return typeof customStorageAPI !== 'undefined';
},
// ... implement other required methods
};
await localforage.defineDriver(customAsyncDriver);Returns the name of the currently active storage driver.
/**
* Gets the name of the current storage driver
* @returns The current driver name
*/
function driver(): string;Usage Examples:
import localforage from 'localforage';
// Check which driver is currently being used
const currentDriver = localforage.driver();
console.log('Current driver:', currentDriver);
// Output might be: 'asyncStorage' (IndexedDB), 'webSQLStorage', or 'localStorageWrapper'
// Conditional logic based on current driver
const driverName = localforage.driver();
if (driverName === localforage.INDEXEDDB) {
console.log('Using IndexedDB - optimal for large data');
} else if (driverName === localforage.LOCALSTORAGE) {
console.log('Using localStorage - limited storage capacity');
}
// Store driver information for debugging
const debugInfo = {
driver: localforage.driver(),
timestamp: new Date().toISOString(),
config: localforage.config()
};Retrieves the implementation object for a specific driver by name.
/**
* Gets the implementation of a specific driver
* @param driver - Name of the driver to retrieve
* @returns Promise resolving to the driver implementation
*/
function getDriver(driver: string): Promise<LocalForageDriver>;Usage Examples:
import localforage from 'localforage';
// Get IndexedDB driver implementation
const idbDriver = await localforage.getDriver(localforage.INDEXEDDB);
console.log('IndexedDB driver:', idbDriver);
// Inspect driver capabilities
const currentDriverName = localforage.driver();
const driverImpl = await localforage.getDriver(currentDriverName);
console.log('Current driver methods:', Object.keys(driverImpl));
// Check if driver supports optional methods
const driver = await localforage.getDriver(localforage.INDEXEDDB);
if (typeof driver.dropInstance === 'function') {
console.log('Driver supports dropInstance method');
}
// Get custom driver implementation
await localforage.defineDriver(myCustomDriver);
const customDriver = await localforage.getDriver('myCustomDriverName');Tests whether a specific driver is supported in the current environment.
/**
* Checks if a driver is supported in the current environment
* @param driverName - Name of the driver to check
* @returns Boolean indicating if the driver is supported
*/
function supports(driverName: string): boolean;Usage Examples:
import localforage from 'localforage';
// Check support for specific drivers
const supportsIndexedDB = localforage.supports(localforage.INDEXEDDB);
const supportsWebSQL = localforage.supports(localforage.WEBSQL);
const supportsLocalStorage = localforage.supports(localforage.LOCALSTORAGE);
console.log('Driver support:');
console.log('- IndexedDB:', supportsIndexedDB);
console.log('- WebSQL:', supportsWebSQL);
console.log('- localStorage:', supportsLocalStorage);
// Build optimal driver list based on support
const supportedDrivers = [];
if (localforage.supports(localforage.INDEXEDDB)) {
supportedDrivers.push(localforage.INDEXEDDB);
}
if (localforage.supports(localforage.WEBSQL)) {
supportedDrivers.push(localforage.WEBSQL);
}
if (localforage.supports(localforage.LOCALSTORAGE)) {
supportedDrivers.push(localforage.LOCALSTORAGE);
}
await localforage.setDriver(supportedDrivers);
// Check custom driver support
const supportsCustom = localforage.supports('myCustomDriver');
if (!supportsCustom) {
console.warn('Custom driver not supported, falling back to defaults');
}Waits for localForage to be fully initialized and ready for operations.
/**
* Waits for localForage to be ready
* @param callback - Optional callback function
* @returns Promise resolving when localForage is ready
*/
function ready(callback?: (error: any) => void): Promise<void>;Usage Examples:
import localforage from 'localforage';
// Wait for localForage to be ready before operations
await localforage.ready();
console.log('localForage is ready');
// Now safe to perform storage operations
await localforage.setItem('key', 'value');
// Using callbacks
localforage.ready((error) => {
if (error) {
console.error('localForage failed to initialize:', error);
} else {
console.log('localForage is ready');
// Perform initial storage operations
}
});
// Combine with driver setup
localforage.config({
driver: localforage.INDEXEDDB,
name: 'MyApp'
});
await localforage.ready();
console.log('Configured with driver:', localforage.driver());Retrieves the current serializer used for data conversion between JavaScript types and storage formats.
/**
* Gets the current serializer instance
* @param callback - Optional callback function
* @returns Promise resolving to the serializer object
*/
function getSerializer(callback?: (serializer: LocalForageSerializer) => void): Promise<LocalForageSerializer>;Usage Examples:
import localforage from 'localforage';
// Get the current serializer
const serializer = await localforage.getSerializer();
console.log('Serializer methods:', Object.keys(serializer));
// Use serializer directly for custom operations
const serializer = await localforage.getSerializer();
const data = { key: 'value', array: [1, 2, 3] };
serializer.serialize(data, (serializedData, error) => {
if (error) {
console.error('Serialization error:', error);
} else {
console.log('Serialized data:', serializedData);
// Deserialize back
const originalData = serializer.deserialize(serializedData);
console.log('Deserialized data:', originalData);
}
});interface LocalForageDriver {
/**
* Unique identifier for the driver
*/
_driver: string;
/**
* Initialize storage with given options
*/
_initStorage(options: LocalForageOptions): void;
/**
* Support check - boolean or async function
*/
_support?: boolean | (() => Promise<boolean>);
// Required storage methods
getItem<T>(key: string, callback?: (err: any, value: T | null) => void): Promise<T | null>;
setItem<T>(key: string, value: T, callback?: (err: any, value: T) => void): Promise<T>;
removeItem(key: string, callback?: (err: any) => void): Promise<void>;
clear(callback?: (err: any) => void): Promise<void>;
length(callback?: (err: any, numberOfKeys: number) => void): Promise<number>;
key(keyIndex: number, callback?: (err: any, key: string) => void): Promise<string>;
keys(callback?: (err: any, keys: string[]) => void): Promise<string[]>;
iterate<T, U>(
iteratee: (value: T, key: string, iterationNumber: number) => U,
callback?: (err: any, result: U) => void
): Promise<U>;
// Optional methods
dropInstance?(dbInstanceOptions?: LocalForageDbInstanceOptions, callback?: (err: any) => void): Promise<void>;
}
interface LocalForageSerializer {
/**
* Serialize a value for storage
*/
serialize<T>(value: T | ArrayBuffer | Blob, callback: (value: string, error: any) => void): void;
/**
* Deserialize a stored value
*/
deserialize<T>(value: string): T | ArrayBuffer | Blob;
/**
* Convert string to ArrayBuffer
*/
stringToBuffer(serializedString: string): ArrayBuffer;
/**
* Convert ArrayBuffer to string
*/
bufferToString(buffer: ArrayBuffer): string;
}// Template for creating a custom driver
const customDriverTemplate = {
// Required: Unique driver identifier
_driver: 'customStorageDriver',
// Required: Initialization function
_initStorage: function(options) {
// Initialize storage backend
// Store configuration in this._dbInfo
const dbInfo = {
db: null, // Your storage backend connection
name: options.name,
storeName: options.storeName
};
this._dbInfo = dbInfo;
// Perform any async initialization if needed
return new Promise((resolve, reject) => {
// Initialize your storage backend
// resolve() when ready, reject(error) on failure
resolve();
});
},
// Optional: Support detection
_support: function() {
// Return boolean or Promise<boolean>
return typeof YourStorageAPI !== 'undefined';
},
// Required: Implement all storage methods
async getItem(key, callback) {
try {
const value = await this._dbInfo.db.get(key);
if (callback) callback(null, value);
return value;
} catch (error) {
if (callback) callback(error);
throw error;
}
},
async setItem(key, value, callback) {
try {
await this._dbInfo.db.set(key, value);
if (callback) callback(null, value);
return value;
} catch (error) {
if (callback) callback(error);
throw error;
}
}
// ... implement other required methods
};// Register and use a custom driver
async function setupCustomStorage() {
// Define the driver
await localforage.defineDriver(customDriverTemplate);
// Check if it's supported
if (localforage.supports('customStorageDriver')) {
// Set as primary driver
await localforage.setDriver('customStorageDriver');
console.log('Custom driver is active');
} else {
console.warn('Custom driver not supported, using fallback');
await localforage.setDriver([
localforage.INDEXEDDB,
localforage.LOCALSTORAGE
]);
}
// Wait for initialization
await localforage.ready();
// Now ready to use
await localforage.setItem('test', 'Custom driver works!');
}
setupCustomStorage();// Driver identifiers available as constants
localforage.INDEXEDDB // 'asyncStorage'
localforage.WEBSQL // 'webSQLStorage'
localforage.LOCALSTORAGE // 'localStorageWrapper'
// Usage in driver selection
await localforage.setDriver([
localforage.INDEXEDDB, // Primary choice
localforage.WEBSQL, // Secondary fallback
localforage.LOCALSTORAGE // Final fallback
]);