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

node_modules are not ignored when providing a project path that is in node_modules. #1477

Closed
dylang opened this issue Sep 28, 2021 · 9 comments

Comments

@dylang
Copy link

dylang commented Sep 28, 2021

Search Terms

  • node_modules
  • baseDir
  • ignoreBaseDir
  • Accessing non-existent property 'getOptionValue' of module exports inside circular dependency

Expected Behavior

  • I'd like to provide the tsconfig.json that ts-node uses, and not worry about conflicts with the tsconfig.json that the projects use that use my code.
  • Therefor I'm bundling a tsconfig.json with my project, which is installed in other projects. This means the tsconfig.json used is in node_modules.

Actual Behavior

  • All code in node_modules is compiled.
  • This error from compiling ts-node with ts-node:
 ⚠  warning (Warning)  Accessing non-existent property 'getOptionValue' of module exports inside circular dependency
    at emitCircularRequireWarning (internal/modules/cjs/loader.js:650:11)
    at Object.get (internal/modules/cjs/loader.js:664:5)
    at Object.read (/project/node_modules/ts-node/dist-raw/node-package-json-reader.js:26:11)
    at readPackage (/project/node_modules/ts-node/dist-raw/node-cjs-loader-utils.js:63:36)
    at readPackageScope (/project/node_modules/ts-node/dist-raw/node-cjs-loader-utils.js:44:19)
    at assertScriptCanLoadAsCJSImpl (/project/node_modules/ts-node/dist-raw/node-cjs-loader-utils.js:20:15)
    at Object.require.extensions.<computed> [as .js] (/project/node_modules/ts-node/src/index.ts:1302:5)
    at Module.load (internal/modules/cjs/loader.js:928:32)
    at Function.Module._load (internal/modules/cjs/loader.js:769:14)
    at Module.require (internal/modules/cjs/loader.js:952:19)

It appears to be caused by prioritizing the configFileDirname over the cwd or any provided directory via configuration:

https://github.com/TypeStrong/ts-node/blob/master/src/index.ts#L629-L643

