CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-store

A localStorage wrapper for all browsers without using cookies or flash, providing persistent client-side storage with automatic fallback and plugin architecture

75

0.96x
Overview
Eval results
Files

plugins.mddocs/

Plugin Extensions

Store.js provides a modular plugin system that extends the core functionality with features like data expiration, event handling, array operations, compression, and more.

Capabilities

Events Plugin

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) => void

Usage 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')
})

Expiration Plugin

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)

Operations Plugin

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 Plugin

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) => any

Usage 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()
    }
})

Defaults Plugin

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)

Compression Plugin

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 retrieving

Usage 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 data

Observe Plugin

Observe 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) => void

Usage 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)

Dump Plugin

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
// }

V1 Backcompat Plugin

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.enabled

Usage 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')
}

JSON2 Plugin

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

Plugin Loading

Loading Individual Plugins

// Load specific plugins
var expirePlugin = require('store/plugins/expire')
var eventsPlugin = require('store/plugins/events')

store.addPlugin(expirePlugin)
store.addPlugin([eventsPlugin, expirePlugin]) // Multiple plugins

Loading All 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 plugin

Install with Tessl CLI

npx tessl i tessl/npm-store

docs

core-api.md

index.md

plugins.md

storage-config.md

tile.json