orbitdb / orbitdb

Peer-to-Peer Databases for the Decentralized Web
MIT License
8.27k stars 568 forks source link

TypeError: exists is not a function #280

Closed cristiano-belloni closed 6 years ago

cristiano-belloni commented 6 years ago

Hi, It seems that in 'orbit-db-cache' you require 'level', which in turn requires 'node-bindings'. 'node-bindings' has a bug and returns the above error in a clean orbit-db install.

Luckily it seems they fixed it: https://github.com/TooTallNate/node-bindings/pull/20 + https://github.com/Level/level/issues/34

It might be just a matter of updating the version of level? Right now, installing orbit-db and importing it dies.

shd101wyy commented 6 years ago

I met the same error while using orbit-db in browser.

cristiano-belloni commented 6 years ago

Yep, now that I think about it, why are we even trying to use fs.exists (which is deprecated anyways) in a browser environment? Is it level's fault? I'll try to go back through orbit-db versions to pinpoint what tag breaks it. Right now I'm at orbit-db@0.18.12

shd101wyy commented 6 years ago

Probably this one: https://github.com/orbitdb/orbit-db/pull/272 But I am not sure.

cristiano-belloni commented 6 years ago

Thanks, @shd101wyy

So, I bisected this and it seems that browser is broken for orbit-db@0.18.11 onwards, included. If you lock your version to orbit-db@0.18.10 it works. @haadcode FIY.

Also (unrelated) when IndexeDb version change it's probably better to make it a breaking change or at least change the minor?

coyotespike commented 6 years ago

Same result as @cristiano-belloni, orbit-db@0.18.10 is the last working version for me, with later versions showing same error.

cristiano-belloni commented 6 years ago

Yep, the problem seems introduced by level, which requires leveldown, which is a node-only package and does not work in the browser.

Pure C++ Node.js LevelDB binding serving as the back-end to LevelUP We aim to support at least Active LTS and Current Node.js releases

Take it with a grain of salt, I only had 10 minutes to look at it.

haadcode commented 6 years ago

Thank you everyone for looking into this! ❤️ I'm sorry you ran into troubles with the latest changes, especially the leveldb one.

I'll take a look at this today and see what's happening. We shouldn't be using leveldown in the browser and there should be no fs references in the code.

haadcode commented 6 years ago

@cristiano-belloni can you provide more context as to where/how this happens? How are you using the module in your browser code? Do you transpile it with webpack? Do you use the included build in dist/orbitdb.min.js?

cristiano-belloni commented 6 years ago

@haadcode I import orbit-db with

import OrbitDB from 'orbit-db'

And I use the Webpack configuration files coming with create-react-app, with no modifications / ejection.

The easiest way to repro this is creating a dummy project with create-react-app, installing orbit-db and ipfs and importing them in app.js. You should see a runtime stack trace when the app tries to dynamically require level.

cristiano-belloni commented 6 years ago

Here is where orbit-db-cache tries to require level, which causes the error.

Here is where orbit-db requires orbit-db-cache.

Here is where a Webpack conf external sets fs to an empty object. Was that added to fix / work around level in tests?

haadcode commented 6 years ago

@cristiano-belloni thanks for pushing this! I understand this is really annoying. I initially started to reply to your previous comment to explain what's happening but after spending a few hours down the rabbit hole of build process, I'm fixing this in a way that is I believe the cleanest way to support what you're trying to do: https://github.com/orbitdb/orbit-db/pull/282.

cristiano-belloni commented 6 years ago

@haadcode - Thanks for the fix! yes, I think that the only way to build for importing in the browser is either have a separate browser build or have something inside the code which conditionally requires a module when it detects it's run in node. That's unfortunate, but the ugly alternative would be asking developers to set externals in their webpack.conf :(

cristiano-belloni commented 6 years ago

However, it's not

import { OrbitDB } from 'orbit-db'

but

import OrbitDB from 'orbit-db'

haadcode commented 6 years ago

@cristiano-belloni moved the current webpack example from orbit-db repo to its own repo: https://github.com/haadcode/example-orbitdb-webpack. Will move it to @orbitdb org soon.