GithubHelp home page GithubHelp logo

eslint-community / eslint-plugin-n Goto Github PK

View Code? Open in Web Editor NEW

This project forked from mysticatea/eslint-plugin-node

187.0 187.0 32.0 1.69 MB

Additional ESLint rules for Node.js

License: MIT License

JavaScript 100.00%
eslint eslint-plugin node nodejs

eslint-plugin-n's People

Contributors

aarongoldenthal avatar adp-psych avatar aladdin-add avatar aprilarcus avatar bizob2828 avatar bmish avatar coderaiser avatar coreyfarrell avatar danielweck avatar davej avatar fabiopaiva avatar fasttime avatar feross avatar giltayar avatar github-actions[bot] avatar jackharrhy avatar jtenclay avatar mysticatea avatar nazrhyn avatar neviaumi avatar papandreou avatar piranna avatar privatenumber avatar renovate[bot] avatar rosskevin avatar scagood avatar sosukesuzuki avatar teppeis avatar voxpelli avatar zaubernerd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

eslint-plugin-n's Issues

v16 planned changes

Starting 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:

  • Drop node < 16
  • recommended changes
    • default node.js version: ">=16"
    • ecmaVersion: "latest"
    • rules changes: TODO
  • support the new eslint config: eslint.config.js: #89

Maybe:

  • Convert package to ESM or TypeScript?

n/no-unsupported-features/es-syntax with TypeScript transpilation

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?

[Typescript] [n/no-unpublished-import] false positive when using 'import type' syntax

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()
}

Possibility to rename `n` to `node2`

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?

Typescript extensions should include tsx

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:

  • ts
  • tsx <-- official typescript file extension
  • cts
  • mts

https://github.com/weiran-zsd/eslint-plugin-node/blob/d7b975a07e1b876ca2c75597d054a81564b25685/lib/util/is-typescript.js#L5

https://github.com/weiran-zsd/eslint-plugin-node/blob/d7b975a07e1b876ca2c75597d054a81564b25685/lib/util/map-typescript-extension.js#L6-L11

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",
}

Error: require file extension '.js or .svg' (n/file-extension-in-import)

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?

no-missing-import does not work with "paths" from "tsconfig.json"

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.

Error: no-undef: 'module' is not defined despite guard check `if (typeof module === 'object')`

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?

`resolvePaths` option works differently with `import` compared to `require`

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.

`node:` prefix not working with some rules

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?

Allow setting the Node.js version in shared settings

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.

Rule suggestion: prefer `node:` prefixed imports when possible

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)

`no-unpublished-require` throws a TypeError when `"."` or `"./"` is required

The rule n/no-unpublished-require sometimes throws a TypeError when require(".") or require("./") occurs in the code.

This only happens under certain circumstances:

  • The node environment is set
  • The file that contains the require is included in the files field in package.json.
  • There is no file named index.js, or if package.json defines a different file in the 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 installand 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"

DEMO LINK


I could try to fix this if desired.

why is n/file-extension-in-import a stylic?

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

Report for features that are not available for the provided engines range

Description

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.

What I want to achieve

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?

Demonstration of the Problem

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 :(

docs updates

  • 1. rename eslint-plugin-node => eslint-plugin-n in readme.
  • 2. replace node/foo => n/foo in readme & rule docs
  • 3. update rule.meta.url
  • 4. update scripts/*

Update default node engine version

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.

Handle node: protocole

I,

Seems some rules does not properly works with node: protocole in import statements.

Cheers

Eslint can't recognise nullish coalescing operator with `plugin:n/recommended`

"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 ?

image

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.

feat request: missing-callback

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.

wrong rule: n/no-unpublished-import

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

  • published in npm and not marked as deprecated
  • installed in my node_modules
  • doesn't contain files[]
  • .npmignore doesn't contain dist/index.js

n/shebang has wrong entry for report node

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:

  • When the shebang is there and it is not supposed to be, we want the yellow squiggly line to appear only over the shebang, not over the entire file.
  • When the shebang is missing and it is supposed to be there, we want the yellow squiggly line to appear on the first line, not over the entire file.

`no-missing-imports` don't support dependencies subpaths

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.

Enable `shebang` rule for other files

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.

n/file-extension-in-import triggered incorrectly on some modules with `/` in path.

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.

range matching fails

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

type import flagged is missing and unpublished

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

Module detection is broken in monorepos

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.

Import and export declarations are not supported yet.

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"
  },

Rule idea: enforce first arg of `assert.x` cannot be a string

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:

image

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...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.