npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

strata-storage

v3.1.4

Published

One storage API across web, iOS and Android — zero runtime dependencies.

Downloads

412

Readme

npm version downloads license types bundle size node

Docs · npm · GitHub · Changelog · AI Guide · Support

[!IMPORTANT] In a Capacitor app, run npx cap sync after installing. Without it the native module is never copied into your iOS/Android projects and the native adapters — secure, sqlite, preferences, filesystem — fail silently on device while working fine in the browser.

Strata Storage gives you one get/set/remove/query/subscribe API over every storage backend a cross-platform app touches: localStorage, sessionStorage, IndexedDB, cookies, the Cache API, the page URL, and — through Capacitor — the iOS Keychain, Android EncryptedSharedPreferences, native SQLite and the filesystem. The core is pure TypeScript with no runtime dependencies; React, Vue, Angular, Capacitor and Firebase are optional peers you install only if you use them. Encryption, compression, TTL, cross-tab sync, integrity checksums and mirrored backups are opt-in per call or per instance.

| | | |---|---| | Version | 3.1.4 | | License | MIT | | Node | >=24.13.0 | | Platforms | Web · iOS · Android (via Capacitor) | | Module format | ESM only — no CommonJS build | | Install size | About 177 kB packed · 723 kB unpacked, including 134 kB of iOS + Android native source (3.1.4 tarball) | | Types | Bundled .d.ts for every entry point | | Status | Stable · actively maintained |

🧭 Table of Contents #

💡 Why strata-storage #

Every cross-platform product re-solves the same problem: pick a storage backend per platform, learn each one's quirks, wrap it for your framework, then bolt on encryption, expiry and cross-tab sync by hand. The result is a per-platform layer nobody wants to own. Strata Storage replaces it with one adapter-based API that behaves identically everywhere, and keeps the runtime package dependency-free so it adds nothing to your dependency tree.

| | strata-storage | Rolling your own per platform | |---|---|---| | Backends | 11 adapters behind one API | one integration per backend, written twice | | Runtime dependencies | none | whatever each wrapper pulls in | | Framework binding | optional sub-path imports, no provider required | hand-written hooks per framework | | Encryption · TTL · sync · queries | opt-in flags | built and maintained by you | | Native iOS/Android | ships as a Capacitor plugin | a separate native module to maintain | | Automated test suite | none — typecheck, lint and build are the gates | yours to write |

Not the right tool when — you only need localStorage in one web app (use it directly); you need a CommonJS build or Node below 24.13 (this package is ESM-only); you need a server-side or multi-user database (this is client-side key-value storage); or you need cryptographic tamper-proofing from the integrity feature specifically — its checksums are non-cryptographic, so use the encryption feature instead.

✨ Features #

  • One API, every backend — the same calls whether the value lives in localStorage, IndexedDB, the URL or the iOS Keychain.
  • Zero runtime dependencies — the core is pure TypeScript; every framework and platform binding is an optional peer.
  • Provider-free by default — create one instance and import it anywhere. No React context, Vue plugin or Angular module is required, though all three styles are still supported.
  • Synchronous API alongside the async one — for initial render and event handlers, on the backends that are genuinely synchronous.
  • Opt-in encryption and compression — AES-GCM via Web Crypto, size-thresholded compression, both off by default.
  • TTL and expiry — absolute or sliding, with expiry inspection and a cleanup sweep.
  • Queries and tags — MongoDB-style conditions over stored values and their tags.
  • Cross-tab synchronisation — subscribe to changes made in other tabs of the same origin.
  • Recovery features — integrity checksums, durable writes, mirrored read-repair, portable snapshots and scheduled backups.
  • Native adapters with no plugin dependencies — SQLite is hand-rolled and the filesystem adapter uses the platform's own FileManager / java.io.File.
  • Typed end to end — bundled declarations for every entry point, including each framework sub-path.

📱 Platform Support #

| Platform | Supported | Notes | |---|---|---| | Browsers | ✅ | All seven web adapters: memory, localStorage, sessionStorage, indexedDB, cookies, cache, url. | | iOS | ✅ | Via Capacitor. Requires npx cap sync. Keychain, UserDefaults, SQLite, FileManager. | | Android | ✅ | Via Capacitor. Requires npx cap sync. EncryptedSharedPreferences, SharedPreferences, SQLite, java.io.File. | | Node / SSR | ⚠️ | Imports and runs, but only the memory adapter is available — there is no DOM storage. Browser-only adapters report isAvailable() === false instead of throwing. | | Firebase | ✅ | Optional cloud sync through the strata-storage/firebase sub-path. |