const ignoreBaseDir = configFileDirname ?? cwd;
...
const shouldIgnore = createIgnore(
  ignoreBaseDir,

createIgnore uses path.Relative, so all paths in node_modules end relative to another directory in node_modules as ../../module and do not contain the string node_modules so they are not ignored.

https://github.com/TypeStrong/ts-node/blob/master/src/index.ts#L1332-L1338

Steps to reproduce the problem

require('ts-node').register({
  pretty: true,
  transpileOnly: true,
  project: require.resolve('./tsconfig.ts-node.json')
});

./tsconfig.ts-node.json:

{
  "$schema": "https://json.schemastore.org/tsconfig",
  "display": "@tsconfig/node14, plus allowJs so Js files can use esm-style imports/exports",

  "compilerOptions": {
	"allowJs": true,

    "lib": ["es2020"],
    "module": "commonjs",
    "target": "es2020",

    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}

Minimal reproduction

I understand why a reproduction is necessary but I'm not sure best way to do it as it requires the code to be in node_modules and I prefer avoiding publishing a new module for this issue.

Maybe there's an online REPL that supports file:// for module versions to install local modules?

Specifications

  • ts-node v10.2.1
  • node v14.15.4
  • compiler v4.4.3
  • tsconfig.json, if you're using one:
{
  "$schema": "https://json.schemastore.org/tsconfig",
  "display": "@tsconfig/node14, plus allowJs so Js files can use esm-style imports/exports",

  "compilerOptions": {
	"allowJs": true,

    "lib": ["es2020"],
    "module": "commonjs",
    "target": "es2020",

    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}
  • Operating system and version: MacOS 11.4
  • If Windows, are you using WSL or WSL2?:
@cspotcode
Copy link
Collaborator

I understand why a reproduction is necessary but I'm not sure best way to do it as it requires the code to be in node_modules and I prefer avoiding publishing a new module for this issue.

You can commit a node_modules directory to git to achieve the same effect; it does not need to be created by npm. Alternatively, npm can install directly from git or from a tarball.
https://docs.npmjs.com/cli/v7/commands/npm-install
If you go the tarball approach, you can create the tarball via npm pack and then commit the tarball directly to git. Feel free to use whatever approach makes the clearest, most minimal reproduction and is easiest for you. It's a reproduction so it doesn't need to follow any best-practices; it just needs to be as small and clear as possible, eliminating as many variables as possible.


At first glance, I thought this was the same as #1341 but I'm not sure.

@cspotcode
Copy link
Collaborator

You're using an older version of ts-node; is that intentional?

@dylang
Copy link
Author

dylang commented Sep 28, 2021

oops, fixed the version of ts-node, thanks for noticing that @cspotcode.

@cspotcode
Copy link
Collaborator

No problem, let me know when you have a reproduction and I'll take a look.

@dylang
Copy link
Author

dylang commented Oct 6, 2021

@cspotcode
Copy link
Collaborator

cspotcode commented Oct 7, 2021

@dylang
Thanks! This is helpful.

The warning appears to be an unrelated bug, so it's great that you've reported it, but I wonder if it's related to your node_modules problem or not. I've created a separate issue to track the warning bug: #1488

For your node_modules issue, I'm curious, have you used these tsconfig.json files with tsc? When I try tsc --showConfig I get:

$ tsc --showConfig --project ./node_modules/@dylang/tsconfig/node14/tsconfig.json
error TS18003: No inputs were found in config file '/d/Personal-dev/@TypeStrong/ts-node/repro-1477/node_modules/@dylang/tsconfig/node14/tsconfig.json'. Specified 'include' paths were '["**/*"]' and 'exclude' paths were '[]'.

I'm not sure if tsconfig files are meant to be used this way. I realize you're using ts-node, not tsc, but we still have to match tsc config behavior pretty closely.

I'll have to double-check the code, but this behavior may be intentional. That is to say, your chosen tsconfig determines the "root directory" of your project and we set other options like scopeDir relative to that. You might have luck setting a custom scopeDir or ignore option?

That's all the time I have for today but I can come back to this soon.

@cspotcode
Copy link
Collaborator

I updated your reproduction with a workaround for #1488 and some ignore ideas.
https://stackblitz.com/edit/ts-node-project-in-node-modules-mjkuag?file=index.js

I see our docs say ignore is intentionally evaluated relative to the tsconfig directory. I'd have to check commit and issue history, but I'm guessing this is done so that ignore patterns don't need to care about whatever craziness might be in the parent path. This is similar to how tsconfig include and exclude paths are always relative to the tsconfig file.
https://typestrong.org/ts-node/api/interfaces/CreateOptions.html#ignore

@dylang
Copy link
Author

dylang commented Oct 8, 2021

I think I found a clean workaround to my problem:

    require('ts-node').register({
        pretty: true,
        transpileOnly: true,
        // Use allowJs so that we can run js files that have esm-style import/export.
        compilerOptions: { allowJs: true, rootDir: getRepoPath() },
        // By not providing a tsconfig.json, ts-node will use the best choice for the version of node in use.
        // And we can still provide our own using TS_NODE_PROJECT=<path to tsconfig.json>.
        skipProject: !process.env.TS_NODE_PROJECT
    });

I didn't realize we had the ability to override allowJs and rootDir from .register()! 😄

getRepoPath is needed because this is for use in monorepos so we can't use the cwd or package.json/tsconfig.json path.

@cspotcode
Copy link
Collaborator

Closing. To summarize:

We established that pointing --project to a tsconfig.json in node_modules is incompatible with vanilla tsc. The correct usage is to create a project-local tsconfig and "extends" the config from node_modules.

Also, it conflicts with intended npx support in ts-node. If your tsconfig is within a node_modules directory, then we reason that your project is within node_modules and that we should transform files there.

We fixed the getOptionValue error in #1488

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