A localStorage wrapper for all browsers without using cookies or flash, providing persistent client-side storage with automatic fallback and plugin architecture
75
Store.js provides a modular plugin system that extends the core functionality with features like data expiration, event handling, array operations, compression, and more.
Get notified when stored values change with watch/unwatch functionality.
/**
* Watch for changes to a specific key
* @param {string} key - Key to watch for changes
* @param {function} listener - Function called when key changes
* @returns {number} Subscription ID for unwatching
*/
store.watch(key, listener)
/**
* Remove an event subscription
* @param {number} subscriptionId - ID returned from watch()
*/
store.unwatch(subscriptionId)
/**
* Listen for a single change event
* @param {string} key - Key to watch for changes
* @param {function} listener - Function called once when key changes
*/
store.once(key, listener)
// Listener callback signature
type WatchCallback = (newValue: any, oldValue: any) => voidUsage Examples:
var eventsPlugin = require('store/plugins/events')
store.addPlugin(eventsPlugin)
// Watch for user changes
var subscriptionId = store.watch('user', function(newUser, oldUser) {
console.log('User changed from', oldUser, 'to', newUser)
})
store.set('user', { name: 'Alice' }) // Triggers callback
store.set('user', { name: 'Bob' }) // Triggers callback
// Stop watching
store.unwatch(subscriptionId)
// One-time listener
store.once('settings', function(newSettings, oldSettings) {
console.log('Settings changed for the first time')
})Store values with automatic expiration based on timestamps.
/**
* Set a value with expiration timestamp
* @param {string} key - Storage key
* @param {any} value - Value to store
* @param {number} expiration - Expiration timestamp (milliseconds since epoch)
* @returns {any} The stored value
*/
store.set(key, value, expiration)
/**
* Get expiration timestamp for a key
* @param {string} key - Storage key
* @returns {number|undefined} Expiration timestamp or undefined
*/
store.getExpiration(key)
/**
* Remove all expired keys from storage
*/
store.removeExpiredKeys()Usage Examples:
var expirePlugin = require('store/plugins/expire')
store.addPlugin(expirePlugin)
// Set value that expires in 1 hour
var oneHourFromNow = Date.now() + (60 * 60 * 1000)
store.set('session', { token: 'abc123' }, oneHourFromNow)
// Set value that expires in 5 minutes
var fiveMinutesFromNow = Date.now() + (5 * 60 * 1000)
store.set('temp-data', 'temporary', fiveMinutesFromNow)
// Check expiration
console.log('Session expires at:', new Date(store.getExpiration('session')))
// Clean up expired keys manually
store.removeExpiredKeys()
// Expired values return undefined when accessed
setTimeout(function() {
console.log(store.get('temp-data')) // undefined after expiration
}, 6 * 60 * 1000)Perform array and object operations directly on stored values.
// Array operations
/**
* Push values to a stored array
* @param {string} key - Array storage key
* @param {...any} values - Values to push
* @returns {number} New array length
*/
store.push(key, ...values)
/**
* Pop value from a stored array
* @param {string} key - Array storage key
* @returns {any} Popped value
*/
store.pop(key)
/**
* Shift value from beginning of stored array
* @param {string} key - Array storage key
* @returns {any} Shifted value
*/
store.shift(key)
/**
* Unshift values to beginning of stored array
* @param {string} key - Array storage key
* @param {...any} values - Values to unshift
* @returns {number} New array length
*/
store.unshift(key, ...values)
// Object operations
/**
* Assign properties to a stored object
* @param {string} key - Object storage key
* @param {...Object} objects - Objects to assign
* @returns {Object} Updated object
*/
store.assign(key, ...objects)Usage Examples:
var operationsPlugin = require('store/plugins/operations')
store.addPlugin(operationsPlugin)
// Array operations
store.set('todos', ['Buy milk', 'Walk dog'])
store.push('todos', 'Do homework', 'Call mom')
console.log(store.get('todos')) // ['Buy milk', 'Walk dog', 'Do homework', 'Call mom']
var lastTodo = store.pop('todos')
console.log(lastTodo) // 'Call mom'
var firstTodo = store.shift('todos')
console.log(firstTodo) // 'Buy milk'
store.unshift('todos', 'Wake up', 'Drink coffee')
console.log(store.get('todos')) // ['Wake up', 'Drink coffee', 'Walk dog', 'Do homework']
// Object operations
store.set('user', { name: 'Alice', age: 25 })
store.assign('user', { email: 'alice@example.com' }, { verified: true })
console.log(store.get('user'))
// { name: 'Alice', age: 25, email: 'alice@example.com', verified: true }Update stored values using transformation functions.
/**
* Update a stored value using a function
* @param {string} key - Storage key
* @param {function} updateFn - Function to transform current value
*/
store.update(key, updateFn)
/**
* Update a stored value with default if key doesn't exist
* @param {string} key - Storage key
* @param {any} defaultValue - Default value if key doesn't exist
* @param {function} updateFn - Function to transform current value
*/
store.update(key, defaultValue, updateFn)
// Update function signature
type UpdateCallback = (currentValue: any) => anyUsage Examples:
var updatePlugin = require('store/plugins/update')
store.addPlugin(updatePlugin)
// Update counter
store.set('counter', 5)
store.update('counter', function(count) {
return count + 1
})
console.log(store.get('counter')) // 6
// Update with default value
store.update('visits', 0, function(visits) {
return visits + 1
})
console.log(store.get('visits')) // 1 (started from default 0)
// Update object properties
store.set('user', { name: 'Alice', loginCount: 5 })
store.update('user', function(user) {
return {
...user,
loginCount: user.loginCount + 1,
lastLogin: new Date().toISOString()
}
})Define default values that are returned when keys don't exist.
/**
* Set default values for keys
* @param {Object} defaultValues - Object mapping keys to default values
*/
store.defaults(defaultValues)Usage Examples:
var defaultsPlugin = require('store/plugins/defaults')
store.addPlugin(defaultsPlugin)
// Set defaults
store.defaults({
theme: 'light',
language: 'en',
notifications: true,
maxItems: 10
})
// Get values (returns defaults if not set)
console.log(store.get('theme')) // 'light'
console.log(store.get('language')) // 'en'
console.log(store.get('maxItems')) // 10
// Set actual values
store.set('theme', 'dark')
console.log(store.get('theme')) // 'dark' (actual value)
console.log(store.get('language')) // 'en' (still default)Automatically compress stored data using LZ-String compression to save space.
// Compression plugin transparently compresses data on set() and decompresses on get()
// Enhanced set and get methods with compression/decompression
store.set(key, value) // Automatically compresses before storing
store.get(key) // Automatically decompresses after retrievingUsage Examples:
var compressionPlugin = require('store/plugins/compression')
store.addPlugin(compressionPlugin)
// Large data is automatically compressed using LZ-String
var largeData = {
users: Array.from({ length: 1000 }, (_, i) => ({
id: i,
name: `User ${i}`,
email: `user${i}@example.com`
}))
}
store.set('large-dataset', largeData)
// Data is compressed when stored and decompressed when retrieved
var retrieved = store.get('large-dataset')
console.log(retrieved.users.length) // 1000
// Fallback: existing uncompressed values still work
// Plugin automatically detects and handles both compressed and uncompressed dataObserve stored values and their changes with immediate callback execution and ongoing change notifications.
/**
* Observe a key for changes, immediately calling callback with current value
* @param {string} key - Key to observe
* @param {function} callback - Function called immediately and on changes
* @returns {number} Subscription ID for unobserving
*/
store.observe(key, callback)
/**
* Stop observing a key
* @param {number} subscriptionId - ID returned from observe()
*/
store.unobserve(subscriptionId)
// Callback signature (same as events plugin)
type ObserveCallback = (newValue: any, oldValue: any) => voidUsage Examples:
var observePlugin = require('store/plugins/observe')
store.addPlugin(observePlugin)
// Observe immediately gets current value, then watches for changes
var subId = store.observe('user', function(newUser, oldUser) {
console.log('User:', newUser) // Called immediately with current value
if (oldUser !== undefined) {
console.log('Changed from:', oldUser, 'to:', newUser)
}
})
store.set('user', { name: 'Alice' }) // Triggers callback
store.set('user', { name: 'Bob' }) // Triggers callback
// Stop observing
store.unobserve(subId)Utility for dumping all stored values for debugging.
/**
* Dump all stored values
* @returns {Object} Object containing all key-value pairs
*/
store.dump()Usage Examples:
var dumpPlugin = require('store/plugins/dump')
store.addPlugin(dumpPlugin)
store.set('user', { name: 'Alice' })
store.set('theme', 'dark')
store.set('count', 42)
var allData = store.dump()
console.log(allData)
// {
// user: { name: 'Alice' },
// theme: 'dark',
// count: 42
// }Provides full backwards compatibility with store.js version 1.x API, allowing legacy code to work without modification.
/**
* Check if a key exists in storage
* @param {string} key - Key to check
* @returns {boolean} True if key exists
*/
store.has(key)
/**
* Perform a transactional update on a stored value
* @param {string} key - Storage key
* @param {any} defaultValue - Default value if key doesn't exist
* @param {function} transactionFn - Function to transform current value
*/
store.transact(key, defaultValue, transactionFn)
/**
* Clear all storage (alias for clearAll)
*/
store.clear()
/**
* Iterate over all key-value pairs (v1 style)
* @param {function} fn - Function called with (key, value) for each pair
*/
store.forEach(fn)
/**
* Get all stored values as an object (alias for dump)
* @returns {Object} Object containing all key-value pairs
*/
store.getAll()
/**
* Manually serialize a value (normally done automatically)
* @param {any} value - Value to serialize
* @returns {string} Serialized value
*/
store.serialize(value)
/**
* Manually deserialize a value (normally done automatically)
* @param {string} value - Serialized value to deserialize
* @returns {any} Deserialized value
*/
store.deserialize(value)
// V1 property compatibility
store.disabled // Boolean - inverse of store.enabledUsage Examples:
var v1Plugin = require('store/plugins/v1-backcompat')
store.addPlugin(v1Plugin)
// V1 style API usage
if (store.has('user')) {
console.log('User exists')
}
// Transactional updates
store.transact('counter', 0, function(currentValue) {
return currentValue + 1
})
// V1 style iteration
store.forEach(function(key, value) {
console.log(key + ' = ' + JSON.stringify(value))
})
// Get all data
var allData = store.getAll()
console.log(allData) // { user: {...}, settings: {...} }
// Manual serialization (rarely needed)
var serialized = store.serialize({ foo: 'bar' })
var deserialized = store.deserialize(serialized)
// V1 property
if (!store.disabled) {
console.log('Storage is enabled')
}Provides JSON polyfill for legacy browsers that don't have native JSON support.
// No additional API - provides JSON.parse and JSON.stringify for old browsers
// Automatically included in legacy builds// Load specific plugins
var expirePlugin = require('store/plugins/expire')
var eventsPlugin = require('store/plugins/events')
store.addPlugin(expirePlugin)
store.addPlugin([eventsPlugin, expirePlugin]) // Multiple plugins// Load all plugins at once
var allPlugins = require('store/plugins/all')
store.addPlugin(allPlugins)
// Or use the everything build which includes all plugins
var store = require('store/dist/store.everything')Usage Examples:
// Custom store with specific plugins
var engine = require('store/src/store-engine')
var storages = require('store/storages/all')
var myPlugins = [
require('store/plugins/expire'),
require('store/plugins/events'),
require('store/plugins/operations')
]
var customStore = engine.createStore(storages, myPlugins)
// Now all selected plugin methods are available
customStore.set('data', 'value', Date.now() + 60000) // expire plugin
customStore.watch('data', function(newVal, oldVal) { // events plugin
console.log('Data changed')
})
customStore.push('items', 'new item') // operations pluginInstall with Tessl CLI
npx tessl i tessl/npm-storeevals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10