Moshe Shmukler
Moshe Shmukler

Reputation: 1300

Dumping indexedDB data

Working on a Chrome Extension, which needs to integrate with IndexedDB. Trying to figure out how to use Dexie.JS. Found a bunch of samples. Those don't look too complicated. There is one specific example particularly interesting for exploring IndexedDB with Dexie at https://github.com/dfahlander/Dexie.js/blob/master/samples/open-existing-db/dump-databases.html

However, when I run the one above - the "dump utility," it does not see IndexedDB databases, telling me: There are databases at the current origin.

From the developer tools Application tab, under Storage, I see my IndexedDB database.

Is this some sort of a permissions issue? Can any indexedDB database be accessed by any tab/user?

What should I be looking at?

Thank you

Upvotes: 2

Views: 9529

Answers (2)

ccpizza
ccpizza

Reputation: 31686

A working example for dumping data to a JSON file using the current indexedDB API as described at:

The snippet below will dump recent messages from a gmail account with the Offline Mode enabled in the gmail settings.

var dbPromise = indexedDB.open("[email protected]_xdb", 109, function (db) {
  console.log(db);
});

dbPromise.onerror = (event) => {
  console.log("oh no!");
};
dbPromise.onsuccess = (event) => {
  console.log(event);
  var transaction = db.transaction(["item_messages"]);
  var objectStore = transaction.objectStore("item_messages");
  var allItemsRequest = objectStore.getAll();

  allItemsRequest.onsuccess = function () {
    var all_items = allItemsRequest.result;
    console.log(all_items);

    // save items as JSON file
    var bb = new Blob([JSON.stringify(all_items)], { type: "text/plain" });
    var a = document.createElement("a");
    a.download = "gmail_messages.json";
    a.href = window.URL.createObjectURL(bb);
    a.click();
  };
};

Running the code above from DevTools > Sources > Snippets will also let you set breakpoints and debug and inspect the objects.

Make sure you set the right version of the database as the second parameter to indexedDB.open(...). To peek at the value used by your browser the following code can be used:

indexedDB.databases().then(
    function(r){
        console.log(r);
    }
);

Upvotes: 0

David Fahlander
David Fahlander

Reputation: 5691

In chrome/opera, there is a non-standard API webkitGetDatabaseNames() that Dexie.js uses to retrieve the list of database names on current origin. For other browsers, Dexie emulates this API by keeping an up-to-date database of database-names for each origin, so:

For chromium browsers, Dexie.getDatabaseNames() will list all databases at current origin, but for non-chromium browsers, only databases created with Dexie will be shown.

If you need to dump the contents of each database, have a look at this issue, that basically gives:

interface TableDump {
    table: string
    rows: any[]
}

function export(db: Dexie): TableDump[] {
    return db.transaction('r', db.tables, ()=>{
        return Promise.all(
            db.tables.map(table => table.toArray()
                .then(rows => ({table: table.name, rows: rows})));
    });
}

function import(data: TableDump[], db: Dexie) {
    return db.transaction('rw', db.tables, () => {
        return Promise.all(data.map (t =>
            db.table(t.table).clear()
              .then(()=>db.table(t.table).bulkAdd(t.rows)));
    });
}

Combine the functions with JSON.stringify() and JSON.parse() to fully serialize the data.

const db = new Dexie('mydb');
db.version(1).stores({friends: '++id,name,age'});

(async ()=>{
    // Export
    const allData = await export (db);
    const serialized = JSON.stringify(allData);

    // Import
    const jsonToImport = '[{"table": "friends", "rows": [{id:1,name:"foo",age:33}]}]';
    const dataToImport = JSON.parse(jsonToImport);
    await import(dataToImport, db);
})();

Upvotes: 4

Related Questions