📋 Requirements #

| Requirement | Version | Why | |---|---|---| | Node | >=24.13.0 | Matches .nvmrc; the package is ESM-only and relies on modern Node resolution. | | TypeScript | moduleResolution: "bundler" or "nodenext" | Older node/node10 resolution cannot see the typed sub-path exports. | | @capacitor/core | >=8.0.0 | Optional peer — only for the native iOS/Android adapters. | | react | >=19.2.3 | Optional peer — only for strata-storage/react. | | vue | >=3.5.26 | Optional peer — only for strata-storage/vue. | | @angular/core, @angular/forms | >=21.0.6 | Optional peers — only for strata-storage/angular. | | firebase | >=10.0.0 | Optional peer — only for strata-storage/firebase. |

📦 Installation #

yarn add strata-storage

Nothing else is needed for web use. Install only the optional peer you actually import:

yarn add react                          # for strata-storage/react
yarn add vue                            # for strata-storage/vue
yarn add @angular/core @angular/forms   # for strata-storage/angular
yarn add @capacitor/core                # for strata-storage/capacitor
yarn add firebase                       # for strata-storage/firebase

Capacitor apps must then sync the native module, or the native adapters will not work on device:

npx cap sync

An optional interactive wizard can scaffold a configuration file for you — see Command Line.

🚀 Quick Start #

The default storage instance registers the standard web adapters and initialises lazily on first use, so importing the package performs no I/O.

import { storage } from 'strata-storage';

await storage.set('user', { id: 123, name: 'Ada Lovelace' });
const user = await storage.get<{ id: number; name: string }>('user');

await storage.remove('user');

🛠️ Usage #

Your own configured instance

defineStorage() is the same factory the default instance is built from. Create one at module scope and import it anywhere — no provider needed.

import { defineStorage } from 'strata-storage';

export const storage = defineStorage({
  defaultStorages: ['indexedDB', 'localStorage'],
  encryption: { enabled: true, password: process.env.STORAGE_KEY! },
});

await storage.set('token', '…', { encrypt: true });

It registers memory, localStorage, sessionStorage, indexedDB, cookies and cache. Register the URL adapter and the native adapters yourself when you need them.

React

Bind the hooks to an instance once, then use them in any component.

// storage.ts
import { defineStorage } from 'strata-storage';
import { createStrataHooks } from 'strata-storage/react';

export const storage = defineStorage();
export const { useStorage, useStorageQuery, useStorageTTL } = createStrataHooks(storage);
// Settings.tsx
import { useStorage } from './storage';

function Settings() {
  const [theme, setTheme, loading] = useStorage<string>('theme', 'light');
  if (loading) return <p>Loading…</p>;
  return (
    <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>Theme: {theme}</button>
  );
}

<StrataProvider instance={storage}> still works if you prefer context.

Vue

import { defineStorage } from 'strata-storage';
import { createStrataComposables } from 'strata-storage/vue';

export const storage = defineStorage();
export const { useStorage, useStorageQuery, useStorageTTL } = createStrataComposables(storage);

The classic StrataPlugin remains available, and each built-in composable also accepts an instance as its last argument.

Angular

import { bootstrapApplication } from '@angular/platform-browser';
import { defineStorage } from 'strata-storage';
import { provideStrata } from 'strata-storage/angular';
import { AppComponent } from './app/app.component';

bootstrapApplication(AppComponent, { providers: [provideStrata(defineStorage())] });

StrataService is then injectable and returns RxJS Observables. StrataModule.forRoot(config) remains for NgModule applications.

Native adapters (iOS and Android)

import { defineStorage } from 'strata-storage';
import { registerCapacitorAdapters } from 'strata-storage/capacitor';

const storage = defineStorage();
await registerCapacitorAdapters(storage);

await storage.set('token', value, { storage: 'secure' }); // Keychain / EncryptedSharedPreferences

PreferencesAdapter, SecureAdapter, SqliteAdapter and FilesystemAdapter are also exported individually when you need per-adapter configuration. Each SqliteAdapter binds to one (database, table) pair, so separate logical stores map to separate physical files and cannot collide.

