nextauthjs / next-auth

Authentication for the Web.
https://authjs.dev
ISC License
24.96k stars 3.52k forks source link

@auth/express No "exports" main defined #9987

Closed luchillo17 closed 6 months ago

luchillo17 commented 9 months ago

Environment

System: OS: Linux 5.15 Ubuntu 22.04.3 LTS 22.04.3 LTS (Jammy Jellyfish) CPU: (32) x64 13th Gen Intel(R) Core(TM) i9-13900KF Memory: 10.74 GB / 15.53 GB Container: Yes Shell: 5.8.1 - /usr/bin/zsh Binaries: Node: 20.11.0 - ~/.nvm/versions/node/v20.11.0/bin/node Yarn: 1.22.19 - ~/.nvm/versions/node/v20.11.0/bin/yarn npm: 10.2.4 - ~/.nvm/versions/node/v20.11.0/bin/npm pnpm: 8.15.1 - ~/.nvm/versions/node/v20.11.0/bin/pnpm Browsers: Chrome: 120.0.6099.224 npmPackages: @auth/core: ^0.26.3 => 0.26.3 @auth/express: ^0.5.0 => 0.5.0 @auth/mongodb-adapter: ^2.2.1 => 2.3.3

Reproduction URL

https://github.com/luchillo17/job-assessment-projects/tree/repro-%40auth/express-issue

Describe the issue

In a new Nrwl Nx monorepo, with NodeJS 20.11.0 (the latest LTS at the moment) Installed latest @auth/express package, the error at import & run is this:

➜  job-assessment-projects git:(main) nx run insurance-policy-manager:serve

> nx run insurance-policy-manager:serve:development

Build option outputFileName not set for insurance-policy-manager. Using fallback value of dist/apps/insurance-policy-manager/main.js.

> nx run insurance-policy-manager:build

chunk (runtime: main) main.js (main) 2.48 KiB [entry] [rendered]
webpack compiled successfully (c93181d72b2934c0)

 ——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

 >  NX   Successfully ran target build for project insurance-policy-manager (1s)

Debugger listening on ws://localhost:9229/34f83655-fca4-4cf9-abf8-0f9037c3eb6b
For help, see: https://nodejs.org/en/docs/inspector

Error: No "exports" main defined in /home/luchillo17/Projects/job-assessment-projects/node_modules/@auth/express/package.json
    at exportsNotFound (node:internal/modules/esm/resolve:303:10)
    at packageExportsResolve (node:internal/modules/esm/resolve:593:13)
    at resolveExports (node:internal/modules/cjs/loader:591:36)
    at Function.Module._findPath (node:internal/modules/cjs/loader:668:31)
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:1130:27)
    at Function.Module._load (node:internal/modules/cjs/loader:985:27)
    at Function.Module._load (/home/luchillo17/Projects/job-assessment-projects/node_modules/.pnpm/@nx+js@18.0.3_@swc-node+register@1.6.8_@swc+core@1.3.107_@types+node@18.16.20_nx@18.0.3_typescript@5.3.3/node_modules/@nx/js/src/executors/node/node-with-require-overrides.js:18:31)
    at Module.require (node:internal/modules/cjs/loader:1235:19)
    at require (node:internal/modules/helpers:176:18)
    at Array.__webpack_modules__ (/home/luchillo17/Projects/job-assessment-projects/dist/apps/insurance-policy-manager/main.js:76:18)

How to reproduce

  1. Clone reproduction url project
  2. Install packages with pnpm, or a package manager of your choice (I also repro this with npm).
  3. Run the project with nx run insurance-policy-manager:serve if you have Nx installed globally, or pnpm exec nx run insurance-policy-manager:serve or equivalent in your package manager.

Expected behavior

Just like the NextAuth which I can run properly in a different project, it should import properly and the server should serve in port 3000.

luchillo17 commented 9 months ago

After trying a lot of things in other issues, like updating Node and updating the TSConfig in multiple ways for the module and target properties, I couldn't get it to work, for reference here's the package.json of the installed library:

@auth/express@0.5.0 package.json ```json { "name": "@auth/express", "description": "Authentication for Express.", "version": "0.5.0", "type": "module", "files": [ "*.js", "*.d.ts*", "lib", "providers", "src" ], "exports": { ".": { "types": "./index.d.ts", "import": "./index.js" }, "./providers": { "types": "./providers/index.d.ts" }, "./adapters": { "types": "./adapters.d.ts" }, "./providers/*": { "types": "./providers/*.d.ts", "import": "./providers/*.js" }, "./package.json": "./package.json" }, "publishConfig": { "access": "public" }, "dependencies": { "@auth/core": "0.25.0" }, "devDependencies": { "@auth/core": "experimental", "@types/express": "^4.17.17", "@types/supertest": "^2.0.12", "supertest": "^6.3.3" }, "peerDependencies": { "express": "^4.18.2" }, "keywords": [ "Express", "Auth.js" ], "author": "Rexford Essilfie ", "contributors": [ "Rexford Essilfie " ], "repository": "https://github.com/nextauthjs/next-auth", "license": "ISC", "scripts": { "build": "pnpm clean && pnpm providers && tsc", "clean": "rm -rf lib index.* src/lib/providers", "test": "vitest -c ../utils/vitest.config.ts", "providers": "node ../utils/scripts/providers" } } ```
elkay commented 9 months ago

