Skip to main content

Strata Class API

The main class for interacting with Strata Storage.

Creating an instance

There are three ways to get a working storage instance. Most apps should use defineStorage() or the default storage singleton — both register the standard web adapters and initialize lazily on first use, so you never have to call initialize() yourself.

import { defineStorage } from 'strata-storage';

const storage = defineStorage({
defaultStorages: ['indexedDB', 'localStorage'],
});

Returns a ready-to-use Strata instance with memory, localStorage, sessionStorage, IndexedDB, cookies, and the Cache API pre-registered — the framework-agnostic, Zustand-style entry point. Create it once anywhere and import it everywhere; no Provider is required. It initializes lazily (every operation awaits readiness internally), so you can call get/set/subscribe immediately.

Default storage singleton

import { storage } from 'strata-storage';

await storage.set('key', 'value'); // works immediately

Built from the same factory as defineStorage(). Importing the package performs no I/O — initialization happens on first use. ensureInitialized() is exported if you want to force readiness before a burst of calls (it is optional and idempotent).

new Strata(config?) — manual

import { Strata } from 'strata-storage';

const storage = new Strata({ defaultStorages: ['indexedDB', 'localStorage'] });
// You register adapters yourself, then call initialize().
storage.registerAdapter(/* ... */);
await storage.initialize();

Use the constructor directly when you want full control over which adapters are registered. registerWebAdapters(strata) is exported to register the same default web set on a custom instance.

Parameters

  • config (optional): Configuration object. See StrataConfig. New 2.5.0 recovery fields (integrity, durableWrites, mirror, autoBackup) are documented in Recovery & Integrity.

Methods

initialize()

async initialize(): Promise<void>

Initializes the storage system. Must be called before any other operations.

const storage = new Strata();
await storage.initialize();

get()

async get<T = unknown>(key: string, options?: StorageOptions): Promise<T | null>

Retrieves a value from storage.

Parameters

  • key: The key to retrieve
  • options (optional): Storage options

Returns

The stored value or null if not found

Example

// Simple get
const value = await storage.get('username');

// With type
const user = await storage.get<User>('currentUser');

// With options
const data = await storage.get('data', {
storage: 'indexedDB',
skipDecryption: false
});

set()

async set<T = unknown>(
key: string,
value: T,
options?: StorageOptions
): Promise<void>

Stores a value in storage.

Parameters

  • key: The key to store under
  • value: The value to store
  • options (optional): Storage options

Example

// Simple set
await storage.set('username', 'john_doe');

// With options
await storage.set('userData', data, {
storage: 'secure',
encrypt: true,
compress: true,
ttl: 3600000, // 1 hour
tags: ['user', 'profile']
});

remove()

async remove(key: string, options?: StorageOptions): Promise<void>

Removes a value from storage.

Parameters

  • key: The key to remove
  • options (optional): Storage options

Example

await storage.remove('tempData');
await storage.remove('userData', { storage: 'secure' });

has()

async has(key: string, options?: StorageOptions): Promise<boolean>

Checks if a key exists in storage.

Parameters

  • key: The key to check
  • options (optional): Storage options

Returns

true if the key exists, false otherwise

Example

if (await storage.has('authToken')) {
// User is authenticated
}

clear()

async clear(options?: ClearOptions & StorageOptions): Promise<void>

Clears storage data.

Parameters

  • options (optional): Clear and storage options

Example

// Clear all storage
await storage.clear();

// Clear specific storage
await storage.clear({ storage: 'localStorage' });

// Clear with filters (ClearOptions: storage, namespace, prefix, pattern, tags, olderThan, expiredOnly)
await storage.clear({
prefix: 'temp_', // only keys starting with 'temp_'
olderThan: Date.now() - 86400000 // and created over 24 hours ago
});

keys()

async keys(
pattern?: string | RegExp,
options?: StorageOptions
): Promise<string[]>

Gets all keys, optionally filtered by pattern.

Parameters

  • pattern (optional): String or RegExp pattern to filter keys
  • options (optional): Storage options

Returns

Array of matching keys

Example

// Get all keys
const allKeys = await storage.keys();

// Filter by prefix
const userKeys = await storage.keys('user_');

// Filter by regex
const tempKeys = await storage.keys(/^temp_.*$/);

Synchronous API

For UI code that must read or write without await, Strata mirrors the core operations synchronously. Added in 2.5.0.

getSync<T = unknown>(key: string, options?: StorageOptions): T | null
setSync<T = unknown>(key: string, value: T, options?: StorageOptions): void
removeSync(key: string, options?: StorageOptions): void
hasSync(key: string, options?: StorageOptions): boolean
keysSync(pattern?: string | RegExp, options?: StorageOptions): string[]
clearSync(options?: ClearOptions & StorageOptions): void

These work only on synchronous adapters: memory, localStorage, sessionStorage, cookies, and url. With no explicit storage, keysSync/clearSync aggregate across the sync-capable adapters. The lookup falls back to the registry, so sync calls work even before async initialize() has completed.