The synchronous API

storage.setSync('lastTab', 'inbox');
const tab = storage.getSync<string>('lastTab');
storage.removeSync('lastTab');

Available on memory, localStorage, sessionStorage, cookies and url only, and it cannot encrypt or compress — see Limitations.

The URL adapter

Persists small UI state in the page URL so it survives reloads and shareable links, and emits change events on popstate/hashchange.

import { defineStorage, URLAdapter } from 'strata-storage';

const storage = defineStorage();
storage.registerAdapter(new URLAdapter());

storage.setSync('tab', 'pending', { storage: 'url' });
const tab = storage.getSync<string>('tab', { storage: 'url' });

⚙️ Configuration #

Passed to defineStorage(config) or new Strata(config):

| Option | Type | Default | What it does | |---|---|---|---| | defaultStorages | StorageType[] | ['localStorage', 'indexedDB', 'sessionStorage', 'memory'] | Preference order for picking the default adapter, and the fallback order when one is unusable. 🔴 Not a registration list — operations with no explicit storage (keys, clear, size, subscribe) span every registered adapter. To leave one out entirely use adapters: { <name>: false }. | | keyPrefix | string \| false | 'strata:' | Key prefix for localStorage/sessionStorage. false restores pre-3.0 unprefixed keys — take it when anything outside this library reads a physical key directly. | | migrateLegacyKeys | boolean | true | Adopt pre-3.0 unprefixed entries on read: never a bulk sweep, never a non-envelope, never overwriting an existing prefixed value. | | adapters | object | {} | Per-adapter settings, or false to leave that adapter unregistered entirely. localStorage/sessionStorage take { prefix }; indexedDB takes { dbName, version }; cookies takes { secure, sameSite }; cache takes { cacheName }. Settings apply immediately, so they hold for setSync/getSync issued before initialize() resolves. | | encryption | { enabled, password } | disabled | AES-GCM encryption on every write. Async path only. | | compression | { enabled, threshold } | disabled | Compress values above threshold bytes. Async path only. | | sync | { enabled } | disabled | Cross-tab change notifications. | | integrity | boolean | false | Store an FNV-1a checksum with each value and verify it on read. | | durableWrites | boolean | false | Read each write back and retry on mismatch. Costs one extra read per write. | | mirror | StorageType[] | [] | Copy every write to backup storages, and read-repair the primary from them. | | autoBackup | { interval, storage } | disabled | Take periodic snapshots into a durable adapter. | | debug | boolean | false | Raise the internal log level from warn to debug. |

The URLAdapter takes its own options: mode ('query' | 'hash', default 'query'), prefix (default 'strata.'), history ('push' | 'replace', default 'replace') and maxLength (default 2000).

Full reference: Configuration.

🔧 API Reference #

An index of the main surface. Full signatures and behaviour live on the docs site.

| Export | Signature | Docs | |---|---|---| | storage | the default Strata instance | → | | defineStorage | (config?: StrataConfig) => Strata | → | | Strata | new (config?: StrataConfig) | → | | .get / .set | get<T>(key, opts?) => Promise<T \| null> · set<T>(key, value, opts?) => Promise<void> | → | | .remove / .clear / .has / .keys | (key?, opts?) => Promise<…> | → | | .getSync / .setSync / .removeSync / .hasSync / .keysSync / .clearSync | synchronous equivalents, sync-capable adapters only | → | | .query | (condition, opts?) => Promise<Array<{ key, value }>> | → | | .subscribe | (cb, opts?) => UnsubscribeFunction | → | | .getTTL / .extendTTL / .persist / .getExpiring / .cleanupExpired | TTL inspection and maintenance | → | | .snapshot / .restore / .export / .import | portable backup and transfer | → | | .size / .getCapabilities / .getAvailableStorageTypes | introspection | → | | .registerAdapter / .refreshAdapters / .close | lifecycle | → | | computeChecksum / verifyChecksum | (data) => string · (data, sum) => boolean | → | | URLAdapter and the six web adapters | new (config?) | → | | registerCapacitorAdapters | (strata) => Promise<void> — strata-storage/capacitor | → | | enableFirebaseSync | (strata, config) => Promise<void> — strata-storage/firebase | → | | Error classes | StrataError, StorageError, IntegrityError, QuotaExceededError, EncryptionError, CompressionError, SerializationError, ValidationError, NotSupportedError, AdapterNotAvailableError | → |