I am having the same issue. Hoping this isn't a dead end for me and a bunch of work I'll have to throw away.

elkay commented 9 months ago

Ok, was able to fix the error. Not sure why everything was working fine without this until suddenly the @auth/express package was added, but after starting a new project and not seeing the problem I was able to compare and fix my actual project by adding this to package.json:

"type": "module"

Hope this helps anyone else that may have the same problem with this particular package.

luchillo17 commented 9 months ago

@elkay You mean you changed the dependency package.json or your projects one? I was in the middle of an interview test so I had no luxury time to try more stuff to fix my issue.

elkay commented 9 months ago

The project one. Didn't have to change anything else, it just started working after that.

luchillo17 commented 9 months ago

Well that leaves me without much of a solution given I'm using an Nx monorepo, it would probably affect all my apps no?

tahayeslbg commented 9 months ago

I'm getting the same error too. Still no solution found?

luchillo17 commented 9 months ago

I got an idea specifically for Nx monorepos, turns out the build process is different if you generate a new app with node+express preset, than if you use the @nx/express application generator, specifically the former uses ESBuild while the latter uses Webpack.

I haven't tested this but I think the setup is way easier to move into ESM if we use the ESBuild setup, at the very least I could add the "type": "module" property in package.json & fix surfacing issues way easier in a new project, I haven't tested adding @auth/express yet though.

m1daz commented 9 months ago

Facing same issue trying to use nextjs + expressjs

luchillo17 commented 9 months ago

