Closed acolytec3 closed 1 year ago
tape only resolves paths when passed on the command line; node is doing the execution and resolution of require and import.
(type module is bad anyways; ESM files should be .mjs, not .js, and unless you have zero deps, your code will require a bundler anyways, so it's probably not a good idea to optimize for that)
Are you saying that tape -r ts-node/register -- './path/to/my/test.spec.ts'
used to work, and now doesn't? Can you elaborate on how it fails?
The best way to recreate it would be to clone our monorepo and then navigate to [repo root directory]/packages/common
and run npm run test
(which uses tape -r ts-node/register
to run all the tests for one of our packages) on the master branch and then on the add-file-extensions
branch.
It produces output like below on the branch:
Error: Cannot find module './eips/index.js'
Require stack:
- /home/jim/development/ethjs/packages/common/src/common.ts
- /home/jim/development/ethjs/packages/common/test/chains.spec.ts
- /home/jim/development/ethjs/node_modules/tape/bin/import-or-require.js
- /home/jim/development/ethjs/node_modules/tape/bin/tape
at Function.Module._resolveFilename (node:internal/modules/cjs/loader:956:15)
at Function.Module._resolveFilename.sharedData.moduleResolveFilenameHook.installedValue [as _resolveFilename] (/home/jim/development/ethjs/node_modules/@cspotcode/source-map-support/source-map-support.js:811:30)
at Function.Module._load (node:internal/modules/cjs/loader:804:27)
at Module.require (node:internal/modules/cjs/loader:1022:19)
at require (node:internal/modules/cjs/helpers:102:18)
at Object.<anonymous> (/home/jim/development/ethjs/packages/common/src/common.ts:17:1)
at Module._compile (node:internal/modules/cjs/loader:1120:14)
at Module.m._compile (/home/jim/development/ethjs/node_modules/ts-node/src/index.ts:1618:23)
at Module._extensions..js (node:internal/modules/cjs/loader:1174:10)
at Object.require.extensions.<computed> [as .ts] (/home/jim/development/ethjs/node_modules/ts-node/src/index.ts:1621:12) {
code: 'MODULE_NOT_FOUND',
requireStack: [
'/home/jim/development/ethjs/packages/common/src/common.ts',
'/home/jim/development/ethjs/packages/common/test/chains.spec.ts',
'/home/jim/development/ethjs/node_modules/tape/bin/import-or-require.js',
'/home/jim/development/ethjs/node_modules/tape/bin/tape'
]
}
That error is coming from /home/jim/development/ethjs/packages/common/src/common.ts
, though, not from tape.
I think the issue is that in order for ts-node/register to work, it has to be evaluated before any file that consumes .ts
files runs - however, tape's binary does its -r
requires, and its file evaluations, in the same file. However, bin/tape
does things quite intentionally in an unidiomatic order specifically to account for this use case.
Thanks for the repro tips, I'll see what I can do.
On both branches, i get Error: Cannot find module 'ts-node/register' from '$PWD/ethereumjs-monorepo/packages/common'
. Should ts-node be a dev dep in that directory's package.json?
(when i npm install --no-save ts-node
, then i get a TS type error on both branches - is @types/tape
installed as a dev dep?)
Ah, sorry, you do npm i
from the monorepo root and that installs ts-node as a general dev dependency. If you then go to packages/common
, you'll see the error on that branch. You get similar errors with some of the other packages. But, if you run npm run test:browser
from packages/common
, the tests pass just fine.
ok, so the error I get is:
Error: Cannot find module './eips/index.js'
Require stack:
- $PWD/packages/common/src/common.ts
- $PWD/packages/common/test/chains.spec.ts
…
and $PWD/packages/common/src/eips/index.ts
is the file that exists, not .js
. Note that I get the same failure sooner if i update $PWD/packages/common/test/chains/index.ts
so that import { Common } from '../src/common'
becomes import { Common } from '../src/common.js'
.
Given that ts-node/register
is the package that's supposed to be resolving those, I suspect it's related to the rapidly evolving handling for native ESM in ts-node itself combined with TS.
Have you tried filing an issue on ts-node?
Yep, that's the same as I get. Thanks for looking into it. I hadn't considered ts-node
as a culprit but that makes sense given above. Will close here for now.
type module is bad anyways
@ljharb Can you elaborate your thoughts on this? I am on the outside, looking in on the JS ecosystem's painful move to ESM, and its hard to get an understanding of what is really going on.
I assumed "type"
within package.json
was to ease the migration of CJS projects to ESM by eliminating another pain point (renaming file extensions).
That doesn’t eliminate a pain point, it adds a new one - because instead of renaming file extensions, all your tools have to change their parse goal for “.js”.
First off, our monorepo has very successfully used
tape
as our test runner for many years so thanks for your continued work on it!My question is related to how
tape
resolves internal imports. Our monorepo is Typescript bases and runs ourtape
tests viats-node
using commands liketape -r ts-node/register -- './path/to/my/test.spec.ts'
and we are currently in the process of updating our code to output both CJS and ESM builds. In an attempt to ensure our code can run natively in browser without requiring a bundler, we're adding file extensions (i.e..js
) to all of the internal imports within our codebase. In doing so, tape suddenly is no longer able to resolve any of these paths when we run the tests. Oddly enough, when we run the web version of our tests usingkarma-typescript
to first bundle up the code, tape runs them just fine (presumably because karma bundles everything up first).Our default build process is still using CJS so there is no
"type": "module"
in our source code (this gets added to the ESM output from Typescript in a post build step) so I'm assuming theimport-or-require
module is somehow unsure of how to resolve an import in CJS that looks likeimport * from '../src/index.js'
but I'm not sure why this is the case whenimport * from '../src'
works just fine.Do you have any instincts on what is going wrong here?