Dynamic Dexie schema

Example on how to change schema runtime with Dexie. Please open the console log to see results.

by David Fahlander

HTML

<script src="dexie@3.x"></script>
<script src="https://unpkg.com/dexie"></script>
<p>
  Please open your console in devtools to see any action...
</p>

JavaScript

console.log("Using Dexie version: " + Dexie.semVer);

//
// !!Please open your console in devtools to see any action!!
//

async function changeSchema(db, schemaChanges) {
    db.close();
    const newDb = new Dexie(db.name);
   
    newDb.on('blocked', ()=>false); // Silence console warning of blocked event.
    // Workaround: If DB is empty from tables, it needs to be recreated
    if (db.tables.length === 0) {
      await db.delete();
      newDb.version(1).stores(schemaChanges);
      return await newDb.open();
    }

		// Extract current schema in dexie format:
    const currentSchema = db.tables.reduce((result,{name, schema}) => {
    	result[name] = [
      	schema.primKey.src,
        ...schema.indexes.map(idx => idx.src)
      ].join(',');
      return result;
    }, {});
    
    console.log("Version: " + db.verno);
    console.log("Current Schema: ", currentSchema);
    
    // Tell Dexie about current schema:
    newDb.version(db.verno).stores(currentSchema);
    // Tell Dexie about next schema:
    newDb.version(db.verno + 1).stores(schemaChanges);
    // Upgrade it:
    return await newDb.open();    
}

// Open database dynamically:
async function playAround() {
    let db = new Dexie ('FriendsDatabase2');
    if (!(await Dexie.exists(db.name))) {
        console.log("Db does not exist");
        db.version(1).stores({});
    }
    await db.open();
    console.log("Could open DB")

    // Add a table with some indexes:
    db = await changeSchema(db, {friends: 'id, name'});
    console.log("Could enforce friends table with id and name")

    // Add another index in the friends table
    db = await changeSchema(db, {friends: 'id, name, age'});
    console.log("Could add the age index")

    // Remove the age index again:
    db = await changeSchema(db, {friends: 'id, name'})
    console.log("Could remove age index")

    // Remove the friends table
    db = await changeSchema(db, {friends: null});
    console.log("Could delete friends...