ipfs / js-ipfs

IPFS implementation in JavaScript
https://js.ipfs.tech
Other
7.44k stars 1.25k forks source link

57.0.1 Breaks a BUNCH of stuff #4122

Closed rick-rheo closed 2 years ago

rick-rheo commented 2 years ago

Severity:

Critical - System crash, application panic.

Description:

ERROR: 06/01 17:27:03+00:00::Module NftInstance Load raised an exception ERROR [ERR_PACKAGE_PATH_NOT_EXPORTED]: No "exports" main defined in /opt/NFTWeb+r_0.0.17/server/node_modules/ipfs-http-client/package.json

3 NPM packages in my project specify ipfs-http-client as a dependency. I do not. Each one of them fails because their package.json allows the latest version of ipfs-http-client. ...and now you removed the ability to "require" the module.

Just to be clear I have NO control over the version of the package that the other dependencies use.

welcome[bot] commented 2 years ago

Thank you for submitting your first issue to this repository! A maintainer will be here shortly to triage and review. In the meantime, please double-check that you have provided all the necessary information to make this process easy! Any information that can help save additional round trips is useful! We currently aim to give initial feedback within two business days. If this does not happen, feel free to leave a comment. Please keep an eye on how this issue will be labeled, as labels give an overview of priorities, assignments and additional actions requested by the maintainers:

Finally, remember to use https://discuss.ipfs.io if you just need general support.

Salman-Arshad commented 2 years ago

Any update on this?

victoryeo commented 2 years ago

I have the same error:

Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: No "exports" main defined in /node_modules/ipfs-http-client/package.json

in package.json: "ipfs-http-client": "^57.0.1",

in code: import { create } from 'ipfs-http-client' const ipfsnode = await create()

FatNerdPeng commented 2 years ago

我遇见了同样的问题: import * as IPFS from 'ipfs-core'

class IpfsService { async add(params) { const ipfs = await IPFS.create() const { cid } = await ipfs.add(params) return cid } }

module.exports = new IpfsService() 报错: Error: No "exports" main defined in ...\node_modules\ipfs-core\package.json at new NodeError (node:internal/errors:372:5) at throwExportsNotFound (node:internal/modules/esm/resolve:472:9) at packageExportsResolve (node:internal/modules/esm/resolve:693:7) at resolveExports (node:internal/modules/cjs/loader:482:36) at Function.Module._findPath (node:internal/modules/cjs/loader:522:31) at Function.Module._resolveFilename (node:internal/modules/cjs/loader:919:27) at Function.Module._load (node:internal/modules/cjs/loader:778:27) at Module.require (node:internal/modules/cjs/loader:1005:19) at require (node:internal/modules/cjs/helpers:102:18) at Object. (C:\work\work_program\nft-service\server\src\service\/ipfs.service.js:1:1) { code: 'ERR_PACKAGE_PATH_NOT_EXPORTED' }

achingbrain commented 2 years ago

ipfs-http-client@57.x.x is ESM only, which means you can't require it, you have to use import. One gotcha here is that if you are writing TypeScript, you have to make sure that your tsc config is set to output ESM and not CJS.

I don't know what dependencies you are using, but if the authors of those dependencies are expecting them to be consumed from a CJS environment, they should stick with ipfs-http-client@56.x.x.

I would suggest you ask them to revert and downgrade to ipfs-http-client@56.x.x, and release a major with ipfs-http-client@57.x.x that will give people time to upgrade to ESM at their own pace.

rick-rheo commented 2 years ago

@achingbrain That is NOT feasible to ask people I don't know or have any real contact with to update their module. Why did you break this?

ptoner commented 2 years ago

Broken unit tests lead me here.

Not sure exactly the remedy that's being suggested here. I AM using import. And I'm pretty sure TypeScript is outputting ESM.

My error is actually happening when I import ipfs-core. Or ipfs. Not sure what the deal is.

Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: No "exports" main defined in c:\Users\1330449\repos\large\node_modules\ipfs\package.json

EDIT: Ok nevermind I checked the link about ESM and I have most, but not all of that. And I've run into problems with other dependencies that have kept that from working. I guess...just stick with the old one? Maybe I'll try the async loading it describes.

UPDATE: That isn't practical right now and needs most of the same setup it looks like. Just gonna downgrade.

achingbrain commented 2 years ago

And I'm pretty sure TypeScript is outputting ESM.

If you are seeing ERR_PACKAGE_PATH_NOT_EXPORTED then it's transpiling dynamic imports to require. To stop that from happening you need "module": "ES2020" and "target": "ES2015".

ptoner commented 2 years ago