🧩 Types #

The types a consumer touches directly. Full definitions: Types.

type StorageType =
  | 'memory' | 'localStorage' | 'sessionStorage' | 'indexedDB' | 'cookies' | 'cache' | 'url'
  | 'preferences' | 'secure' | 'sqlite' | 'filesystem';

interface StorageOptions {
  storage?: StorageType;      // target a specific adapter
  ttl?: number;               // milliseconds
  sliding?: boolean;          // reset the TTL on each read
  tags?: string[];            // for query()
  encrypt?: boolean;          // per-call override (async only)
  compress?: boolean;         // per-call override (async only)
  verify?: boolean;           // integrity check on read
  durable?: boolean;          // read-back-and-retry on write
}

interface StrataConfig {
  defaultStorages?: StorageType[];
  adapters?: { /* per-adapter settings — see Configuration */ };
  encryption?: EncryptionConfig;
  compression?: CompressionConfig;
  sync?: SyncConfig;
  integrity?: boolean;
  durableWrites?: boolean;
  mirror?: StorageType[];
  autoBackup?: { interval: number; storage: StorageType };
  debug?: boolean;
}

💻 Command Line #

npx strata-storage <command>

| Command | What it does | |---|---| | configure | Interactive wizard that writes a Strata configuration for your project. | | init | Alias for configure. | | setup | Alias for configure. | | --help | Print usage. |

The CLI is optional — everything it produces can be written by hand.

🧪 Examples #

| Goal | Example | |---|---| | See every core call in one file | docs/examples/basic-usage.ts | | Run a real app against a local build | example-apps/demo-app | | Browse framework and feature recipes | Examples on the docs site |

🎛️ Advanced Features #

  • Encryption — AES-GCM through Web Crypto, per instance or per call. →
  • Compression — applied above a byte threshold you set. →
  • TTL and expiry — absolute or sliding, with a cleanup sweep. →
  • Queries — MongoDB-style conditions over values and tags. →
  • Cross-tab sync — change notifications across tabs of one origin. →
  • Integrity, durable writes, mirroring, snapshots — the opt-in recovery set, all off by default. →
  • Migrations — an experimental adapter-level utility for reshaping stored data. →
  • Firebase sync — mirror values to Firestore or the Realtime Database. →

🚑 Recovery & Troubleshooting #

| Symptom | Cause | Fix | |---|---|---| | Native adapters do nothing on device, but web works | The native module was never copied into the iOS/Android project | Run npx cap sync, then rebuild the app | | Cannot find module 'strata-storage/react' or its types | TypeScript is on moduleResolution: "node", which cannot read sub-path exports | Set "moduleResolution": "bundler" or "nodenext" in tsconfig.json | | StorageError telling you to use the async API | A sync call targeted an async-only adapter (indexedDB, cache, sqlite, filesystem, secure, preferences) | Use await storage.get/set(...), or pass { storage: 'localStorage' } | | setSync throws with { encrypt: true } or { compress: true } | Web Crypto and compression are asynchronous | Use await storage.set(...) for encrypted or compressed values | | getSync throws on a value you stored earlier | The value was written encrypted or compressed | Read it with await storage.get(...) | | IntegrityError on read | The stored value no longer matches its checksum | Configure mirror for read-repair, or pass { ignoreCorruption: true } to get null instead | | No available storage adapters | Every adapter in defaultStorages reported unavailable — common in Node and SSR | Include 'memory' in defaultStorages, or guard the call behind a browser check | | Console errors naming keys your app owns, not Strata's | Known open defect — see Limitations | Set a prefix: defineStorage({ adapters: { localStorage: { prefix: 'myapp:' } } }) |

More: Troubleshooting · FAQ.

