Unable to convert from TSLint to ESLint with tslint-to-eslint-config 2.7.0
mkurte opened this issue · 34 comments
Hi guys,
in this issue I described that I am not able to run the command to migrate from tslint to eslint.
When I type ng g @angular-eslint/schematics:convert-tslint-to-eslint PROJECTNAME and check the defaults I get this error:
There was a critical error when trying to inspect your tslint.json:
env: node: No such file or directory
I'm running this command on a mac, in a multiple projects workspace.
My project is in the root folder, the tslint.json file too. Is there something I am missing?
If I type npx tslint --print-config {PATH_TO_YOUR_TSLINT_JSON_HERE} as suggested I get a new tslint.json config, but that one doesn't work too.
Many thanks in advance,
Matthias
My tslint.json looks like this:
{
"rulesDirectory": [
"node_modules/codelyzer",
"node_modules/rxjs-tslint"
],
"rules": {
"callable-types": true,
"class-name": true,
"comment-format": [
true,
"check-space"
],
"curly": true,
"deprecation": {
"severity": "warning"
},
"eofline": true,
"forin": true,
"import-blacklist": [],
"import-spacing": true,
"indent": [
true,
"spaces"
],
"interface-over-type-literal": true,
"label-position": true,
"max-line-length": [
true,
160
],
"member-access": false,
"member-ordering": [
true,
{
"order": [
"public-static-field",
"public-instance-field",
"private-static-field",
"private-instance-field",
"constructor",
"public-static-method",
"public-instance-method",
"private-static-method",
"private-instance-method"
]
}
],
"no-arg": true,
"no-bitwise": true,
"no-console": true,
"no-construct": true,
"no-debugger": true,
"no-duplicate-variable": true,
"no-empty": false,
"no-empty-interface": true,
"no-eval": true,
"no-inferrable-types": [true, "ignore-params", "ignore-properties"],
"no-shadowed-variable": true,
"no-string-literal": false,
"no-string-throw": true,
"no-switch-case-fall-through": true,
"no-trailing-whitespace": true,
"no-unused-expression": true,
"no-var-keyword": true,
"object-literal-sort-keys": false,
"one-line": [
true,
"check-open-brace",
"check-catch",
"check-else",
"check-whitespace"
],
"prefer-const": true,
"quotemark": [
true,
"single"
],
"radix": true,
"semicolon": [
true,
"always"
],
"triple-equals": [
true,
"allow-null-check"
],
"typedef-whitespace": [
true,
{
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace"
}
],
"unified-signatures": true,
"variable-name": false,
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type"
],
"directive-selector": [true, "attribute", "p1", "camelCase"],
"component-selector": [true, "element", "p1", "kebab-case"],
"no-inputs-metadata-property": true,
"no-outputs-metadata-property": true,
"no-host-metadata-property": true,
"no-input-rename": true,
"no-output-rename": true,
"use-lifecycle-interface": true,
"use-pipe-transform-interface": true,
"component-class-suffix": true,
"directive-class-suffix": true,
"rxjs-collapse-imports": true,
"rxjs-pipeable-operators-only": true,
"rxjs-no-static-observable-methods": true,
"rxjs-proper-imports": true
}
}
Update: Even if I create a new app with Angular CLI 11 I get the same error:
ng new my-app
cd my-app
ng add @angular-eslint/schematics
ng g @angular-eslint/schematics:convert-tslint-to-eslint --defaultsResult:
INFO: We are now installing the "tslint-to-eslint-config" package into a tmp directory to aid with the conversion
This may take a minute or two...
There was a critical error when trying to inspect your tslint.json:
env: node: No such file or directory@mkurte are you replacing the part which says to put the path to your actual tslint.json i.e. the placeholder {PATH_TO_YOUR_TSLINT_JSON_HERE} - it's not clear from your description.
E.g. if your tslint.json were in the current directory you would run
npx tslint --print-config ./tslint.jsonI am in the directory where my tslint.json lives and enter the command
ng g @angular-eslint/schematics:convert-tslint-to-eslint projectname
That leads to the error.
If I type npx tslint --print-config ./tslint.json I get
{
"extends": [],
"jsRules": {},
"linterOptions": {},
"rules": {
"callable-types": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"class-name": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"comment-format": {
"ruleArguments": [
"check-space"
],
"ruleSeverity": "error"
},
"curly": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"deprecation": {
"ruleSeverity": "warning"
},
"eofline": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"forin": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"import-blacklist": {
"ruleSeverity": "error"
},
"import-spacing": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"indent": {
"ruleArguments": [
"spaces"
],
"ruleSeverity": "error"
},
"interface-over-type-literal": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"label-position": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"max-line-length": {
"ruleArguments": [
160
],
"ruleSeverity": "error"
},
"member-access": {
"ruleArguments": [],
"ruleSeverity": "off"
},
"member-ordering": {
"ruleArguments": [
{
"order": [
"public-static-field",
"public-instance-field",
"private-static-field",
"private-instance-field",
"constructor",
"public-static-method",
"public-instance-method",
"private-static-method",
"private-instance-method"
]
}
],
"ruleSeverity": "error"
},
"no-arg": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"no-bitwise": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"no-console": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"no-construct": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"no-debugger": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"no-duplicate-variable": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"no-empty": {
"ruleArguments": [],
"ruleSeverity": "off"
},
"no-empty-interface": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"no-eval": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"no-inferrable-types": {
"ruleArguments": [
"ignore-params",
"ignore-properties"
],
"ruleSeverity": "error"
},
"no-shadowed-variable": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"no-string-literal": {
"ruleArguments": [],
"ruleSeverity": "off"
},
"no-string-throw": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"no-switch-case-fall-through": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"no-trailing-whitespace": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"no-unused-expression": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"no-var-keyword": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"object-literal-sort-keys": {
"ruleArguments": [],
"ruleSeverity": "off"
},
"one-line": {
"ruleArguments": [
"check-open-brace",
"check-catch",
"check-else",
"check-whitespace"
],
"ruleSeverity": "error"
},
"prefer-const": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"quotemark": {
"ruleArguments": [
"single"
],
"ruleSeverity": "error"
},
"radix": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"semicolon": {
"ruleArguments": [
"always"
],
"ruleSeverity": "error"
},
"triple-equals": {
"ruleArguments": [
"allow-null-check"
],
"ruleSeverity": "error"
},
"typedef-whitespace": {
"ruleArguments": [
{
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace"
}
],
"ruleSeverity": "error"
},
"unified-signatures": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"variable-name": {
"ruleArguments": [],
"ruleSeverity": "off"
},
"whitespace": {
"ruleArguments": [
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type"
],
"ruleSeverity": "error"
},
"directive-selector": {
"ruleArguments": [
"attribute",
"p1",
"camelCase"
],
"ruleSeverity": "error"
},
"component-selector": {
"ruleArguments": [
"element",
"p1",
"kebab-case"
],
"ruleSeverity": "error"
},
"no-inputs-metadata-property": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"no-outputs-metadata-property": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"no-host-metadata-property": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"no-input-rename": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"no-output-rename": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"use-lifecycle-interface": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"use-pipe-transform-interface": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"component-class-suffix": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"directive-class-suffix": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"rxjs-collapse-imports": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"rxjs-pipeable-operators-only": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"rxjs-no-static-observable-methods": {
"ruleArguments": [],
"ruleSeverity": "error"
},
"rxjs-proper-imports": {
"ruleArguments": [],
"ruleSeverity": "error"
}
},
"rulesDirectory": [
"/Users/matthiaskurte/src/planone/frontend/app/node_modules/codelyzer",
"/Users/matthiaskurte/src/planone/frontend/app/node_modules/rxjs-tslint"
]
}
This is my directory structure:
.
├── README.md
├── angular.json
├── karma.global.conf.js
├── ngsw-config.json
├── package-lock.json
├── package.json
├── projects
│ └── libs
├── run-tests.sh
├── server.ts
├── src
│ ├── app
│ ├── assets
│ ├── environments
│ ├── i18n
│ ├── index.html
│ ├── karma.conf.js
│ ├── main.server.ts
│ ├── main.ts
│ ├── polyfills.ts
│ ├── styles
│ ├── test.ts
│ ├── tsconfig.app.json
│ ├── tsconfig.server.json
│ ├── tsconfig.spec.json
│ └── typings.d.ts
├── tsconfig.e2e.json
├── tsconfig.json
├── tsconfig.spec.json
├── tslint.json
├── typedoc.json
└── webpack.server.config.js
Thanks @mkurte that's useful.
What happens if you run:
node --versionand
npm --version?
After a quick search env: node: No such file or directory seems to be coming up for folks (unrelated to angular-eslint) who have unusual/malformed nodejs installations, so the above might give us a clue on that...
I use nvm and have currently installed:
node -v
v12.18.0
npm -v
7.16.0
I have the same problem with a project containing several applications
Update: I have the impression that the problem is with the package tslint-to-eslint-config with the last version (not working with 2.7.0, working with 2.6.0)
@KyDenZ Yep, thanks a lot. Converting a tslint.json file to .eslintrs.js with tslint-to-eslint-config@2.6.0 works for me too. Should we close that issue here?
My quick fix was to manually install tslint-to-eslint-config in version 2.6.0 as a dev dependency, migrate and then uninstall it again:
ng add @angular-elements/schematics
npm install --save-dev tslint-to-eslint-config@2.6.0
ng g @angular-eslint/schematics:convert-tslint-to-eslint myproject
npm uninstall --save-dev tslint-to-eslint-config
Yes we can do like that! Thank you
Thanks for looking into this more and reporting it on typescript-eslint/tslint-to-eslint-config#1159
I was mightily confused why 3 separate people were suddenly reporting installation related issues on the same day, but an issue/change in tslint-to-eslint-config explains that.
I'll wait to hear back from Josh on this before changing anything about angular-eslint, and direct people here in the meantime if anyone else runs into it
Hi folks, sorry for the breakage! 😰
I don't know why tslint-to-eslint-config@2.7.0 would suddenly break things. There are exactly two changes in it that could impact file reading in ng:
For now, I've released a 2.9.0 that reverts those two suspicious changes.
So that we can add back those features, is there a self-contained reproduction someone can post here for me to use locally? I'm not totally familiar with ng schematics, but going forward I'd like to add some kind of testing to tslint-to-eslint-config to make sure we don't break angular-eslint again.
Edit:
env: node No such file or directory
This makes me suspect typescript-eslint/tslint-to-eslint-config#1152 a bit more. FYI @AdamTReineke
Thanks so much @JoshuaKGoldberg!
@mkurte @KyDenZ @gs-scooter would you mind trying the conversion again without any workarounds to verify 2.9.0 is behaving as 2.6.0 used to?
@JoshuaKGoldberg the relevant bits of usage are that we dynamically install tslint-to-eslint-config into a tmp dir only when the user actually needs conversion:
(The version is based on the devDeps version we use:
- I didn't pin it to avoid the need for angular-eslint to update every time there are improvements in tslint-to-eslint-config)This allows us to avoid tslint ending up in people's node_modules (and the associated install warnings).
We then leverage the tslint that it brought in after installing it: https://github.com/angular-eslint/angular-eslint/blob/master/packages/schematics/src/convert-tslint-to-eslint/convert-to-eslint-config.ts#L75
...in order to use the node API of tslint-to-eslint-config
@JamesHenry I removed the package from my project, and reinstalled it, it works fine again
Thanks !
Same here - works like a charm! Thanks a lot for the quick fix!
Thanks for confirming @KyDenZ @mkurte please could I ask a favour in helping Josh and I get to the bottom of this?
Please code you create a simple js file (e.g. repro.js) with the following contents and then run it
repro.js
const { dirSync } = require(‘tmp’);
const { execSync } = require(‘child_process’);
const tempDir = dirSync().name;
execSync(`npm i -D tslint-to-eslint-config@2.7.0`, {
cwd: tempDir,
stdio: ‘ignore’,
});
console.log(
require(require.resolve(‘tslint-to-eslint-config’, {
paths: [tempDir],
}))
);
node ./repro.jsDo you get a similar error to when you ran the angular-eslint schematic?
@mkurte @KyDenZ @gs-scooter would you mind trying the conversion again without any workarounds to verify 2.9.0 is behaving as 2.6.0 used to?
@JamesHenry - I can confirm that the conversion works as expected - Thanks!
@JamesHenry The normal way with only adding schematics and then converting works now as expected.
@mkurte Yes understood, but that's only because Josh reverted the recent changes - this isn't really a true solution. So we were hoping you could help us troubleshoot further by ignoring the schematics and running the snippet outlined above: #571 (comment)
If it fails in the same way that you were seeing via the schematics previously then we know there is something about your environment and the changes that went into v2.7.0 of tslint-to-eslint-config that do not mix.
Please could you give it a try?
Calling the above script gives me following output:
/Users/matthiaskurte/Desktop/test/repro.js:1
const { dirSync } = require(‘tmp’);
SyntaxError: Invalid or unexpected token
at wrapSafe (internal/modules/cjs/loader.js:1054:16)
at Module._compile (internal/modules/cjs/loader.js:1102:27)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10)
at Module.load (internal/modules/cjs/loader.js:986:32)
at Function.Module._load (internal/modules/cjs/loader.js:879:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
at internal/main/run_main_module.js:17:47
@mkurte those don’t look like single quotes in your string there, is that just a GitHub rendering issue or have you somehow ended up with a different Unicode character in there?
@JamesHenry the snippet you pasted has the odd quotes 😛. Here's a version with them fixed:
repro.js
const { dirSync } = require('tmp');
const { execSync } = require('child_process');
const tempDir = dirSync().name;
execSync(`npm i -D tslint-to-eslint-config@2.7.0`, {
cwd: tempDir,
stdio: 'ignore',
});
console.log(
require(require.resolve('tslint-to-eslint-config', {
paths: [tempDir],
}))
);node ./repro.jsWhat would be super duper helpful for me is if someone could post a simple reliable way to trigger the initial error by forcing tslint-to-eslint-config@2.7.0 to run in a project. I'm having a hard time getting that.
I tried a similar set of scripts to the suggestion from @mkurte earlier (thanks for this!):
ng new my-app
cd my-app
npm i tslint
ng add @angular-eslint/schematics
ng g @angular-eslint/schematics:convert-tslint-to-eslint...with these manual steps:
- Before the
ng g, adding atslint.jsonwith basic contents - Changing the value of
tslintToEslintConfigVersioninmy-app/node_modules/@angular-eslint/schematics/dist/convert-tslint-to-eslint/convert-to-eslint-config.jsto2.7.0 - Selecting
N(no) for prompts in the schematic
No luck. Nothing crashes and the config is successfully created.
Hey guys, sorry, was on vacation. 🌴
@JamesHenry
The new version of the repro.js doesn't work too:
node repro.js
internal/modules/cjs/loader.js:969
throw err;
^
Error: Cannot find module 'tmp'
Require stack:
- /Users/matthiaskurte/Desktop/test/repro.js
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:966:15)
at Function.Module._load (internal/modules/cjs/loader.js:842:27)
at Module.require (internal/modules/cjs/loader.js:1026:19)
at require (internal/modules/cjs/helpers.js:72:18)
at Object.<anonymous> (/Users/matthiaskurte/Desktop/test/repro.js:1:21)
at Module._compile (internal/modules/cjs/loader.js:1138:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10)
at Module.load (internal/modules/cjs/loader.js:986:32)
at Function.Module._load (internal/modules/cjs/loader.js:879:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12) {
code: 'MODULE_NOT_FOUND',
requireStack: [ '/Users/matthiaskurte/Desktop/test/repro.js' ]
I guess you should call the converter with --defaults to avoid prompts. I'm pretty sure not all defaults had the option N
@JoshuaKGoldberg Ah sorry must have been because I copied the snippet from slack!
Josh, are you on a mac?
@mkurte ah ok, sorry I guess you will need to install the tmp dependency first then! Please could you try that and rerun?
Windows here.
Ah ok damn, so it's not a simple as being reproducible by OS (that was purely a guess anyway based on the commits you highlighted above)
FWIW, I also wasn't able to reproduce this (on Windows).
But did you run a npm install before running the schematic?
If you're using 3rd party plugins (e.g. codelyzer or rxjs-tslint), these must be installed.
Perhaps this is useful if the error message is different based on OS or node versions.
There was a critical error when trying to inspect your tslint.json:
Failed to load C:\Users\tdeschryver\dev\throw-aways\my-app\tslint.json: Could not find custom rule directory: node_modules/codelyzer@JamesHenry Output is now this (I forgot the quotes around tmp. 🙄 )
{
convertFileComments: [Getter],
convertTSLintConfig: [Getter],
createESLintConfiguration: [Getter],
findOriginalConfigurations: [Getter],
findReportedConfiguration: [Getter],
formatOutput: [Getter],
joinConfigConversionResults: [Getter],
ResultStatus: [Getter]
}
@mkurte Ok thanks then there is sadly no minimal repro for this...
I'm really not sure what to suggest at this point - I don't think there is anything more that can be done. @JoshuaKGoldberg this ended up impacting you the most because of the revert you did on the tslint-to-eslint-config side.
How would you like to move forward? Chalk this up to a transient/user env fluke and restore the change that was reverted?
Hmm, I'm not convinced this won't come back again if I revert the revert. The original issue (typescript-eslint/tslint-to-eslint-config#1150) is that tslint-to-eslint-config tries using cat on Windows. I can switch that to using type on Windows.
@JamesHenry I think we can close this issue out now. v2.10.1 of tslint-to-eslint-config works better on Windows 👍
This is still throwing error on my Windows 11 terminal having git bash installed with all latest versions
This is because u don't have a TS Lint in your app. So u don't need to migrate from TS Lint. Install ES Lint directly.
Else you can also install the TS Lint again and migrate - This a dumb way to proceed any way.
