privatenumber / tsx

⚡️ TypeScript Execute | The easiest way to run TypeScript in Node.js
https://tsx.is
MIT License
9.27k stars 141 forks source link

CJS loader to support importing with `import` condition #239

Open felix98765 opened 1 year ago

felix98765 commented 1 year ago

Bug description

What did you do? (Provide reproduction code in next section)

Import a ES module with a main export (https://github.com/nextauthjs/next-auth/blob/b96f01319c751c7d62433c24fdb9f3f8f1e572c1/packages/core/package.json#L36).

What did you expect to happen?

Import successfully.

What happened instead?

An error throwed.

Do you have an error stack-trace or screenshots?

node:internal/errors:490
    ErrorCaptureStackTrace(err);
    ^

Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: No "exports" main defined in /tsx-no-exports-main-defined/node_modules/@auth/core/package.json
    at __node_internal_captureLargerStackTrace (node:internal/errors:490:5)
    at new NodeError (node:internal/errors:399:5)
    at exportsNotFound (node:internal/modules/esm/resolve:261:10)
    at packageExportsResolve (node:internal/modules/esm/resolve:535:13)
    at resolveExports (node:internal/modules/cjs/loader:569:36)
    at Module._findPath (node:internal/modules/cjs/loader:643:31)
    at Module._resolveFilename (node:internal/modules/cjs/loader:1068:27)
    at u.default._resolveFilename (/tsx-no-exports-main-defined/node_modules/@esbuild-kit/cjs-loader/dist/index.js:1:1519)
    at Module._load (node:internal/modules/cjs/loader:928:27)
    at Module.require (node:internal/modules/cjs/loader:1149:19)
    at require (node:internal/modules/helpers:121:18)
    at <anonymous> (/tsx-no-exports-main-defined/index.ts:1:22)
    at Object.<anonymous> (/tsx-no-exports-main-defined/index.ts:4:25)
    at Module._compile (node:internal/modules/cjs/loader:1267:14)
    at Object.F (/tsx-no-exports-main-defined/node_modules/@esbuild-kit/cjs-loader/dist/index.js:1:941)
    at Module.load (node:internal/modules/cjs/loader:1125:32)
    at Module._load (node:internal/modules/cjs/loader:965:12)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:165:29)
    at ModuleJob.run (node:internal/modules/esm/module_job:192:25) {
  code: 'ERR_PACKAGE_PATH_NOT_EXPORTED'
}

Node.js v20.1.0

Reproduction

https://github.com/felix98765/tsx-no-exports-main-defined

Environment

System:
    OS: macOS 13.3.1
    CPU: (8) arm64 Apple M2
    Memory: 448.70 MB / 24.00 GB
    Shell: 3.6.1 - /opt/homebrew/bin/fish
  Binaries:
    Node: 20.1.0 - /opt/homebrew/bin/node
    Yarn: 1.22.19 - /opt/homebrew/bin/yarn
    npm: 9.6.4 - /opt/homebrew/bin/npm
  npmPackages:
    tsx: ^3.12.7 => 3.12.7

Can you work on a fix?

privatenumber commented 1 year ago

This happens because tsx converts the ESM file to CommonJS (since your package has a CommonJS type).

That means your import here:

import { Auth } from '@auth/core'

Is converted to a require, and given to Node.js to resolve:

const { Auth } = require('@auth/core')

Since to Node.js, it's a require(), it's unable to resolve the entry-point because it only supports types and import:

".": {
    "types": "./index.d.ts",
    "import": "./index.js"
},
felix98765 commented 1 year ago

Thanks. Do this mean I can't use ESM dependencies with tsx when my project is itself a CommonJS package?

I ended up rebundling the @auth/core as a CommonJS package.

privatenumber commented 1 year ago

tsx supports loading ESM from CommonJS. Just not the exports map configuration in @auth/core.

privatenumber commented 1 year ago

Leaving this open as a feature request

privatenumber commented 6 months ago

As an example of where something like this might be necessary, some packages are not only supporting the import condition.

For example, @octokit/core: https://github.com/octokit/core.js/blob/9ab61fa16e8350c29af790869abd2028893a5126/scripts/build.mjs#L60-L65

https://unpkg.com/@octokit/core@6.0.1/package.json