@m1daz Wait what? why are you using Next and Express together? you usually pick 1 or the other since you can also do APIs in Next, do you mean 2 different projects? in Next you use next-auth (afaik the migration to @auth is still not done so @auth/next or so doesn't yet exist, and you need the beta branch for the app router).

https://authjs.dev/getting-started/introduction#about-authjs This has a link for the Next example app that then links to NextAuth.js. https://authjs.dev/reference/nextjs This is the latest docs for next-auth inside authjs.dev

m1daz commented 9 months ago

@m1daz Wait what? why are you using Next and Express together? you usually pick 1 or the other since you can also do APIs in Next, do you mean 2 different projects? afaik in Next you use next-auth (afaik the migration to @auth is still not done so @auth/next or so doesn't yet exist, and you need the beta branch for the app router).

https://authjs.dev/getting-started/introduction#about-authjs This has a link for Next example app that then links to NextAuth.js. https://authjs.dev/reference/nextjs This is the latest docs for next-auth inside authjs.dev

Originally I did that because I wanted a non-serverless backend (I self-host) on top of nextjs. But now I thought about what my application really would entail (data processing & calculation) and I think maybe going serverless would be better.

luchillo17 commented 9 months ago

Ok so as far as I understand CommonJS modules cannot import ESM, but ESM can import CommonJS, which is why adding "type": "module" which turns your non-extension defined modules (ts and js) into ESM, which then can properly import @auth/express.

TS has an extensive documentation page about modules and explains the history, issues, and solutions around CommonJS, ESM, and how TS handles both. https://www.typescriptlang.org/docs/handbook/2/modules.html

I'm not sure if the @auth/express is true ESM or coincidentally the solution matches the ESM configuration. Still, the bottom line to fix this is to add "type": "module" to your package.json and fix any build issues that come with transforming your codebase to ESM.

luchillo17 commented 9 months ago

To clarify, what I put above is a workaround, not a proper fix, I see @auth/express has an exports field so I would guess it's following the guidelines for modern libraries to compile to multiple targets, but that it's misconfigured and this issue happens, not really sure...

apeck14 commented 8 months ago

Having the same issue with @auth/mongodb-adapter. I know this was mentioned in another issue, but it's just not accurate. Everything was working fine on the old adapter. I believe it was next-auth/mongodb-adapter?

FlynnHillier commented 7 months ago

I am also experiencing this issue for @auth/drizzle-adapter, setting "type":"module" in package.json is, as mentioned, not an ideal fix as it can cause issues throughout the rest of the app. Has anyone since been able to fix this error by any other means?

Oddadmix commented 7 months ago

@balazsorban44, can you please advise ?

CodeZak commented 6 months ago

anyone found a solution to this ?

Edit by maintainer bot: Comment was automatically minimized because it was considered unhelpful. (If you think this was by mistake, let us know). Please only comment if it adds context to the issue. If you want to express that you have the same problem, use the upvote 👍 on the issue description or subscribe to the issue for updates. Thanks!

ndom91 commented 6 months ago

All @auth/* packages are ESM-only. We realize this may be a bit bigger of an issue with the express package as compared to the other (browser-only) ones.

To fix it, (1) you can of course write your node project with ESM (by adding "type": "module") to your root package.json, or (2) use node@22+ which added support for require(esm) packages (source).

Additionally, these recommendations I haven't personally tried but seen floating around, you could try using the esm package and/or renaming the file in which yuo import @auth/express to .mjs (if you don't have "type": "module" in your package.json).

For more info on esm/cjs in node: https://blog.logrocket.com/how-to-use-ecmascript-modules-with-node-js/

zsilbi commented 6 months ago

I have the same issue and found none of the mentioned workarounds working.

It's an ESM-only project that's running on CF Workers, but my dev server fails to import anything from @auth/core on startup.

 ERROR  No "exports" main defined in node_modules/@auth/core/package.json                   

  at exportsNotFound (node:internal/modules/esm/resolve:294:10)
  at packageExportsResolve (node:internal/modules/esm/resolve:584:13)

Strangely if I add the imports to the project while the dev server is running, it works fine.

The only possible way I found to get it working if I modify the the exports field in node_modules/@auth/core/package.json Adding a default option for each exported entry solves the problem.

"exports": {
    ".": {
      "types": "./index.d.ts",
      "import": "./index.js",
      "default": "./index.js"
    },
    "./adapters": {
      "types": "./adapters.d.ts"
    },
    "./errors": {
      "types": "./errors.d.ts",
      "import": "./errors.js",
      "default": "./errors.js"
    },
    "./jwt": {
      "types": "./jwt.d.ts",
      "import": "./jwt.js",
      "default": "./jwt.js"
    },
    "./providers": {
      "types": "./providers/index.d.ts"
    },
    "./providers/*": {
      "types": "./providers/*.d.ts",
      "import": "./providers/*.js",
      "default": "./providers/*.js"
    },
    "./types": {
      "types": "./types.d.ts"
    }
  },
GeorgeIpsum commented 5 months ago

I have the same issue and found none of the mentioned workarounds working.

It's an ESM-only project that's running on CF Workers, but my dev server fails to import anything from @auth/core on startup.

 ERROR  No "exports" main defined in node_modules/@auth/core/package.json                   

  at exportsNotFound (node:internal/modules/esm/resolve:294:10)
  at packageExportsResolve (node:internal/modules/esm/resolve:584:13)

Strangely if I add the imports to the project while the dev server is running, it works fine.

The only possible way I found to get it working if I modify the the exports field in node_modules/@auth/core/package.json Adding a default option for each exported entry solves the problem.

"exports": {
    ".": {
      "types": "./index.d.ts",
      "import": "./index.js",
      "default": "./index.js"
    },
    "./adapters": {
      "types": "./adapters.d.ts"
    },
    "./errors": {
      "types": "./errors.d.ts",
      "import": "./errors.js",
      "default": "./errors.js"
    },
    "./jwt": {
      "types": "./jwt.d.ts",
      "import": "./jwt.js",
      "default": "./jwt.js"
    },
    "./providers": {
      "types": "./providers/index.d.ts"
    },
    "./providers/*": {
      "types": "./providers/*.d.ts",
      "import": "./providers/*.js",
      "default": "./providers/*.js"
    },
    "./types": {
      "types": "./types.d.ts"
    }
  },

I'm currently using patchfiles to handle this and it works perfectly for me; only gripe is that I have to do it for all @auth/* packages in my workspace.

Would it be possible to add the "default" export key in all exports in the future? Apologies for the naivety, not sure if this isn't currently being done for a specific reason.

ndom91 commented 5 months ago

@GeorgeIpsum @zsilbi thanks for sharing. I think this might be due to some tsconfig or similar setting of yours though because the default configuration does work, for example in our example app (https://express-auth-example.vercel.app)

Can you share your tsconfig.json or any other similar config?

GeorgeIpsum commented 5 months ago

Of course!

My tsconfig.json:

{
  "compilerOptions": {
    "rootDir": ".",
    "baseUrl": ".",
    "paths": {
      "~/*": [
        "./src/*"
      ]
    },
    "outDir": "./dist",
    "target": "es2022",
    "module": "ESNext",
    "lib": ["es2022", "DOM", "DOM.Iterable"],
    "moduleResolution": "Bundler",
    "moduleDetection": "force",
    "noUncheckedIndexedAccess": true,
    "resolveJsonModule": true,
    "allowArbitraryExtensions": true,
    "forceConsistentCasingInFileNames": true,
    "declaration": true,
    "declarationMap": true,
    "esModuleInterop": true,
    "incremental": false,
    "isolatedModules": true,
    "resolveJsonModule": true,
    "skipLibCheck": true,
    "strict": true
  },
  "include": [
    "src",
    "*.d.ts",
    "*.d.ts",
    "*.config.mjs"
  ],
  "exclude": [
    "node_modules",
    "dist",
    "turbo"
  ],
}

Currently running the project with tsx in dev (so it might just be an issue with how esbuild is resolving imports?), haven't actually tried building using tsc with this configuration.

I'm assuming either my "target" or "module" fields here are the problematic entries (haven't tried changing these yet); I have tried changed "moduleResolution" to "Node" to no avail. I'm honestly still very much a newbie when it comes to understanding how to configure tsconfigs; apologies if there's an obvious mistake here that would rectify the issue.