Skip to content

Instantly share code, notes, and snippets.

@azproduction
Created July 8, 2021 11:22
Show Gist options
  • Select an option

  • Save azproduction/d259d7a69c4e46c83df36b7c877448fa to your computer and use it in GitHub Desktop.

Select an option

Save azproduction/d259d7a69c4e46c83df36b7c877448fa to your computer and use it in GitHub Desktop.
Dumps all IndexedDB databases and saves all of them into a json file
;(async () => {
async function dumpDatabase(dbName) {
var dbExists = await new Promise(resolve => {
var request = window.indexedDB.open(dbName)
request.onupgradeneeded = e => {
e.target.transaction.abort()
resolve(false)
}
request.onerror = () => resolve(true)
request.onsuccess = () => resolve(true)
})
if (!dbExists) {
throw new Error('Database does not exist')
}
var idbDatabase = await new Promise((resolve, reject) => {
var request = window.indexedDB.open(dbName)
request.onerror = () => reject('Could not open the database')
request.onsuccess = () => resolve(request.result)
});
const data = await new Promise((resolve, reject) => {
const exportObject = {}
if (idbDatabase.objectStoreNames.length === 0) {
resolve(exportObject)
return;
}
const transaction = idbDatabase.transaction(
idbDatabase.objectStoreNames,
'readonly'
)
transaction.addEventListener('error', reject)
for (const storeName of idbDatabase.objectStoreNames) {
const allObjects = []
transaction
.objectStore(storeName)
.openCursor()
.addEventListener('success', event => {
const cursor = event.target.result
if (cursor) {
// Cursor holds value, put it into store data
allObjects.push(cursor.value)
cursor.continue()
} else {
// No more values, store is done
exportObject[storeName] = allObjects
// Last store was handled
if (
idbDatabase.objectStoreNames.length ===
Object.keys(exportObject).length
) {
resolve(exportObject);
}
}
})
}
});
return data;
}
try {
const databases = await window.indexedDB.databases();
const result = [];
for (const db of databases) {
result.push({
db,
content: await dumpDatabase(db.name)
});
}
const a = document.createElement('a');
a.href = URL.createObjectURL(new Blob([JSON.stringify(result, null, 2)], {type: 'application/json'}));
a.download = `indexed-db-dump-${new Date().toJSON()}.json`;
a.click();
URL.revokeObjectURL(a.href);
} catch(error) {
console.error(error)
}
})();
@KaKi87
Copy link
Copy Markdown

KaKi87 commented Apr 10, 2026

5 years later, thank you for this.

Here's my lightweight modernized single-function rewrite, for my use case I dropped the download part :

const dumpIndexedDB = async () => {
    const result = {};
    for(const { name: databaseName, version } of await window.indexedDB.databases()){
        result[databaseName] = {
            version,
            stores: {}
        };
        const database = await new Promise((resolve, reject) => {
            const request = window.indexedDB.open(databaseName);
            request.addEventListener('success', () => resolve(request.result));
            request.addEventListener('error', reject);
        });
        for(const storeName of database.objectStoreNames){
            result[databaseName].stores[storeName] = [];
            await new Promise((resolve, reject) => {
                const transaction = database.transaction(database.objectStoreNames, 'readonly');
                transaction.addEventListener('error', reject);
                transaction
                    .objectStore(storeName)
                    .openCursor()
                    .addEventListener('success', event => {
                        const cursor = event.target.result;
                        if(!cursor) return resolve();
                        result[databaseName].stores[storeName].push(cursor.value);
                        cursor.continue();
                    });
            });
        }
    }
    return result;
};
await dumpIndexedDB();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment