-
-
Notifications
You must be signed in to change notification settings - Fork 531
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
feat(register): resolve .js to .ts in ts-node/register #1361
Conversation
776d768
to
9c4b462
Compare
9c4b462
to
1ad76e0
Compare
1ad76e0
to
22a15ba
Compare
Thanks for sending this, I almost forgot to respond. (well, I did forget yesterday) This is a pretty important feature; really glad to support this. I vaguely remember when I was implementing this .js -> .ts mapping for our ESM resolver, there were corner cases that prevented me from taking the approach being used here: try Due to the complexity of node's module resolution algorithm, and the fact that it checks many directories and package.json files, I think there are rare cases where it can actually resolve to a We also have a For the ESM resolver, we ended up copying node's resolver and patching it to do what we needed. We could probably do the same for the CommonJS resolver. For option naming, would the name change if we also added mapping from |
I agree it's an important feature especially right now. This quick implementation is really naive as you mentioned, and solves the problem reliably only when outDir is in a different tree entirely. Lack of outDir, has node potentially finding stale built js.
Do these complexities still exist if we have a relative request with an exact extension?
I'm curious on your thoughts as to whether this behavior should roll up into the
I'm not sure if we should blend/burden commonjs extensions api with the esm loader terminology. |
I tried the other approach here and it seems to do the trick. And I can't immediately think of any corner cases this wouldn't work Still need to do:
|
It feels like the same terminology should be used for both, right? Because we are, indeed, hooking resolution behavior. I'm also thinking this CJS resolve hook can become the default in a future release.
I think this depends on the project. The way I see it, if a This is distinct from our |
Now that I think about it, if the user has |
I've jotted down some funky CJS resolver situations: https://github.com/TypeStrong/ts-node-repros/tree/commonjs-resolver-corner-cases |
Yeah, that makes sense, sgtm. Is there anyway used to determine the scope from active tsconfigs? (isSourceFile?).. Relative specifiers of mono-repo (workspace) packages seems strange to me... Typically those would be linked from node_modules, right? Playing around with the corner cases I ended up here, but definitely need a way to resolve the "virtual file" you're talking about. |
I'm not sure I understand this question. Is this referring specifically to the |
@cspotcode I wasn't familiar with those options. I'm more curious if we can determine if a resolved filename is a sourcefile. But even that might be too in the weeds... I think the problem that needs solving could be reduced to "do what tsc does", which in this case, it treats relative imports of I think until typescript supports more complicated resolutions via exports, it probably doesn't need to be more complicated than that? But I'll defer to your judgement. |
The Sometimes Perhaps the trickiest thing for now is: when In that scenario, I think if we can get that, we should be in a pretty good place. |
f88eb40
to
dd9044b
Compare
dd9044b
to
5135aeb
Compare
This fixes two problems with the ESM build of this module. 1. The `package.json` that contains `{ "type": "module" }` wasn't being included in the npm tarball 2. When running in an ESM environment, `import foo from './bar'` does not work, you have to specify the extension The fix for the first is simple, add the cjs/esm `package.json` files to the `files` array in the project `package.json`. The second fix is harder. If you just add the `.js` extension to the source files, typescript is happy but ts-node is not, and this project uses ts-node to run the tests without a compile step. Typescript does not support importing `*.ts` and will not support adding `*.js` to the transpiled output - microsoft/TypeScript#16577 ts-node thought this was a bug in Typescript but it turns out not. Their suggestion to use `ts-node/esm` breaks sourcemap support because `source-map-support/register` is not esm - TypeStrong/ts-node#783 There is a PR against ts-node to add support for resolving `./foo.js` if `./foo.ts` or `./foo` fails but it seems to have stalled - TypeStrong/ts-node#1361 Given all of the above, the most expedient way forward seemed to just be to add a shell script that rewrites the various `import` statements in the esm output to add the `.js` extension, then if the ts-node PR ever gets merged the script can be backed out. Fixes beaugunderson#147
Applying this patch locally seems to work well enough that I can use ts-node to run tests with mocha without needing an explicit compilation step (yay!) along with source maps and correct stack traces etc. This makes ts much easier to work with, is there any chance this could get merged? |
Unfortunately, while this does work, (I also use this branch) I think the full solution will need to account for all the scenarios outlined in the epic #1514. A concise and pragmatic solution for that isn't straight forward. |
5135aeb
to
1e82e3c
Compare
I'm revisiting this. Although a complete resolver is still ideal, and I want to get there eventually, I also want to fix the simpler issue of mapping I'm thinking I'll keep it behind an Merging this in some form will unblock #1564. Will also need to update it to handle .cjs and .mjs from #1564. And will need to be merged with the path-mapping hook from #1585. |
I completely understand 😅 . I'll see if I can get this updated in the near future to account for the things you mentioned + tests. |
Much appreciated, usually when I leave a PR stuck in review for this long, the author abandons me. Can't say I blame them either. :) I made some code changes locally, mostly replacing the I also spent some time last night revisiting the "complete resolver" idea so I would have a better idea of the path forward, beyond this PR. The problem isn't how to do the mappings, the question is when. I think "when" is determined both by the parent's location and the resolved target's location. (In a monorepo, if a non-TS package tries to |
98fb61a
to
b630c75
Compare
I have finally (!) implemented a complete commonjs resolver that can do these file extension re-mappings: #1727 This is happening alongside #1694, which adds full support for the new node support, with cts, mts, cjs, mjs extensions. Hoping to get this all released ahead of TS 4.7.0. Thanks again for sending this PR; closing it as I ended up going another route, but I appreciate it all the same. |
Fixes #783
Makes
A
work #783 (comment)Adds an entrypoint
ts-node/register/try-ts-ext
That applies a patch to attempt resolution of a ts file when a js file returns MODULE_NOT_FOUNDReasoning:
Ran into this when trying to do dual mode modules, that is developing with tooling set to commonjs, and shipping both esm and commonjs.