dumbmatter / fakeIndexedDB

A pure JS in-memory implementation of the IndexedDB API
Apache License 2.0
562 stars 69 forks source link

transaction doesn't support array stores? #61

Closed zslucky closed 3 years ago

zslucky commented 3 years ago

Looks like doesn't support db.transaction(["customers"], "readwrite") ? Only support db.transaction("customers", "readwrite")?

This code is from MDN

version: fake-indexeddb@3.1.2

dumbmatter commented 3 years ago

It does support that, and there are many unit tests including that syntax such as https://github.com/dumbmatter/fakeIndexedDB/blob/4333821ec0b292ccf4a09fc4318817dfaa8ca697/src/test/fakeIndexedDB/fakeIndexedDB.ts#L489

So I suspect you're running into some other problem. Can you post a self-contained code example?

zslucky commented 3 years ago

Here's a simple demo via jest:

require("fake-indexeddb/auto");

export default class IndexDBWrapper {
  constructor(dbName, dbVersion = 1, onUpgrade) {
    this.dbName = dbName;
    this.dbVersion = dbVersion;
    this.onUpgrade = onUpgrade;

    this.db = null;
    this.dbInitPromise = this.initDB();
    this.dbInitPromise.catch((err) => { console.log('init db error ', err) });
  }

  initDB() {
    return new Promise((resolve, reject) => {
      const { dbName, dbVersion, onUpgrade } = this;
      const request = window.indexedDB.open(dbName, dbVersion);

      request.onsuccess = () => {
        this.db = request.result;
        this.db.onversionchange = () => {
          if (this.db) {
            this.db.close();
            window.location.reload();
          }
        };
        resolve(this.db);
      };

      request.onerror = (event) => {
        reject(event);
      };

      request.onupgradeneeded = (event) => {
        if (onUpgrade) onUpgrade(event.target.result);
      };
    });
  }

  getTx(table, permission) {
    try {
      console.log('table = ', table);
      return Promise.resolve(this.db.transaction(table, permission).objectStore(table));
    } catch (err) {
      console.error('getTx err = ', err);
      Promise.reject(err);
    }
  }
}

const testTable = 'test-table';
const onUpgrade = (db) => {
  if (!db.objectStoreNames.contains(testTable)) {
    db.createObjectStore(testTable, { keyPath: 'id' });
  }
};
const idb = new IndexDBWrapper('test-db', 1, onUpgrade);

describe('test code', () => {
  test('support array', async () => {
    await idb.dbInitPromise;
    await idb.getTx([testTable]);
  });
});

The error shows: Error [NotFoundError]: The operation failed because the requested database object could not be found. For example, an object store did not exist but was being opened.

dumbmatter commented 3 years ago
      return Promise.resolve(this.db.transaction(table, permission).objectStore(table));

The problem is not the call to transaction, it is the call to objectStore - the argument needs to be a string, not an array.

zslucky commented 3 years ago

👍