I have the target. Adding the module breaks a bunch of other things. I'd like to do this but not all libraries are to this point.

Downgrading fixed it.

ptoner commented 2 years ago

App itself works fine. Just breaks the unit tests.

The tests rely on some testing libraries that must require somewhere inside of them.

So I have to rid my entire testing stack of requires? Some of these things are built into the tooling. I'm not even sure that's possible for many things.

I'm going to explore what I might need to do to better separate the testing setup from the app. I understand wanting to use modules. It seems excessive to force all calling code to also be a module. Like...why is IPFS the one who's gonna call lockdown on the whole system? My actual app is spitting out modules as far as I know but getting stuff set up for a browser, testing with node, and also a reasonable dev environment can be tricky at best sometimes. Not having the main package be a module allowed the testing setup to co-exist with the rest of the code nicely. Webpack is doing the builds fine but I don't have it involved with the testing.

I appreciate the work that goes into this and hopefully I can learn how to address the problems I'm dealing with. I haven't actually successfully explored the dynamic import option yet because...I guess this is the first library that's made me look into it.

I may just refactor IPFS out of the unit/integration tests altogether. Though that would be super disappointing.

ptoner commented 2 years ago

If you are seeing ERR_PACKAGE_PATH_NOT_EXPORTED then it's transpiling dynamic imports to require. To stop that from happening you need "module": "ES2020" and "target": "ES2015".

Ok with a little refactoring I got through the problem I was having with dynamic imports originally.

But I am still getting that error even when dynamically importing.

I think what you're saying must be the thing. But making the original changes you suggested breaks a bunch of stuff for me.

I'm going to play around with it a bit. Maybe it won't be so bad. Thank you for coming to my TED talk.

ptoner commented 2 years ago
  "compilerOptions": {
    "experimentalDecorators": true,
    "lib": [ "es2017", "dom" ],
    "target": "ES2017",
    "types": ["reflect-metadata", "node", "mocha"],
    "skipLibCheck": true,  
    "resolveJsonModule": true,
    "moduleResolution": "node",
    "declaration": true,
    "emitDecoratorMetadata": true,
    "esModuleInterop": true,
    "outDir": "./dist",
    "sourceMap": true,
    "allowSyntheticDefaultImports": true
  },
  "include": ["src"],
  "exclude": ["node_modules"]
}

I have that configuration. If I run 'webpack serve' with that config it actually works fine with the most recent version of ipfs-core.

But if I then add:

"module": "ES2020"

It breaks. And it complains about imports inside the webpack config file.

Why would it work fine without the module line and then suddenly break?

UPDATE: Ok I still don't know why the above works, but to my problem adding 'module'...according to this there is some problem with the combo of webpack and typescript that stops this from working. There are workarounds listed but I have not had success yet. https://github.com/webpack/webpack-cli/issues/2916

UPDATE 2: Did not succeed. It seems like to use dynamic imports it needs all the same steps as just making the whole thing a module. Is there a way to have the dynamic import work properly without making it a module? It doesn't quite make sense how that's even a workaround if you need to do basically all the same stuff.

Also it seems as though there is specifically a problem with TypeScript transpiling dynamic imports to require: https://github.com/microsoft/TypeScript/issues/43329

ptoner commented 2 years ago

Ok based on this post I was able to workaround this in TypeScript: https://github.com/microsoft/TypeScript/issues/43329#issuecomment-1008361973

The dynamic import had to be:

        const IPFS = await Function('return import("ipfs-core")')() as Promise<typeof import('ipfs-core')>
        let node = IPFS.create()
ghost commented 2 years ago

it's still has the same error

ademidun commented 2 years ago

yarn upgrade ipfs-http-client@56.0.3 or (npm install ipfs-http-client@56.0.3)

Updated from @danskyr answer below. (I revisited this because I'm facing this issue in another project I'm building.)

Previous answer below:

For a workaround, I just downgraded to an older version: yarn upgrade ipfs-http-client@50.1.2 or (npm install ipfs-http-client@50.1.2). 57.0.1 was the version that was breaking for me.

I somewhat arbitrarily picked 50.1.2 because that's the version I use in another project that's working for me. Does anyone know if there's a higher version than 50.1.2 that can also be used?

danskyr commented 2 years ago

I had the same problem using 57.0.2. A downgrade to ^56.0.3 fixed it for me

ptoner commented 1 year ago

Ultimately I addressed my problem(s) by converting everything else to ESM. Which wasn't fun but seems like the way forward.

The biggest problems are that both hardhat and truffle struggle in various ways when run in a project marked as a module, but I guess I'll just accept that and look for a workaround for my tests.