Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow import of directories with index.ts and import of files without extension #1198

Closed
Fuzzyma opened this issue Jan 18, 2021 · 9 comments
Closed

Comments

@Fuzzyma
Copy link

Fuzzyma commented Jan 18, 2021

Desired Behavior

This should work

import {a, b, c} from './alphabet' // same as '/alphabet/index.{ts,js,mjs,cjs}'
import {a} from './alphabet/a' // same as '/alphabet/a.{ts,js,mjs,cjs}'

Is this request related to a problem?

I am using ts-node together with vite. Vite natively supports typescript and imports as requested.
I would like to share code on both client and server but the client side code uses directory imports and imports without file extension. So it wont run.

Alternatives you've considered

I tried to use --experimental-specifier-resolution=node but it doenst seem to work together with a loader (which makes sense).

If someone has a quickfix for me, that would also do the trick for now

@cspotcode
Copy link
Collaborator

cspotcode commented Jan 18, 2021

--experimental-specifier-resolution=node should, in fact, work with our --loader ts-node/esm. See also: #1122 and #1010

I see you omitted some of the information we request in our issue template. Any reason for this? That information is necessary to reproduce what you're seeing.

@cspotcode
Copy link
Collaborator

cspotcode commented Jan 18, 2021

I'm so accustomed to people omitting information from the bug report template, that I forgot you're using the "feature request" template instead. My apologies; responding to lots of low-effort bug reports tends to wear on a person over time.

But anyway, yes this should work. Can you share the exact node, ts-node, and typescript versions you're using, as well as the exact command you're using to invoke ts-node? Are you able to reproduce the issue using ts-node without vite, or does it only occur with vite in the mix? All of this will help figure out what's going on here.

@Fuzzyma
Copy link
Author

Fuzzyma commented Jan 18, 2021

Sure, here are the information:

node@14.13.0
ts-node@9.1.1
typescript@4.1.3

I am invoking it like this: node --loader ts-node/esm server/index.ts and I get this error:

> node --loader ts-node/esm server/index.ts

(node:3912) ExperimentalWarning: --experimental-loader is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)

D:\Repositories\canvas\node_modules\ts-node\dist-raw\node-esm-resolve-implementation.js:374
    throw new ERR_MODULE_NOT_FOUND(
          ^
Error: ERR_MODULE_NOT_FOUND D:\Repositories\canvas\src\models\User D:\Repositories\canvas\server\websocket.ts module
    at finalizeResolution (D:\Repositories\canvas\node_modules\ts-node\dist-raw\node-esm-resolve-implementation.js:374:11)
    at moduleResolve (D:\Repositories\canvas\node_modules\ts-node\dist-raw\node-esm-resolve-implementation.js:809:10)
    at Object.defaultResolve (D:\Repositories\canvas\node_modules\ts-node\dist-raw\node-esm-resolve-implementation.js:920:11)
    at D:\Repositories\canvas\node_modules\ts-node\src\esm.ts:55:38
    at Generator.next (<anonymous>)
    at D:\Repositories\canvas\node_modules\ts-node\dist\esm.js:8:71
    at new Promise (<anonymous>)
    at __awaiter (D:\Repositories\canvas\node_modules\ts-node\dist\esm.js:4:12)
    at resolve (D:\Repositories\canvas\node_modules\ts-node\dist\esm.js:31:16)
    at Loader.resolve (internal/modules/esm/loader.js:85:40)

I tried adding the flag:

> node --loader ts-node/esm server/index.ts --experimental-specifier-resolution=node

(node:17220) ExperimentalWarning: --experimental-loader is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)

D:\Repositories\canvas\node_modules\ts-node\dist-raw\node-esm-resolve-implementation.js:374
    throw new ERR_MODULE_NOT_FOUND(

Other way round:

> node --experimental-specifier-resolution=node --loader ts-node/esm server/index.ts

(node:10312) ExperimentalWarning: --experimental-loader is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
Error: Unexpected import statement in CJS module.
  at @:1:8
    at throwIfImportStatement (internal/deps/cjs-module-lexer/lexer.js:882:13)
    at parseSource (internal/deps/cjs-module-lexer/lexer.js:83:13)
    at parseCJS (internal/deps/cjs-module-lexer/lexer.js:38:5)
    at cjsPreparseModuleExports (internal/modules/esm/translators.js:193:34)
    at Loader.commonjsStrategy (internal/modules/esm/translators.js:143:35)
    at new ModuleJob (internal/modules/esm/module_job.js:38:41)
    at Loader.getModuleJob (internal/modules/esm/loader.js:245:11)
    at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:53:21)
    at async Promise.all (index 5)
    at link (internal/modules/esm/module_job.js:58:9)

I am not using it together with vite in that sense. I just proxy a few requests to the server but the server wouldnt even start.

@Fuzzyma
Copy link
Author

Fuzzyma commented Jan 18, 2021

This is the version where I removed all direct directory imports in the server file. However, imported files still use the syntax.
When I had directory imports in the server file itself I got a different error (without the flag) which was a ERR_UNSUPPORTED_DIR_IMPORT. However, with the flag, the error is the same as the last one

@cspotcode
Copy link
Collaborator

Thanks, this information makes it easy to point out the proper solution.

As you probably know from node's documentation, --experimental-specifier-resolution=node is necessary. You may not know that node only parses node flags when they come before the entrypoint script. Anything after is passed to the script. For example, node ./index.js --gc will not enable node's garbage collector API; it will simply put --gc into process.argv.

The correct invocation is node --experimental-specifier-resolution=node --loader ts-node/esm server/index.ts

The error you're getting:

Error: Unexpected import statement in CJS module.

...happens because node is trying to execute the file as CJS instead of ESM. Node has its own rules for when it decides to run a file as ESM and when as CJS. It will either use file extension or package.json. In our case, because we're using the TypeScript compiler which has not implemented any sort of .cjs / .mjs features, we rely on telling node how to behave via package.json.

Documentation is here:
https://nodejs.org/dist/latest-v15.x/docs/api/esm.html#esm_enabling

Once you tell node to execute your files as ESM, this should work.

@Fuzzyma
Copy link
Author

Fuzzyma commented Jan 18, 2021

@cspotcode adding the module type to the package.json is one of the first things I did. Omitting it leads to the same error when the flag is omitted, too. However, adding it, leads to error no1 while adding the flag gives us back error no3.

So even with type: module it handles some module as cjs

PS: didnt know the node parameter thing yet. Thanks for that!

@cspotcode
Copy link
Collaborator

Could be that another package.json exists and does not have the necessary flag, causing node to load certain files as CJS.

Here is a reproduction showing that this feature does work as intended.
https://github.com/TypeStrong/ts-node-repros/tree/experimental-specifier-resolution-node
https://github.com/TypeStrong/ts-node-repros/runs/1724259280

If you're able to modify that reproduction to demonstrate the issue, then we can investigate further. Modifying the reproduction means forking and submitting a pull request to ts-node-repros, which will be executed by Github Actions.

@Fuzzyma
Copy link
Author

Fuzzyma commented Jan 18, 2021

Omg, I finally found the issue. I was importing a ts module whose package.json did not have the type correctly set. It works now - well it errors - but it works. Thank you very much for pointing me in the right direction!

@Fuzzyma Fuzzyma closed this as completed Jan 18, 2021
@cspotcode
Copy link
Collaborator

cspotcode commented Jan 18, 2021 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants