shared-memory-store
v1.0.3
Published
High-performance memory store for JavaScript objects with optional expiry
Downloads
8
Readme
Bun Shared State
A high-performance C++ native addon for Node.js/Bun that provides a shared memory store with mutable keys.
Features
- 🚀 High-performance in-memory key-value store
- 🔑 Mutable keys that update references across your application
- ⏱️ TTL support for automatic key expiration
- 🧹 Background cleanup of expired items
- 🔄 Thread-safe operations
- 🛡️ Error-resistant string conversion
Installation
npm install shared-memory-store
# or
bun add shared-memory-storeBasic Usage
const MemoryStore = require('shared-memory-store');
// Create a memory store with cleanup every 5 seconds
const store = new MemoryStore({ cleanupInterval: 5000 });
// Start the cleanup task
store.startCleanupTask();
// Regular key-value operations
store.set('user:123', { name: 'Alice', role: 'admin' });
const user = store.get('user:123');
console.log(user); // { name: 'Alice', role: 'admin' }
// Set with TTL (Time-To-Live)
store.set('session:abc', { userId: 123, token: 'xyz' }, {
isPermanent: false,
maxAgeMs: 30000 // expire after 30 seconds
});
// Check if a key exists
if (store.has('user:123')) {
console.log('User exists!');
}
// Delete a key
store.delete('user:123');
// Get all keys
const keys = store.keys();
console.log(keys); // ['session:abc', ...]
// Clear the store
store.clear();
// Get the number of items in the store
console.log(store.size()); // 0
// Stop the cleanup task before exit
store.stopCleanupTask();Advanced: Mutable Keys
One of the most powerful features is the ability to create mutable keys that can be used throughout your codebase and automatically update their string representation:
// Create a mutable key
const userConfigKey = store.createKey('user-config');
// Store data with the key
store.set(userConfigKey, { theme: 'dark' });
// Pass the key around your application
function getUserTheme(store, key) {
const config = store.get(key);
return config?.theme;
}
console.log(getUserTheme(store, userConfigKey)); // 'dark'
// Change the key everywhere it's referenced
userConfigKey.value = 'user-settings';
// The same reference now points to a different storage location
store.set(userConfigKey, { theme: 'light' });
console.log(getUserTheme(store, userConfigKey)); // 'light'Architecture and Data Flow
System Architecture
┌─────────────────┐ ┌───────────────────┐
│ │ │ │
│ JavaScript │◄──────►│ C++ Native Addon │
│ Application │ │ (MemoryStore) │
│ │ │ │
└────────┬────────┘ └───────────┬───────┘
│ │
│ │
▼ ▼
┌─────────────────┐ ┌───────────────────┐
│ │ │ │
│ Mutable Keys │◄──────►│ Memory Store │
│ (JS Proxies) │ │ (C++ HashMap) │
│ │ │ │
└─────────────────┘ └───────────────────┘Data Flow
Set Operation: When
store.set(key, value)is called:- The key is converted to a string representation
- If it's a mutable key, its current value is retrieved
- Data is stored in the C++
std::unordered_map - JavaScript references are kept alive via N-API
Get Operation: When
store.get(key)is called:- The key string is retrieved (or converted from the input)
- The C++ addon looks up the value in the hash map
- If found and not expired, the JS value is returned
Mutable Key: When a key value is changed via
key.value = newValue:- The JS Proxy intercepts the change
- It updates the target object in JavaScript
- It notifies the C++ addon about the key change
- Existing values remain accessible via the new key string
Memory Management
┌─────────────────────────────────────────────────────────┐
│ Node.js / Bun Process │
│ │
│ ┌───────────────┐ ┌────────────────────┐ │
│ │ │ │ │ │
│ │ V8 JavaScript│ │ C++ Native Memory │ │
│ │ Heap │ │ (MemoryStore) │ │
│ │ │◄────────►│ │ │
│ │ - JS Objects │ │ - Hash Tables │ │
│ │ - Proxies │ │ - References │ │
│ │ - Functions │ │ - Mutexes │ │
│ │ │ │ │ │
│ └───────────────┘ └────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘N-API Integration
The addon uses N-API (Node-API) to safely interact with the V8 engine:
Napi::ObjectWrap- Wraps C++ object with JavaScript objectNapi::Reference- Keeps JavaScript values alive for later useNapi::ObjectReference- Prevents JavaScript objects from being garbage collectedstd::mutex- Provides thread safety for operations in the C++ layer
API Reference
Constructor
new MemoryStore([options])
Creates a new memory store instance.
Parameters:
options(Object, optional)cleanupInterval(Number): Milliseconds between cleanup operations (default: 60000)
Methods
store.set(key, value, [options])
Sets a value in the store.
Parameters:
key: String, object, or mutable keyvalue: Any JavaScript valueoptions(Object, optional)isPermanent(Boolean): If false, the item can expire (default: true)maxAgeMs(Number): Time in milliseconds before the item expires (default: 0)
Returns: Boolean
store.get(key)
Gets a value from the store.
Parameters:
key: String, object, or mutable key
Returns: The stored value or undefined if not found
store.has(key)
Checks if a key exists in the store and hasn't expired.
Parameters:
key: String, object, or mutable key
Returns: Boolean
store.delete(key)
Removes a key from the store.
Parameters:
key: String, object, or mutable key
Returns: Boolean (true if key was found and deleted)
store.clear()
Removes all keys from the store.
Returns: Boolean
store.size()
Gets the number of items in the store.
Returns: Number
store.keys()
Gets all keys in the store as strings.
Returns: Array of strings
store.getKeys()
Gets all keys in the store in their original form.
Returns: Array of keys
store.createKey(initialValue)
Creates a mutable key.
Parameters:
initialValue: Initial string or object to use as the key
Returns: Proxy object with a mutable value property
store.startCleanupTask([intervalMs])
Starts the background cleanup task.
Parameters:
intervalMs(Number, optional): Override the cleanup interval
Returns: Boolean
store.stopCleanupTask()
Stops the background cleanup task.
Returns: Boolean
Performance Considerations
- The memory store uses a C++
std::unordered_mapwhich provides O(1) average case lookup - String conversions are optimized and cached when possible
- For best performance, use string keys directly rather than complex objects
- Mutable keys add flexibility but have slightly more overhead than static strings
- TTL (time-to-live) cleanup is handled in a background thread to avoid blocking the main thread
Building from Source
Requirements:
- Node.js 14+ or Bun
- C++17 compatible compiler
- node-gyp
git clone https://github.com/yourusername/bun-shared-state.git
cd bun-shared-state
npm install
npm run buildLicense
MIT
