eslint-community / eslint-plugin-n Goto Github PK
View Code? Open in Web Editor NEWThis project forked from mysticatea/eslint-plugin-node
Additional ESLint rules for Node.js
License: MIT License
This project forked from mysticatea/eslint-plugin-node
Additional ESLint rules for Node.js
License: MIT License
Example
let myVar = null; // or `undefined`
myVar ??= "defined";
The rule n/no-unpublished-require
sometimes throws a TypeError
when require(".")
or require("./")
occurs in the code.
This only happens under certain circumstances:
node
environment is setrequire
is included in the files
field in package.json.main
field, that file does not exist.The smallest repro I've come up with:
package.json
{
"files": [
"*.js"
],
"devDependencies": {
"eslint": "latest",
"eslint-plugin-n": "latest"
}
}
.eslintrc
{
"env": {
"node": true
},
"plugins": [
"n"
],
"rules": {
"n/no-unpublished-require": "error"
}
}
foo.js
require('.');
Running npm install
and then npx eslint .
in the project folder prints an error message like this:
Oops! Something went wrong! :(
ESLint: 8.22.0
TypeError: path must not be empty
Occurred while linting /home/user/my-project/foo.js:1
Rule: "n/no-unpublished-require"
I could try to fix this if desired.
e.g. fetch
: requires node.js >= 18.0.0
idk if there is an existing rule to handle this case, but in Typescript, you can do:
import type { SomeType } from 'some-library';
for context, when transpiling to either CJS or MJS, the import doesn't make it to the output -- obviously a lint plugin can't know that is going to happen, but if there could be some way to relax n/no-missing-import
and n/no-unpublished-import
, (or require that some-library
be in devDependencies
if not found in the normal locations, this'd be a huge help <3
When I set engines.node: ">=6"
in the package.json, I expect dynamic imports to evoke an error (see mdn). They don't. When I set an upper boundary, like >=6 <=12.16
, it will throw an error.
I recreated the error here, using this project's code.
import semver from 'semver';
const supported = new semver.Range('>=12.17 <13 || >=13.2');
const versionFailing = new semver.Range('>=6');
const versionPassing = new semver.Range('>=6 <=12.16');
console.log(versionFailing.intersects(supported)); // In the code, this means the rule is supported
// => true, because >=6 *includes* a node version which supports it.
Possible cause:
The code only checks that some of the given versions support the code. ("intersects")
https://github.com/weiran-zsd/eslint-plugin-node/blob/592869528b1e6e3278603ea00696000019c22114/lib/rules/no-unsupported-features/es-syntax.js#L461
There are two imports for asserts:
import assert from 'node:assert/strict'
: Strict assertion mode;import assert from 'node:assert'
: Legacy assertion mode that exports 4 functions no longer actively maintained (deepEqual
, equal
, notDeepEqual
and notEqual
).I propose a new rule prefer-import/assert-strict
that reports an error when node:assert
is imported.
Getting this lint Import and export declarations are not supported yet. eslint(n/no-unsupported-features/es-syntax)
on a typescript file
node 16.14.2
eslint 8.13.0
eslint-plugin-n 15.1.0
.eslintrc.js:
module.exports = {
env: {
browser: false,
es2021: true,
mocha: true,
node: true
},
plugins: ['@typescript-eslint'],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'prettier',
'plugin:n/recommended'
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 2021,
sourceType: 'module'
}
};
Any ideas? I saw the plugin checks engine version, my package.json has:
"engines": {
"node": ">=16.13.0"
},
Opening this up to discuss the idea and naming, not to request someone else implement it - I'm happy to do that.
Today I noticed across several projects that I maintain that the order of the arguments passed to Node's assert method are often confused.
Take assert.equal(actual, expected[, message])
for example... the docs clearly show the first argument should be the actual
value, and the second the expected value.
The impact of getting them the wrong way around is very minor - but it breaks my brain when trying to debug a test and staring at this output where the prompt says the expected value should start with a plus and be green, but in reality that's the actual value:
I think this is very easy to enforce by ensuring that the first param passed to the assert functions is not a string.
Soooo what to call this rule? I'm thinking: params-order-assert
Slightly confusing because assert is referring to the module, not enforcing the rule...
If using plugin:n/recommended
, this line is always fetching the "type"
value from the root level package.json
instead of the nearest one, which produces false positives on monorepos with a mix of "commonjs"
and "module"
packages.
Additionally, eslint
already provides settings for determining which type of package the current project is: parserOptions.sourceType
. IMHO, we should be using that instead of leveraging package.json
properties. As of right now, even if I have "sourceType"
set to "script"
, this plugin may produce errors out of module.exports
and require
usages — which should never really be the case.
As discussed in a previous thread with eg. me, you @aladdin-add, @MichaelDeBoey: standard/eslint-config-standard#192 (comment)
Having an eslint-community
organization (or similar) that's home to this module + eslint-plugin-promise
and other important modules would be good .
@aladdin-add You mentioned that @nzakas were setting up an eslint-community
organization, do you know anything more?
I have a node-check repository here at repo-link. The project is using NodeJS >=8.0.0 <=14.20.0
properly configured at the engines
inside the package.json
file.
Now, sometimes we may accidentally add NodeJS code that is not supported in the specified range but available with the latest versions, like while using replaceAll
with strings. It is only introduced in v15, so if the range does not include 15.x.x
, the code will break.
Can eslint-plugin-node
help me in this case? Can we configure this package to report for such issues?
Here is a Github workflow demonstrating the case: https://github.com/kiranparajuli589/node-check/runs/7738971827?check_suite_focus=true
Here I've used plugin:n/recommend
in the extends section, but the linter does not report anything :(
[DEP0147] DeprecationWarning: In future versions of Node.js, fs.rmdir(path, { recursive: true }) will be removed. Use fs.rm(path, { recursive: true }) instead
Currently the shebang
rule only ensures that the file referenced by the bin
field in package.json
has a shebang. However, there are times when you want other files to be run as scripts, say in a scripts
directory in your project.
I recommend adding an option to ensure that all files matched by a glob pattern also require a shebang. This would also ensure that those files don't have any other shebang related issues like BOM or non-LF line breaks.
I hope this is a real issue.
I recently modified like fs.unlinkSync
to fs.unlink
but missing the callback parameter callback: fs.NoParamCallback
, I mistakenly think it is an optional parameter. No editor or building message appears, an error occurs when it is executed, even quietly if meet try catch
.
I tested this using "n/prefer-promises/fs": "error"
and it gave no error:
import { readFile } from 'node:fs';
readFile('/etc/passwd', (err, data) => {
if (err) throw err;
console.log(data);
});
The rules prefer-promises
does not seem to be able to handle using the node:
prefix. Maybe this is true for several more rules?
If an import includes a sub-path, like @scope/package-name/sub-path
, it's identified as missing. Not sure if in all the cases, or just only when using the exports
field, but in any case it should be easy to fix, get the package sub-path and checks if it exists in the package folder or matches its exports
field.
Sorry for the bikeshedding, but "n
" sounds a bit minimal. Especially in the ESlint configuration rules.
I believe any name would be suboptimal, but having the weird node
in the name would, I believe be beneficial.
Something like node2
or node-new
?
In a monorepo, you typically use the "paths" option inside of the "tsconfig.json" file to make your individual packages aware of each other like this:
tsconfig.json
{
"paths": {
"foo": ["packages/foo/src/index.ts"],
"bar": ["packages/bar/src/index.ts"],
},
}
However, this triggers false positives for no-missing-import
.
Hi, thanks for making this maintenance fork!
I like the eslint-plugin-node, and use it for years, but today it broke.
I made a demo project that wraps my demo code
const EX = { dummy: true };
if (typeof module === 'object') { Object.assign(module.exports, EX); }
in all the bells and whistles required for proper Github CI, and initially everything works.
Then I add plugin:n/recommended
and suddenly eslint reports
##[error] 2:49 error 'module' is not defined no-undef
Looks like something overrides { "env": { "node": true } }
, even if I explicitly add it to my package.json
.
(Edit: Nope, that part is correct, global module
is indeed undefined in node v16 when using .mjs filename extension.)
But even then, shouldn't my typeof
check guard it?
Hi, there is a breaking change between versions 14 and 15 and I would like to report/discuss whether it's intentional or not (and how to fix it).
Basically, rule n/file-extension-in-import
started reporting the following errors:
error: require file extension '.js or .svg' (n/file-extension-in-import) at src/abacus-kochka/src/LanguageSwitch.js:9:20:
7 |
8 | import FlagMX from './design/svg/generated/flags/mx';
> 9 | import FlagUS from './design/svg/generated/flags/us';
| ^
10 | import useViewerContext from './hooks/useViewerContext';
11 |
12 | export default function LanguageSwitch(): React.Node {
The thing is that everything works as it did before. Moreover, other imports are not problematic. I think it happens only when there are more files with the same name. For example in this case the content of the folder I am trying to import from is:
├── mx.js
├── mx.svg
├── us.js
└── us.svg
Is it intentional behavior? How should it be fixed? I could of course add the extensions like so:
import FlagMX from './design/svg/generated/flags/mx.js';
import FlagUS from './design/svg/generated/flags/us.js';
However, that goes against import/extensions
because we disallow extensions. What is the motivation behind this change and what is the correct behavior?
This repository is currently forked from https://github.com/mysticatea/eslint-plugin-node, which makes it impossible to search code via GitHub. Since the original repository is stale, I'm not sure there is a point to keep it forked.
I recommend unforking this repository to enable code search.
I'm not sure if this is a problem with eslint-plugin-n or what, but here goes...
So XO from 0.49 to 0.50 has changed from eslint-plugin-node to eslint-plugin-n, and now I am getting a bunch of errors. They're bogus because TypeScript is transpiling, so for example optional chainings & nullish coalescing operators work just fine with node 12 and don't need node 14.
The doc says "If you are using transpilers, maybe you want to ignore the warnings about some features." so I added this to my config file (which is .xo-config.json in this case, it should be forwarded to eslint):
"n/no-unsupported-features/es-syntax": ["error", { "ignores": [ "optionalChaining", "nullishCoalescingOperator" ] }]
But I am still seeing the errors.
Again, I am not sure this is a problem with eslint-plugin-n or XO or what?
In future maybe it would be possible to fix things such that TypeScript transpilation would be recognised and these errors would not be generated?
it would requires switching from eslint-plugin-es
=> eslint-plugin-es-x
Suggested fix: try esbuild externals
--external:./node_modules/*
(or be more selective if some externals are ESM instead of CJS dependencies)
See documentation: https://esbuild.github.io/api/#external
eslint-plugin-node
=> eslint-plugin-n
in readme.node/foo
=> n/foo
in readme & rule docsStarting a list of my desired breaking changes, feedback welcome. We can perform this release once we have compiled enough changes. We should watch out for any breaking changes needed for ESLint v9 in the coming months.
Planned:
recommended
changes
eslint.config.js
: #89Maybe:
ESLint supports setting the cwd
.
However, the getPackageJson
function looks up using process.cwd()
.
i don't consider file extension as something that is stylic
it's more of a problem if you want to trully run ESM scripts that demands that you use file extension
it will possible only work b/c someone is using a build script anyways.
i think demanding a extension should be a recommended rule.
when using remote path resolver like http import you can't guess what you meant to import cuz you do not have access to the fs
https://nodejs.org/dist/latest-v18.x/docs/api/esm.html#mandatory-file-extensions (<-- mandatory is in the link desc)
standard/standard#1674
Similar to n/file-extension-in-import - I'll take a look at reusing the code and PR.
This plugin supports Typescript's Node ESM file extension conventions but does not support all Typescript extensions.
In this case, Example.tsx
exists but is not properly resolved.
error "./Example.js" is not found n/no-missing-import
The Typescript docs mention the following extensions:
This would probably fix it:
// lib/util/is-typescript.js
const typescriptExtensions = [".ts", ".tsx", ".cts", ".mts"]
// lib/util/map-typescript-extension.js
const mapping = {
"": ".js", // default empty extension will map to js
".ts": ".js",
".tsx": ".js", // <--
".cts": ".cjs",
".mts": ".mjs",
}
in my code I use import { pathsToModuleNameMapper } from 'ts-jest';
but ts-jest is reported as unpublished
I checked all the requirements to consider the package is published
https://github.com/eslint-community/eslint-plugin-n/blob/master/docs/rules/no-unpublished-import.md stats:
ECMAScript 2015 (ES6) does not define the lookup logic and Node does not support modules yet. So this rule spec might be changed in future.
This is not true since quite some time back. It would be good to search & replace all instances of this mention in all rules (in case there are more than the one linked above).
Similar to https://github.com/mysticatea/eslint-plugin-node/blob/master/docs/rules/no-missing-import.md, add support for the tryExtensions
option.
Older built-in Node modules such as fs now can be imported via either their name or node: + their name:
import fs from "fs";
import fs from "node:fs";
The prefixed versions are nice because they can't be overridden by user modules and are similarly formatted to to prefix-only modules such as node:test.
Suggestion: let's add a linter rule to enforce using them, with an auto-fixer.
(copied from mysticatea#344)
"eslint": "8.24.0"
"eslint-plugin-n": "15.6.0"
.eslintrc.yml
:
root: true
env:
node: true
es2021: true
parserOptions:
sourceType: module
extends:
- eslint:recommended
- plugin:n/recommended
- prettier
package.json
:
"engines": {
"node": "16"
},
VSCode shows the following error for nullish coalescing operator:
Parsing error: Unexpected token ?
According to node.green, this operator is supported in Node v16: https://node.green/#ES2020-features--nullish-coalescing-operator-----
Running eslint with --print-config
shows:
"ecmaVersion": 2019
Perhaps, this is the cause. But why is it 2019?
Disabling plugin:n/recommended
removes the above mentioned eslint error, but it brings back another error about instance class fields, which is part of ES2022. This feature is supported by Node v16, but I can't specify "ecmaVersion": 2022
because Node v16 does not support it fully. This was my motivation for using eslint-plugin-n
.
When a dependency (express in my example) is available in devDependencies, typescript import type
syntax should not trigger n/no-unpublished-import
error, as the dependency will not be imported at runtime.
import type {RequestHandler} from 'express'
// error "express" is not published n/no-unpublished-import
export const handler: RequestHandler = (req, response, next) => {
console.log(req.url)
response.json({})
next()
}
The bug is here:
https://github.com/eslint-community/eslint-plugin-n/blob/master/lib/rules/shebang.js#L164
Instead of selecting node
, we need to select only the first line of the file.
In other words, when in VSCode:
I,
Seems some rules does not properly works with node: protocole in import statements.
Cheers
Currently, the only way to specify the target node version is by setting the engines.node
field in package.json
or by specifying a version
field in each rule configuration.
It would be helpful to be able to set the version in shared settings like you can set allowModules
, convertPath
, and tryExtensions
.
This would allow you to set the Node.js version for a specific directory, like test
.
// package.json
{
"engines": {
"node": "^12 || >=14"
}
}
// test/.eslintrc.json
{
"settings": {
"node": {
"version": ">=14"
}
}
}
Let me know if this is desirable, and I can work on a PR.
At the moment of writing, the latest supported Node.js version is 14 (release schedule). Currently the default version in this plugin is Node.js 8, which reached end of life in 2019. I think it makes sense to update the default version.
I forked eslint-plugin-es and released eslint-plugin-es-x.
https://github.com/ota-meshi/eslint-plugin-es-x
Do you think eslint-plugin-n
needs to use eslint-plugin-es-x?
For example the convertPath
settings, should still come under settings.node
rather than settings.n
e.g. used by shebang
When using the resolvePaths
setting to set the paths where eslint should look when resolving module specifiers, import
statements resolve as expected, but require
statements don't.
See my minimal reproducible example.
The way eslint-plugin-n handles import
statements is that it pretends that the source module is in each of the directories specified by resolvePaths
, however it does not do this for require
statements.
Note that the paths
property of the options
parameter of resolve.sync
should work like the paths
property of the options
parameter of require.resolve
, but it doesn't.
require file extension '.js' n/file-extension-in-import
error is being triggered incorrectly for a few modules including @apollo/client/core
and yargs/helpers
The key driver to these appear to be the occurrence of a slash even, which may be tripping a condition to call it a local file.
I am investigating now to see if I can solve and PR.
It was bad that they overrided it in the first place...
https://nodejs.org/dist/latest-v18.x/docs/api/buffer.html#bufslicestart-end
Buffer don't even have a slice method that did the correct thing. slice is only an alias for subarray. and subarray is what ppl should have been using instead.
Node.js has experimental support for loading modules via HTTP.
no-missing-import
should support http
/https
protocols by ignoring it, or offer an option to ignore certain protocols/patterns.
It seems package entry points are not supported by file-extension-in-import
as it still requires a file extension for them, eg. for eslint/use-at-your-own-risk
.
But by adding the file extension the file in the package root is required instead.
I am willing to submit a pull request for this.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.