storage.setSync('lastTab', 'inbox');
const tab = storage.getSync<string>('lastTab'); // 'inbox'
storage.setSync('filters', { status: 'open' }, { storage: 'localStorage', ttl: 60_000 });
storage.keysSync(); // string[] across memory/localStorage/sessionStorage/cookies/url
storage.clearSync();

Constraints

  • Targeting an async-only adapter (indexedDB, cache, sqlite, filesystem, secure, preferences) throws a StorageError — use the async API instead.
  • setSync with { encrypt: true } or { compress: true } throws: encryption and compression are inherently asynchronous. Use await storage.set(...).
  • getSync on a value that was stored encrypted or compressed throws. Read it with await storage.get(...).
  • TTL, tags, and metadata are supported by the synchronous API.

size()

async size(detailed?: boolean): Promise<SizeInfo>

Gets storage size information.

Parameters

  • detailed (optional): Include detailed breakdown

Returns

Size information object

Example

const size = await storage.size();
console.log(`Total: ${size.total} bytes, Items: ${size.count}`);

const detailed = await storage.size(true);
console.log('By storage:', detailed.byStorage);

query()

async query<T = unknown>(
condition: QueryCondition,
options?: StorageOptions & QueryOptions
): Promise<Array<{ key: string; value: T }>>

Queries storage with advanced conditions. Conditions match the decoded value using bare field names (e.g. { age: { $gte: 18 } }); wrapper fields like key, tags, created, and expires are not queryable. See the Query API for the full model and operators ($eq $ne $gt $gte $lt $lte $in $nin $regex $exists $type $and $or $not).

Parameters

  • condition: Query conditions matched against the stored value
  • options (optional): Storage options plus query options (sort, skip, limit, select)

Returns

Array of matching key-value pairs

Example

// Query by a value field
const admins = await storage.query({
role: 'admin'
});

// Range query on a value field
const adults = await storage.query({
age: { $gte: 18 }
});

// Complex query — bare value fields + logical operators
const results = await storage.query({
$and: [
{ status: 'active' },
{ score: { $gte: 10 } }
]
});

subscribe()

subscribe(
callback: SubscriptionCallback,
options?: StorageOptions
): UnsubscribeFunction

Subscribes to storage changes.

Parameters

  • callback: Function called on storage changes
  • options (optional): Storage options

Returns

Function to unsubscribe

Example

const unsubscribe = storage.subscribe((change) => {
console.log(`Key ${change.key} changed`);
console.log('Old value:', change.oldValue);
console.log('New value:', change.newValue);
});

// Later...
unsubscribe();

Which backends actually deliver

Omitting options attaches to every registered adapter that can emit change eventsmemory, localStorage, sessionStorage and url. indexedDB, cookies and cache have no native change notification and are skipped, so an unscoped subscription hears fewer backends than are registered. That is the intended outcome: an observer that hears everything able to speak.

Naming a non-observable backend explicitly logs a warning, because a subscription that can never fire is almost certainly not what you meant:

storage.subscribe(cb, { storage: 'indexedDB' });
// [strata-storage] subscribe: storage "indexedDB" does not support change events,
// so this subscription will never fire.
Before 2.9.0

The unscoped form threw NotSupportedError: Operation 'subscribe' is not supported by indexedDB adapter, because the fan-out did not skip backends that cannot subscribe — and indexedDB is registered on every default instance. Since the throw propagated out of whatever set up the subscription, it commonly took application boot down with it. Scoping to { storage: 'localStorage' } was the workaround; it still works and is tighter when only one backend matters.

export()

async export(options?: ExportOptions): Promise<string>

Exports storage data.

Parameters

  • options (optional): Export options

Returns

Exported data as string

Example

// Export all data
const backup = await storage.export();

// Export specific keys
const userData = await storage.export({
keys: ['user', 'preferences', 'settings'],
format: 'json',
pretty: true
});

import()

async import(data: string, options?: ImportOptions): Promise<void>

Imports storage data.

Parameters

  • data: Data to import
  • options (optional): Import options

Example

// Import with overwrite
await storage.import(backupData, {
format: 'json',
overwrite: true
});

// Import with merge
await storage.import(partialData, {
merge: 'shallow'
});

snapshot()

async snapshot(options?: ExportOptions): Promise<string>

Creates a portable, integrity-verified backup of all stored data. Added in 2.5.0. The returned string embeds a manifest (version, timestamp, FNV-1a checksum, and the full export including metadata) so restore() can detect a corrupted backup. Pair with config.autoBackup for scheduled snapshots.

Returns

A JSON string containing the checksum manifest and payload.

Example

const backup = await storage.snapshot();
// Persist `backup` to a file, server, or another storage type.

restore()

async restore(snapshot: string, options?: ImportOptions): Promise<void>

