A framework-agnostic, lightweight TypeScript library for exporting and importing IndexedDB databases via type-tagged JSON.
aossie-idb-backup provides a simple, portable way to back up and restore IndexedDB databases in the browser. It produces a self-describing JSON file that preserves data types that JSON.stringify normally corrupts — such as Uint8Array, bigint, and Date.
The library is designed to be framework-agnostic: it works in any browser environment and includes SSR safety guards for server-rendered frameworks like Next.js and Nuxt.
- Generic JSON export format : Structured
schema+storesmapping for portable, human-readable backups - Type-tagged serialization : Lossless round-trip for
Uint8Array,bigint, andDateusing a__typetag convention - Import strategies : Choose between
"overwrite"(fresh restore) or"merge"(additive sync with existing data) - SSR-safe : Graceful no-op guards for server-side rendering environments
- Dual output : Ships both ESM and CJS bundles
- Lightweight : Uses the
idbwrapper over the native IndexedDB API with no heavy dependencies
| Category | Tools |
|---|---|
| Language | TypeScript 5 |
| IndexedDB | Native API + idb wrapper |
| Bundler | tsup (ESM + CJS) |
| Testing | vitest + happy-dom |
| Linting | ESLint 9 + TypeScript ESLint |
| Formatting | Prettier |
graph TD
A[aossie-idb-backup] --> B[src/core]
A --> C[src/serialization]
A --> D[src/types]
A --> E[src/utils]
B --> B1["exporter.ts — exportDB()"]
B --> B2["importer.ts — importDB()"]
B --> B3["migrations.ts — future schema migrations"]
C --> C1["index.ts — serialize() / deserialize()"]
D --> D1["index.ts — ExportFormat, TaggedValue, etc."]
E --> E1["ssr.ts — isBrowser(), assertBrowser()"]
E --> E2["file.ts — downloadJSON(), readJSONFile()"]
The library produces a self-describing JSON structure:
{
"backupVersion": 1,
"databaseName": "my-app-db",
"databaseVersion": 3,
"exportedAt": "2025-06-01T12:00:00.000Z",
"schema": {
"messages": {
"keyPath": "id",
"autoIncrement": false,
"indexes": [
{ "name": "by-timestamp", "keyPath": "timestamp", "unique": false }
]
}
},
"stores": {
"messages": [
{
"id": "msg-001",
"payload": { "__type": "u8", "value": "SGVsbG8gV29ybGQ=" },
"timestamp": { "__type": "date", "value": "2025-06-01T12:00:00.000Z" },
"fee": { "__type": "bigint", "value": "1000000000000000000" }
}
]
}
}| Source Type | __type |
Serialized value |
|---|---|---|
Uint8Array |
"u8" |
Base64-encoded string |
bigint |
"bigint" |
String representation |
Date |
"date" |
ISO 8601 string |
All other JSON-safe values (strings, numbers, booleans, nulls, plain objects, arrays) pass through unchanged.
- Node.js >= 20
- npm (ships with Node.js)
- Clone the repository
git clone https://github.com/AOSSIE-Org/IndexedDB-Import-Export.git
cd IndexedDB-Import-Export- Install dependencies
npm install- Build the library
npm run build- Run tests
npm test| Script | Description |
|---|---|
npm run build |
Bundle the library with tsup (ESM + CJS + type declarations) |
npm test |
Run the test suite with Vitest |
npm run test:watch |
Run tests in watch mode during development |
npm run lint |
Lint source and test files with ESLint |
npm run format |
Auto-format code with Prettier |
npm run format:check |
Check formatting without modifying files |
Note: The core API is under active development. The examples below show the intended usage once the feature PRs are merged.
import { exportDB } from 'aossie-idb-backup';
const backup = await exportDB({
dbName: 'my-app-db',
// Optional: export only specific stores
storeNames: ['messages', 'contacts'],
});
console.log(JSON.stringify(backup, null, 2));import { importDB } from 'aossie-idb-backup';
// Overwrite: delete existing data and restore from backup
await importDB({
dbName: 'my-app-db',
backupData: backup,
strategy: 'overwrite',
});
// Merge: keep existing data and add/update from backup
await importDB({
dbName: 'my-app-db',
backupData: backup,
strategy: 'merge',
});import { downloadJSON } from 'aossie-idb-backup';
downloadJSON(backup, 'my-backup.json');import { readJSONFile } from 'aossie-idb-backup';
const fileInput = document.querySelector<HTMLInputElement>('#file-input');
const file = fileInput!.files![0];
const backup = await readJSONFile(file);Contributions are welcome! If you would like to contribute, please refer to CONTRIBUTING.md.
This project is licensed under the GNU General Public License v3.0. See the LICENSE file for details.
Thanks to everyone who has contributed to this project.
© 2025 AOSSIE