🚧 Limitations #

  • ESM only. There is no CommonJS build. engines.node is >=24.13.0, where Node can require() an ESM graph; on older Node a require('strata-storage') will fail.
  • A small test suite, by design. yarn gates runs typecheck, lint, build and then Vitest against the built dist/: the storage-ownership predicate's 18 cases and the README version row. Everything else is covered by the typecheck, lint and build gates, run locally before every release.
  • Native behaviour cannot be verified from web or Node. The iOS and Android adapters depend on your Capacitor project's own configuration, so verify them on a real device using the device-verification guide.
  • Integrity checksums are not cryptographic. They are FNV-1a: they cheaply catch accidental corruption such as truncated writes, and they do not resist deliberate tampering. Use encryption for that.
  • The synchronous API is genuinely limited. It works only on memory, localStorage, sessionStorage, cookies and url, and it cannot encrypt or compress.
  • The URL adapter is not durable storage. URLs have practical length limits around 2,000 characters, and in 'query' mode the data is sent to the server and appears in its logs. Use 'hash' mode to keep it client-side.
  • Node support is minimal. Only the memory adapter is available outside a browser, so values do not persist across processes.
  • Web adapters share their storage area, and identify their own data by shape. localStorage, sessionStorage and cookies are shared with every other script on the origin. An adapter treats a key as its own only when the stored value is a StorageValue envelope, so keys(), the TTL sweep and clear() never touch another application's data, and a value we cannot read is skipped at debug rather than reported as an error. The consequence to know about: a key written to the same area by something other than this library is invisible to keys() by design. Call setLogLevel('debug') to see what is being skipped and why.
  • Keys are prefixed strata: since 3.0.0, and that is a breaking change. Existing data migrates itself on read, so most consumers do nothing. 🔴 But if anything outside this library reads a physical key directly — a pre-paint theme script, a logger reading its own level — set defineStorage({ keyPrefix: false }). Migration keeps the data reachable through this library; it cannot fix a hard-coded reader. See Changelog.
  • Firebase adapter names are not in the StorageType union. 'firestore' and 'realtime' are runtime names, so strict TypeScript may need a cast on the options object.

📚 Documentation #

| Document | Read it when | |---|---| | Installation | setting the package up for the first time | | Quick start | you want a working call in two minutes | | Configuration | you need the full option set | | API reference | you need an exact signature | | Adapters | choosing a backend, or writing your own | | Platform guides | wiring web, iOS, Android, Capacitor or Firebase | | Recovery and integrity | the data must survive corruption | | Migration guide | upgrading from an earlier major | | Troubleshooting · FAQ | something is not behaving | | AI integration guide | a coding agent is implementing against this package | | llms.txt · llms-full.txt | you need the docs as machine-readable text |

🔄 Changelog #

Latest release: 3.1.4 — the Firebase adapter names are now accepted by the public TypeScript storage option. Runtime behavior is unchanged.

Full history: CHANGELOG.md.

🤝 Contributing #

Fork and open a pull request — see CONTRIBUTING.md for setup, standards, and how to request collaborator access. main is protected against deletion and force-push. The maintainer can push releases directly under the repository ruleset.

🗂️ Repository #

src/            TypeScript source — core, adapters, features, framework integrations
dist/           build output (published)
ios/            native iOS plugin sources (published, for Capacitor)
android/        native Android plugin sources (published, for Capacitor)
bin/            the npx CLI (published)
tests/          Vitest checks against the built dist/
docs/           internal project records — NOT the docs site
example-apps/   runnable demo application

The documentation site lives in its own repository: aoneahsan/strata-storage-docs.

💬 Support #

Questions and bugs: open an issue.

If this package saves you time, you can support its maintenance at aoneahsan.com/payment.

📄 License #

MIT © Ahsan Mahmood — see LICENSE.

👤 Author #

Ahsan Mahmood — aoneahsan.com · GitHub · LinkedIn · [email protected]

🔗 Links #

| | | |---|---| | Documentation | https://stratastorage-docs.aoneahsan.com | | npm | https://www.npmjs.com/package/strata-storage | | Repository | https://github.com/aoneahsan/strata-storage | | Issues | https://github.com/aoneahsan/strata-storage/issues | | Changelog | https://github.com/aoneahsan/strata-storage/blob/main/CHANGELOG.md | | Docs site source | https://github.com/aoneahsan/strata-storage-docs | | Project website | https://stratastorage.aoneahsan.com | | Support the project | https://aoneahsan.com/payment |

🏷️ Keywords #

storage · capacitor · localstorage · indexeddb · sqlite · keychain · cross-platform · zero-dependencies · react · vue · angular · typescript