Restores data from a snapshot() string. Added in 2.5.0. Validates the manifest checksum and throws IntegrityError if the backup is corrupted. A plain export string (no manifest) is also accepted and imported directly. Snapshot payloads are written back with their full value wrappers intact, preserving TTL, tags, encryption flags, and checksums.

Parameters

  • snapshot: A string produced by snapshot() (or a raw export() string)
  • options (optional): Import options

Example

try {
await storage.restore(backup);
} catch (error) {
if (error instanceof IntegrityError) {
// The backup is corrupted — checksum mismatch.
}
}

See Recovery & Integrity for the full recovery toolkit (integrity, durable writes, mirroring, auto-backup).

getTTL()

async getTTL(key: string, options?: StorageOptions): Promise<number | null>

Gets time-to-live for a key.

Parameters

  • key: The key to check
  • options (optional): Storage options

Returns

Milliseconds until expiration or null if no TTL

Example

const ttl = await storage.getTTL('sessionToken');
if (ttl && ttl < 60000) {
// Token expires in less than 1 minute
await refreshToken();
}

extendTTL()

async extendTTL(
key: string,
extension: number,
options?: StorageOptions
): Promise<void>

Extends the TTL of a key.

Parameters

  • key: The key to extend
  • extension: Milliseconds to add to current TTL
  • options (optional): Storage options

Example

// Extend by 1 hour
await storage.extendTTL('session', 3600000);

persist()

async persist(key: string, options?: StorageOptions): Promise<void>

Makes a key persistent (removes TTL).

Parameters

  • key: The key to persist
  • options (optional): Storage options

Example

await storage.persist('importantData');

getExpiring()

async getExpiring(
timeWindow: number,
options?: StorageOptions
): Promise<Array<{ key: string; expiresIn: number }>>

Gets items expiring within a time window.

Parameters

  • timeWindow: Milliseconds to look ahead
  • options (optional): Storage options

Returns

Array of expiring items

Example

// Get items expiring in next hour
const expiring = await storage.getExpiring(3600000);
for (const item of expiring) {
console.log(`${item.key} expires in ${item.expiresIn}ms`);
}

cleanupExpired()

async cleanupExpired(options?: StorageOptions): Promise<number>

Manually triggers cleanup of expired items.

Parameters

  • options (optional): Storage options

Returns

Number of items removed

Example

const removed = await storage.cleanupExpired();
console.log(`Cleaned up ${removed} expired items`);

generatePassword()

generatePassword(length?: number): string

Generates a secure random password.

Parameters

  • length (optional): Password length (default: 32)

Returns

Generated password

Example

const password = storage.generatePassword(16);

hash()

async hash(data: string): Promise<string>

Hashes data using SHA-256.

Parameters

  • data: Data to hash

Returns

Hex-encoded hash

Example

const hash = await storage.hash('sensitive-data');

getAvailableStorageTypes()

getAvailableStorageTypes(): StorageType[]

Gets list of available storage types.

Returns

Array of available storage type names

Example

const types = storage.getAvailableStorageTypes();
// ['indexedDB', 'localStorage', 'sessionStorage', 'memory']

getCapabilities()

getCapabilities(storage?: StorageType): StorageCapabilities | Record<string, StorageCapabilities>

Gets capabilities of storage adapters.

Parameters

  • storage (optional): Specific storage type

Returns

Capabilities object or map of all capabilities

Example

// Get specific adapter capabilities
const indexedDBCaps = storage.getCapabilities('indexedDB');

// Get all capabilities
const allCaps = storage.getCapabilities();

close()

async close(): Promise<void>

Closes all storage connections and cleans up resources.

Example

// Clean shutdown
await storage.close();

Factory functions

These are module-level exports (not static methods on the class).

defineStorage()

function defineStorage(config?: StrataConfig): Strata

Creates a Strata instance with the standard web adapters pre-registered. The recommended entry point — see Creating an instance.

import { defineStorage } from 'strata-storage';

const storage = defineStorage({ encryption: { enabled: true, password: '…' } });

registerWebAdapters()

function registerWebAdapters(strata: Strata): Strata

Registers memory, localStorage, sessionStorage, IndexedDB, cookies, and Cache API adapters on an existing instance and returns it for chaining. Used internally by defineStorage(); call it directly to add the default web set to a new Strata(...) you configured yourself.

ensureInitialized()

function ensureInitialized(): Promise<void>

Forces initialization of the default storage singleton and awaits readiness. Optional (every operation auto-awaits readiness) and idempotent.

Events

The Strata class emits events through the subscription system:

  • set - When a value is set
  • remove - When a value is removed
  • clear - When storage is cleared
  • expire - When an item expires

Error Handling

All async methods can throw errors. See Error Classes for details.

import { StorageError, QuotaExceededError } from 'strata-storage';

try {
await storage.set('data', largeData);
} catch (error) {
if (error instanceof QuotaExceededError) {
// Handle quota exceeded
} else if (error instanceof StorageError) {
// Handle other storage errors
}
}

Next Steps