IndexedDB-backed envelope storage for AES-GCM payloads in browsers and workers.
npm install offdexIndexedDB-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.
- Minimal put/get/has/delete API 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.
``bash`
npm install offdexor
pnpm add offdexor
yarn add offdex
`js
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);
`
Singleton storage instance per JavaScript realm backed by the offdex databaseenvelopes
and object store. The underlying store is shared per origin across
tabs and workers.
- put(key, envelope) -> Promiseget(key)
- -> Promisehas(key)
- -> Promisedelete(key)
- -> Promisedestroy()
- -> Promise
- key must be a base64url string, exactly 43 chars (32 random bytes, noput/get/has/delete
padding).
- throw a TypeError if the identifier is invalid.
- envelope must be an object with:iv
- : Uint8Array exactly 12 bytes (AES-GCM nonce).ciphertext
- : non-empty ArrayBuffer.put
- throws a TypeError if the envelope is invalid.
`bash`
npm run build
`bash`
npx playwright install
npm test
Unit, integration, and end-to-end runs are available as well:
`bash`
npm run test:unit
npm run test:integration
npm run test:e2e
Playwright runs Chromium, Firefox, WebKit, plus mobile emulation projects for
integration and end-to-end coverage.
`bash`
npx playwright install
npm run bench
The benchmark runs in Chromium via Playwright and times a batch of envelope
put/has/get/delete operations.
`text`
[bench] put 200 envelopes: 148.6ms
[bench] has 200 envelopes: 101.6ms
[bench] get 200 envelopes: 100.3ms
[bench] delete 200 envelopes: 123.8ms
- Run npm run build, open in-browser-testing.html, then use storage from
the console with envelope values.
- Requires indexedDB` (modern browsers / worker runtimes).
- Data is scoped per origin; all tabs/workers on the same origin share the same
store.