dumbmatter / fakeIndexedDB

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

Circular import #33

Open TvoroG opened 5 years ago

TvoroG commented 5 years ago

Hey! Thanks for this lib!

I'm trying to use fakeIndexedDB in node environment and have the following code:

import FDBCursor = require("fake-indexeddb/lib/FDBCursor");

Just trying to import fdbcursor but it throws error:

    TypeError: Object prototype may only be an Object or null: undefined
        at setPrototypeOf (<anonymous>)

      at extendStatics (node_modules/fake-indexeddb/build/FDBCursorWithValue.js:7:16)
      at __extends (node_modules/fake-indexeddb/build/FDBCursorWithValue.js:10:9)
      at node_modules/fake-indexeddb/build/FDBCursorWithValue.js:18:5
      at Object.<anonymous> (node_modules/fake-indexeddb/build/FDBCursorWithValue.js:28:2)

I found that it is because of circular import.

What should i do?

dumbmatter commented 5 years ago

That looks like a TypeScript import. What is the actual Node.js code it gets compiled to? Importing like this should work:

const FDBCursor = require("fake-indexeddb/lib/FDBCursor");
TvoroG commented 5 years ago

It gets compiled to this:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const FDBCursor = require("fake-indexeddb/lib/FDBCursor");
TvoroG commented 5 years ago

I'm using following command to compile it:

tsc --skipLibCheck --target es6 --module commonjs --outDir ...
dumbmatter commented 5 years ago

Ah crap you're right, I get the same error even with my code! I'll look into this soon, thanks for the bug report.

TvoroG commented 5 years ago

Cool! Thanks for quick response! :)

dumbmatter commented 5 years ago

You're right, it is related to circular imports. Probably nobody noticed it before because if you import fake-indexeddb first, it's not a problem. And there probably is not a reason to import FDBCursor without importing fake-indexeddb too.

So if you change from:

const FDBCursor = require("fake-indexeddb/lib/FDBCursor");

to:

const indexedDB = require("fake-indexeddb");
const FDBCursor = require("fake-indexeddb/lib/FDBCursor");

it will work. If you really have no use for the indexedDB variable, you could also do:

require("fake-indexeddb");
const FDBCursor = require("fake-indexeddb/lib/FDBCursor");

I'd still like to fix this, but I'm just posting the workaround in case I don't get around to it for a while.

TvoroG commented 5 years ago

Thanks! It works this way.

About my use case: i'm writing custom testEnvironment for jest and want to extend this.global with fakeIndexedDB:

require("fake-indexeddb"); // workaround
import FDBCursor = require("fake-indexeddb/lib/FDBCursor");
import FDBCursorWithValue = require("fake-indexeddb/lib/FDBCursorWithValue");
import FDBFactory = require("fake-indexeddb/lib/FDBFactory");
...

export function makeIndexedDBEnv() {
    return {
        indexedDB: new FDBFactory(), // to not worry about resetting
        IDBCursor: FDBCursor,
        IDBCursorWithValue: FDBCursorWithValue,
        ...
    }
}
class CustomEnvironment extends NodeEnvironment {
  ...
  async setup() {
    await super.setup();
    const idbEnv = makeIndexedDBEnv();
    Object.assign(this.global, idbEnv);
    ...
  }
}