offdex
v4.0.0
Published
IndexedDB-backed envelope storage for AES-GCM payloads in browsers and workers.
Maintainers
Readme
Offdex
IndexedDB-backed envelope storage for browsers and workers. Store AES-GCM envelopes (12-byte IV + ciphertext ArrayBuffer) by base64url identifier and read them back directly. The store is shared per origin across tabs and workers.
Why use Offdex
- Minimal
put/get/has/deleteAPI for encrypted payload envelopes. - Fixed-width base64url identifiers (43 chars, 32 random bytes).
- Single object store keyed by identifier; no migrations to manage.
- Data shared per origin across tabs and workers (instance per realm).
- Offline persistence via IndexedDB.
- TypeScript-first.
Install
npm install offdex
# or
pnpm add offdex
# or
yarn add offdexQuick start
import storage from "offdex";
const makeId = () => {
const bytes = crypto.getRandomValues(new Uint8Array(32));
let binary = "";
for (let i = 0; i < bytes.length; i += 1) {
binary += String.fromCharCode(bytes[i]);
}
return btoa(binary)
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=+$/, "");
};
const envelope = {
iv: crypto.getRandomValues(new Uint8Array(12)),
ciphertext: new Uint8Array([1, 2, 3]).buffer,
};
const key = makeId();
await storage.put(key, envelope);
const stored = await storage.get(key);
if (stored) {
console.log(stored.iv, stored.ciphertext);
}
await storage.delete(key);API
storage (default export)
Singleton storage instance per JavaScript realm backed by the offdex database
and envelopes object store. The underlying store is shared per origin across
tabs and workers.
Methods
put(key, envelope)->Promise<void>get(key)->Promise<OffdexEnvelope | null>has(key)->Promise<boolean>delete(key)->Promise<void>destroy()->Promise<void>
Identifier requirements
keymust be a base64url string, exactly 43 chars (32 random bytes, no padding).put/get/has/deletethrow aTypeErrorif the identifier is invalid.
Envelope requirements
envelopemust be an object with:iv:Uint8Arrayexactly 12 bytes (AES-GCM nonce).ciphertext: non-emptyArrayBuffer.
putthrows aTypeErrorif the envelope is invalid.
Build
npm run buildTests
npx playwright install
npm testUnit, integration, and end-to-end runs are available as well:
npm run test:unit
npm run test:integration
npm run test:e2ePlaywright runs Chromium, Firefox, WebKit, plus mobile emulation projects for integration and end-to-end coverage.
Benchmarks
npx playwright install
npm run benchThe benchmark runs in Chromium via Playwright and times a batch of envelope
put/has/get/delete operations.
[bench] put 200 envelopes: 148.6ms
[bench] has 200 envelopes: 101.6ms
[bench] get 200 envelopes: 100.3ms
[bench] delete 200 envelopes: 123.8msManual browser check
- Run
npm run build, openin-browser-testing.html, then usestoragefrom the console with envelope values.
Notes
- Requires
indexedDB(modern browsers / worker runtimes). - Data is scoped per origin; all tabs/workers on the same origin share the same store.
