Super-easy (and fast) persistent data structures in Node.js, modeled after HTML5 localStorage
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Methods for querying stored data, retrieving keys and values, and inspecting storage contents with filtering capabilities.
Returns an array of all stored keys, optionally filtered.
/**
* Returns an array of all stored keys, optionally filtered
* @param filter - Optional filter function to select specific items
* @returns Promise resolving to array of key strings
*/
async function keys(filter?: (datum: any) => boolean): Promise<string[]>;Usage Examples:
const storage = require('node-persist');
await storage.init();
// Store some data
await storage.setItem('user1', { name: 'Alice', active: true });
await storage.setItem('user2', { name: 'Bob', active: false });
await storage.setItem('config', { theme: 'dark' });
// Get all keys
const allKeys = await storage.keys();
console.log(allKeys); // ['user1', 'user2', 'config']
// Filter keys (filter receives full datum object with key, value, ttl)
const activeUserKeys = await storage.keys(datum =>
datum.key.startsWith('user') && datum.value.active
);
console.log(activeUserKeys); // ['user1']Returns an array of all stored values, optionally filtered.
/**
* Returns an array of all stored values, optionally filtered
* @param filter - Optional filter function to select specific items
* @returns Promise resolving to array of stored values
*/
async function values(filter?: (datum: any) => boolean): Promise<any[]>;Usage Examples:
// Get all values
const allValues = await storage.values();
console.log(allValues);
// [{ name: 'Alice', active: true }, { name: 'Bob', active: false }, { theme: 'dark' }]
// Filter values
const activeUsers = await storage.values(datum =>
datum.key.startsWith('user') && datum.value.active
);
console.log(activeUsers); // [{ name: 'Alice', active: true }]
// Filter by value properties
const darkThemeConfigs = await storage.values(datum =>
datum.value.theme === 'dark'
);Returns the count of stored items, optionally filtered.
/**
* Returns the count of stored items, optionally filtered
* @param filter - Optional filter function to select specific items
* @returns Promise resolving to number of items
*/
async function length(filter?: (datum: any) => boolean): Promise<number>;Usage Examples:
// Get total count
const totalItems = await storage.length();
console.log(totalItems); // 3
// Count filtered items
const userCount = await storage.length(datum => datum.key.startsWith('user'));
console.log(userCount); // 2
const activeUserCount = await storage.length(datum =>
datum.key.startsWith('user') && datum.value.active
);
console.log(activeUserCount); // 1Returns values for keys that match a string or regular expression pattern.
/**
* Returns values for keys matching a string or RegExp pattern
* @param match - String or RegExp to match against keys
* @returns Promise resolving to array of matching values
*/
function valuesWithKeyMatch(match: string | RegExp): Promise<any[]>;Usage Examples:
await storage.setItem('user:alice', { name: 'Alice' });
await storage.setItem('user:bob', { name: 'Bob' });
await storage.setItem('admin:charlie', { name: 'Charlie' });
await storage.setItem('config:theme', 'dark');
// String matching (substring search)
const userValues = await storage.valuesWithKeyMatch('user');
console.log(userValues); // [{ name: 'Alice' }, { name: 'Bob' }]
// RegExp matching
const colonUsers = await storage.valuesWithKeyMatch(/^user:/);
console.log(colonUsers); // [{ name: 'Alice' }, { name: 'Bob' }]
// Case-insensitive RegExp
const adminValues = await storage.valuesWithKeyMatch(/admin/i);
console.log(adminValues); // [{ name: 'Charlie' }]Asynchronously iterates over all stored key-value pairs.
/**
* Asynchronously iterates over all stored key-value pairs
* @param callback - Async function called for each item
* @returns Promise resolving when iteration completes
*/
async function forEach(callback: (datum: { key: string, value: any }) => Promise<void>): Promise<void>;Usage Examples:
// Simple iteration
await storage.forEach(async (datum) => {
console.log(`${datum.key}: ${JSON.stringify(datum.value)}`);
});
// Process each item
await storage.forEach(async (datum) => {
if (datum.key.startsWith('user:')) {
// Perform async operation on user data
await processUser(datum.value);
}
});
// Update items during iteration
await storage.forEach(async (datum) => {
if (datum.value.needsUpdate) {
await storage.setItem(datum.key, {
...datum.value,
updated: new Date().toISOString()
});
}
});Returns the complete raw data array with all datum objects containing key, value, and TTL information.
/**
* Returns all stored data as array of datum objects
* @returns Promise resolving to array of datum objects
*/
function data(): Promise<Array<{ key: string, value: any, ttl?: number }>>;
/**
* Gets the raw JSON string content of a storage file
* @param key - The key to get raw data for
* @returns Promise resolving to raw JSON string
*/
function getRawDatum(key: string): Promise<string>;Usage Examples:
// Get complete data structure
const allData = await storage.data();
console.log(allData);
// [
// { key: 'user1', value: { name: 'Alice' }, ttl: 1640995200000 },
// { key: 'config', value: { theme: 'dark' } }
// ]
// Inspect TTL information
allData.forEach(datum => {
console.log(`Key: ${datum.key}`);
if (datum.ttl) {
const expiresAt = new Date(datum.ttl);
console.log(`Expires at: ${expiresAt.toISOString()}`);
} else {
console.log('No expiration');
}
});
// Find items expiring soon
const expiringSoon = allData.filter(datum => {
if (!datum.ttl) return false;
const now = Date.now();
const timeUntilExpiry = datum.ttl - now;
return timeUntilExpiry > 0 && timeUntilExpiry < 60000; // expires within 1 minute
});Returns the raw JSON string content of a storage file for debugging or inspection purposes.
Usage Examples:
await storage.setItem('user', { name: 'Alice', age: 30 }, { ttl: 60000 });
// Get raw JSON string
const rawData = await storage.getRawDatum('user');
console.log(rawData);
// '{"key":"user","value":{"name":"Alice","age":30},"ttl":1640995200000}'
// Parse it manually if needed
const parsedData = JSON.parse(rawData);
console.log(parsedData); // { key: 'user', value: { name: 'Alice', age: 30 }, ttl: 1640995200000 }
// Non-existent key returns empty JSON object string
const missing = await storage.getRawDatum('nonexistent');
console.log(missing); // '{}'The filter functions receive the complete datum object with key, value, and ttl properties:
// Filter by multiple criteria
const complexFilter = (datum) => {
return datum.key.startsWith('user:') &&
datum.value.active === true &&
datum.value.role === 'admin';
};
const adminUsers = await storage.values(complexFilter);
const adminUserKeys = await storage.keys(complexFilter);
const adminUserCount = await storage.length(complexFilter);// Analyze storage usage
const allData = await storage.data();
const report = {
totalItems: allData.length,
itemsWithTTL: allData.filter(d => d.ttl).length,
itemsWithoutTTL: allData.filter(d => !d.ttl).length,
expiredItems: allData.filter(d => d.ttl && d.ttl < Date.now()).length,
keyPrefixes: {}
};
// Count items by key prefix
allData.forEach(datum => {
const prefix = datum.key.split(':')[0];
report.keyPrefixes[prefix] = (report.keyPrefixes[prefix] || 0) + 1;
});
console.log(report);// Process large datasets in batches
const batchSize = 100;
let processed = 0;
await storage.forEach(async (datum) => {
await processItem(datum);
processed++;
if (processed % batchSize === 0) {
console.log(`Processed ${processed} items`);
// Optional: Add delay to prevent overwhelming the system
await new Promise(resolve => setTimeout(resolve, 10));
}
});valuesWithKeyMatch() for better performancedata(), keys(), and values() load all items into memory simultaneously