Registry
Named stores with an automatic key prefix per name, and one call to close everything.
createStoreRegistry() holds multiple named stores, each safely isolated even when two of them share the same Redis database.
import { createStoreRegistry } from '@codexa/core/store';
const stores = createStoreRegistry();
const sessions = await stores.register('auth:sessions', {
mode: 'redis',
redisClient: redis.getClient(),
});
const metadata = await stores.register('auth:metadata', {
mode: 'kv',
kvPath: './data/auth.db',
});
await stores.closeAll();Automatic key prefixing
A registered store's keys are prefixed with <name>: unless you pass your own keyPrefix. Two stores registered as auth:sessions and auth:metadata on the same Redis database never collide, and flushdb() on one only clears that store's own keys, not the whole database.
const sessions = await stores.register('auth:sessions', { mode: 'redis', redisClient });
await sessions.set('u1', data);
// stored under the real key "auth:sessions:u1"createStore() called directly, outside a registry, has no prefix by default. Opt into the same protection yourself with keyPrefix when a store is not going through a registry but still shares a Redis database with something else.
await createStore({ mode: 'redis', redisClient, keyPrefix: 'billing:' });Reading the registry back
stores.has('auth:sessions'); // boolean
stores.names(); // readonly string[]
stores.get('auth:sessions'); // throws if not registeredRegistering the same name twice throws, register does not silently return the existing instance.
Closing
await stores.close('auth:sessions'); // one store, returns false if it was not registered
await stores.closeAll(); // every store in the registry, in parallelcloseAll is the pattern to reach for in a single app.onShutdown hook, instead of manually closing every store your app created one at a time.
app.onShutdown(() => stores.closeAll());