diff --git a/.github/workflows/native-wsl.yml b/.github/workflows/native-wsl.yml index 5e8318899..360b2873f 100644 --- a/.github/workflows/native-wsl.yml +++ b/.github/workflows/native-wsl.yml @@ -16,7 +16,7 @@ jobs: fail-fast: false matrix: os: [windows-2019] - node-version: [18, 16, 14, 12, 10, 8, 6, 4] + node-version: [22, 20, 18] configuration: [wsl, native] steps: @@ -30,80 +30,29 @@ jobs: if: matrix.configuration == 'wsl' env: ESLINT_VERSION: 7 - TRAVIS_NODE_VERSION: ${{ matrix.node-version }} run: | curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/master/install.sh | bash export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm nvm install --latest-npm ${{ matrix.node-version }} - if [ ${{ matrix.node-version }} -ge 4 ] && [ ${{ matrix.node-version }} -lt 6 ]; then - npm install eslint@4 --no-save --ignore-scripts - npm install - npm install eslint-import-resolver-typescript@1.0.2 --no-save - npm uninstall @angular-eslint/template-parser @typescript-eslint/parser --no-save - fi - if [ ${{ matrix.node-version }} -ge 6 ] && [ ${{ matrix.node-version }} -lt 7 ]; then - npm install eslint@5 --no-save --ignore-scripts - npm install - npm uninstall @angular-eslint/template-parser --no-save - npm install eslint-import-resolver-typescript@1.0.2 @typescript-eslint/parser@3 --no-save - fi - if [ ${{ matrix.node-version }} -ge 7 ] && [ ${{ matrix.node-version }} -lt 8 ]; then - npm install eslint@6 --no-save --ignore-scripts - npm install - npm install eslint-import-resolver-typescript@1.0.2 typescript-eslint-parser@20 --no-save - npm uninstall @angular-eslint/template-parser --no-save - fi - if [ ${{ matrix.node-version }} -eq 8 ]; then - npm install eslint@6 --no-save --ignore-scripts - npm install - npm uninstall @angular-eslint/template-parser --no-save - npm install @typescript-eslint/parser@3 --no-save - fi - if [ ${{ matrix.node-version }} -gt 8 ] && [ ${{ matrix.node-version }} -lt 10 ]; then - npm install eslint@7 --no-save --ignore-scripts - npm install - npm install @typescript-eslint/parser@3 --no-save - fi - if [ ${{ matrix.node-version }} -ge 10 ] && [ ${{ matrix.node-version }} -lt 12 ]; then - npm install - npm install @typescript-eslint/parser@4 --no-save - fi - if [ ${{ matrix.node-version }} -ge 12 ]; then - npm install - fi + npm install npm run copy-metafiles npm run pretest npm run tests-only - - name: install dependencies for node <= 10 - if: matrix.node-version <= '10' && matrix.configuration == 'native' - run: | - npm install --legacy-peer-deps - npm install eslint@7 --no-save - - - name: Install dependencies for node > 10 - if: matrix.node-version > '10' && matrix.configuration == 'native' + - name: Install dependencies in Native + if: matrix.configuration == 'native' run: npm install - - name: install the latest version of nyc + - name: install the latest version of nyc in Native if: matrix.configuration == 'native' run: npm install nyc@latest --no-save - - name: copy metafiles for node <= 8 - if: matrix.node-version <= 8 && matrix.configuration == 'native' - env: - ESLINT_VERSION: 6 - TRAVIS_NODE_VERSION: ${{ matrix.node-version }} - run: | - npm run copy-metafiles - bash ./tests/dep-time-travel.sh 2>&1 - - name: copy metafiles for Node > 8 - if: matrix.node-version > 8 && matrix.configuration == 'native' + - name: copy metafiles in Native + if: matrix.configuration == 'native' env: ESLINT_VERSION: 7 - TRAVIS_NODE_VERSION: ${{ matrix.node-version }} run: | npm run copy-metafiles bash ./tests/dep-time-travel.sh 2>&1 diff --git a/.github/workflows/node-4+.yml b/.github/workflows/node-4+.yml deleted file mode 100644 index 323c2ad54..000000000 --- a/.github/workflows/node-4+.yml +++ /dev/null @@ -1,160 +0,0 @@ -name: 'Tests: node.js' - -on: [pull_request, push] - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} - -permissions: - contents: read - -jobs: - matrix: - runs-on: ubuntu-latest - outputs: - latest: ${{ steps.set-matrix.outputs.requireds }} - minors: ${{ steps.set-matrix.outputs.optionals }} - steps: - - uses: ljharb/actions/node/matrix@main - id: set-matrix - with: - versionsAsRoot: true - type: majors - preset: '>= 6' # preset: '>=4' # see https://github.com/import-js/eslint-plugin-import/issues/2053 - - latest: - needs: [matrix] - name: 'majors' - runs-on: ${{ matrix.os }} - - strategy: - fail-fast: false - matrix: - os: - - ubuntu-latest - - macos-latest - node-version: ${{ fromJson(needs.matrix.outputs.latest) }} - eslint: - - 9 - - 8 - - 7 - - 6 - - 5 - - 4 - - 3 - - 2 - include: - - node-version: 'lts/*' - os: ubuntu-latest - eslint: 7 - ts-parser: 4 - env: - TS_PARSER: 4 - - node-version: 'lts/*' - os: ubuntu-latest - eslint: 7 - ts-parser: 3 - env: - TS_PARSER: 3 - - node-version: 'lts/*' - os: ubuntu-latest - eslint: 7 - ts-parser: 2 - env: - TS_PARSER: 2 - exclude: - - node-version: 16 - eslint: 9 - - node-version: 15 - eslint: 9 - - node-version: 15 - eslint: 8 - - node-version: 14 - eslint: 9 - - node-version: 13 - eslint: 9 - - node-version: 13 - eslint: 8 - - node-version: 12 - eslint: 9 - - node-version: 11 - eslint: 9 - - node-version: 11 - eslint: 8 - - node-version: 10 - eslint: 9 - - node-version: 10 - eslint: 8 - - node-version: 9 - eslint: 9 - - node-version: 9 - eslint: 8 - - node-version: 9 - eslint: 7 - - node-version: 8 - eslint: 9 - - node-version: 8 - eslint: 8 - - node-version: 8 - eslint: 7 - - node-version: 7 - eslint: 9 - - node-version: 7 - eslint: 8 - - node-version: 7 - eslint: 7 - - node-version: 7 - eslint: 6 - - node-version: 6 - eslint: 9 - - node-version: 6 - eslint: 8 - - node-version: 6 - eslint: 7 - - node-version: 6 - eslint: 6 - - node-version: 5 - eslint: 9 - - node-version: 5 - eslint: 8 - - node-version: 5 - eslint: 7 - - node-version: 5 - eslint: 6 - - node-version: 5 - eslint: 5 - - node-version: 4 - eslint: 9 - - node-version: 4 - eslint: 8 - - node-version: 4 - eslint: 7 - - node-version: 4 - eslint: 6 - - node-version: 4 - eslint: 5 - - steps: - - uses: actions/checkout@v4 - - uses: ljharb/actions/node/install@main - continue-on-error: ${{ matrix.eslint == 4 && matrix.node-version == 4 }} - name: 'nvm install ${{ matrix.node-version }} && npm install, with eslint ${{ matrix.eslint }}' - env: - NPM_CONFIG_LEGACY_PEER_DEPS: ${{ matrix.node-version == 11 && false || true }} - ESLINT_VERSION: ${{ matrix.eslint }} - TRAVIS_NODE_VERSION: ${{ matrix.node-version }} - with: - node-version: ${{ matrix.node-version }} - after_install: npm run copy-metafiles && ./tests/dep-time-travel.sh - skip-ls-check: true - - run: npm run pretest - - run: npm run tests-only - - uses: codecov/codecov-action@v3.1.5 - - node: - name: 'node 4+' - needs: [latest] - runs-on: ubuntu-latest - steps: - - run: 'echo tests completed' diff --git a/.github/workflows/node.yml b/.github/workflows/node.yml new file mode 100644 index 000000000..1f8bbf177 --- /dev/null +++ b/.github/workflows/node.yml @@ -0,0 +1,85 @@ +name: 'Tests: node.js' + +on: [pull_request, push] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +permissions: + contents: read + +jobs: + matrix: + runs-on: ubuntu-latest + outputs: + latest: ${{ steps.set-matrix.outputs.requireds }} + minors: ${{ steps.set-matrix.outputs.optionals }} + steps: + - uses: ljharb/actions/node/matrix@main + id: set-matrix + with: + versionsAsRoot: true + type: majors + preset: '^18.18.0 || ^20.9.0 || >=21.1.0' + + latest: + needs: [matrix] + name: 'majors' + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + os: + - ubuntu-latest + - macos-latest + node-version: ${{ fromJson(needs.matrix.outputs.latest) }} + eslint: + - 9 + - 8 + - 7 + - 6 + - 5 + - 4 + - 3 + - 2 + include: + - node-version: 'lts/*' + os: ubuntu-latest + eslint: 7 + env: + TS_PARSER: 4 + - node-version: 'lts/*' + os: ubuntu-latest + eslint: 7 + env: + TS_PARSER: 3 + - node-version: 'lts/*' + os: ubuntu-latest + eslint: 7 + env: + TS_PARSER: 2 + + steps: + - uses: actions/checkout@v4 + - uses: ljharb/actions/node/install@main + continue-on-error: false + name: 'nvm install ${{ matrix.node-version }} && npm install, with eslint ${{ matrix.eslint }}' + env: + NPM_CONFIG_LEGACY_PEER_DEPS: false + ESLINT_VERSION: ${{ matrix.eslint }} + with: + node-version: ${{ matrix.node-version }} + after_install: npm run copy-metafiles && ./tests/dep-time-travel.sh + skip-ls-check: true + - run: npm run pretest + - run: npm run tests-only + - uses: codecov/codecov-action@v3.1.5 + + node: + name: 'node 18+' + needs: [latest] + runs-on: ubuntu-latest + steps: + - run: 'echo tests completed' diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index f73f8e18f..db61d30b0 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -20,7 +20,7 @@ jobs: id: set-matrix with: type: 'majors' - preset: '>= 6' # preset: '>=4' # see https://github.com/import-js/eslint-plugin-import/issues/2053 + preset: '^18.18.0 || ^20.9.0 || >=21.1.0' versionsAsRoot: true tests: @@ -46,9 +46,8 @@ jobs: - uses: ljharb/actions/node/install@main name: 'nvm install ${{ matrix.node-version }} && npm install' env: - NPM_CONFIG_LEGACY_PEER_DEPS: ${{ matrix.node-version == 11 && false || true }} + NPM_CONFIG_LEGACY_PEER_DEPS: false ESLINT_VERSION: ${{ matrix.eslint }} - TRAVIS_NODE_VERSION: ${{ matrix.node-version }} with: node-version: ${{ matrix.node-version }} after_install: npm run copy-metafiles && ./tests/dep-time-travel.sh && cd ${{ matrix.package }} && npm install diff --git a/package.json b/package.json index 7852506bd..a7cfe5cdc 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "2.31.0", "description": "Import with sanity.", "engines": { - "node": ">=4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "main": "lib/index.js", "directories": { @@ -93,7 +93,6 @@ "jackspeak": "=2.1.1", "jsonc-parser": "=3.2.0", "linklocal": "^2.8.2", - "lodash.isarray": "^4.0.0", "markdownlint-cli": "~0.35", "mocha": "^3.5.3", "npm-which": "^3.0.1", @@ -110,23 +109,14 @@ }, "dependencies": { "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.8", - "array.prototype.findlastindex": "^1.2.5", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", "eslint-module-utils": "^2.12.0", - "hasown": "^2.0.2", - "is-core-module": "^2.15.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", "object.groupby": "^1.0.3", - "object.values": "^1.2.0", "semver": "^6.3.1", - "string.prototype.trimend": "^1.0.8", "tsconfig-paths": "^3.15.0" } } diff --git a/resolvers/README.md b/resolvers/README.md index e55ebb610..fefc025a3 100644 --- a/resolvers/README.md +++ b/resolvers/README.md @@ -73,11 +73,11 @@ If the resolver cannot resolve `source` relative to `file`, it should just retur Here is most of the [Node resolver] at the time of this writing. It is just a wrapper around substack/Browserify's synchronous [`resolve`]: ```js +var { isBuiltin } = require('node:module'); var resolve = require('resolve/sync'); -var isCoreModule = require('is-core-module'); exports.resolve = function (source, file, config) { - if (isCoreModule(source)) return { found: true, path: null }; + if (isBuiltin(source)) return { found: true, path: null }; try { return { found: true, path: resolve(source, opts(file, config)) }; } catch (err) { diff --git a/resolvers/node/index.js b/resolvers/node/index.js index 9e0e753cc..7daa8cef2 100644 --- a/resolvers/node/index.js +++ b/resolvers/node/index.js @@ -1,7 +1,7 @@ 'use strict'; +const { isBuiltin } = require('node:module'); const resolve = require('resolve/sync'); -const isCoreModule = require('is-core-module'); const path = require('path'); const log = require('debug')('eslint-plugin-import:resolver:node'); @@ -49,7 +49,7 @@ exports.resolve = function (source, file, config) { log('Resolving:', source, 'from:', file); let resolvedPath; - if (isCoreModule(source)) { + if (isBuiltin(source)) { log('resolved to core'); return { found: true, path: null }; } diff --git a/resolvers/node/package.json b/resolvers/node/package.json index 6f6999e6c..3c406ee1b 100644 --- a/resolvers/node/package.json +++ b/resolvers/node/package.json @@ -31,12 +31,14 @@ "homepage": "https://github.com/import-js/eslint-plugin-import", "dependencies": { "debug": "^3.2.7", - "is-core-module": "^2.13.0", "resolve": "^1.22.4" }, "devDependencies": { "chai": "^3.5.0", "mocha": "^3.5.3", "nyc": "^11.9.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } } diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js index 83297cd18..6a5841766 100644 --- a/resolvers/webpack/index.js +++ b/resolvers/webpack/index.js @@ -2,17 +2,13 @@ const findRoot = require('find-root'); const path = require('path'); +const { isBuiltin } = require('node:module'); const isEqual = require('lodash/isEqual'); const interpret = require('interpret'); const existsSync = require('fs').existsSync; -const isCore = require('is-core-module'); const resolve = require('resolve/sync'); const semver = require('semver'); -const hasOwn = require('hasown'); const isRegex = require('is-regex'); -const isArray = Array.isArray; -const keys = Object.keys; -const assign = Object.assign; const log = require('debug')('eslint-plugin-import:resolver:webpack'); @@ -22,7 +18,7 @@ function registerCompiler(moduleDescriptor) { if (moduleDescriptor) { if (typeof moduleDescriptor === 'string') { require(moduleDescriptor); - } else if (!isArray(moduleDescriptor)) { + } else if (!Array.isArray(moduleDescriptor)) { moduleDescriptor.register(require(moduleDescriptor.module)); } else { for (let i = 0; i < moduleDescriptor.length; i++) { @@ -38,7 +34,7 @@ function registerCompiler(moduleDescriptor) { } function findConfigPath(configPath, packageDir) { - const extensions = keys(interpret.extensions).sort(function (a, b) { + const extensions = Object.keys(interpret.extensions).sort(function (a, b) { return a === '.js' ? -1 : b === '.js' ? 1 : a.length - b.length; }); let extension; @@ -79,7 +75,7 @@ function findExternal(source, externals, context, resolveSync) { if (typeof externals === 'string') { return source === externals; } // array: recurse - if (isArray(externals)) { + if (Array.isArray(externals)) { return externals.some(function (e) { return findExternal(source, e, context, resolveSync); }); } @@ -133,7 +129,7 @@ function findExternal(source, externals, context, resolveSync) { // else, vanilla object for (const key in externals) { - if (hasOwn(externals, key) && source === key) { + if (Object.hasOwn(externals, key) && source === key) { return true; } } @@ -156,7 +152,7 @@ const webpack2DefaultResolveConfig = { function createWebpack2ResolveSync(webpackRequire, resolveConfig) { const EnhancedResolve = webpackRequire('enhanced-resolve'); - return EnhancedResolve.create.sync(assign({}, webpack2DefaultResolveConfig, resolveConfig)); + return EnhancedResolve.create.sync(Object.assign({}, webpack2DefaultResolveConfig, resolveConfig)); } /** @@ -178,7 +174,7 @@ function makeRootPlugin(ModulesInRootPlugin, name, root) { if (typeof root === 'string') { return new ModulesInRootPlugin(name, root); } - if (isArray(root)) { + if (Array.isArray(root)) { return function () { root.forEach(function (root) { this.apply(new ModulesInRootPlugin(name, root)); @@ -238,7 +234,7 @@ function createWebpack1ResolveSync(webpackRequire, resolveConfig, plugins) { if ( plugin.constructor && plugin.constructor.name === 'ResolverPlugin' - && isArray(plugin.plugins) + && Array.isArray(plugin.plugins) ) { resolvePlugins.push.apply(resolvePlugins, plugin.plugins); } @@ -401,7 +397,7 @@ exports.resolve = function (source, file, settings) { webpackConfig = webpackConfig(env, argv); } - if (isArray(webpackConfig)) { + if (Array.isArray(webpackConfig)) { webpackConfig = webpackConfig.map((cfg) => { if (typeof cfg === 'function') { return cfg(env, argv); @@ -448,7 +444,7 @@ exports.resolve = function (source, file, settings) { try { return { found: true, path: resolveSync(path.dirname(file), source) }; } catch (err) { - if (isCore(source)) { + if (isBuiltin(source)) { return { found: true, path: null }; } diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json index 60e5c900f..135c99ef2 100644 --- a/resolvers/webpack/package.json +++ b/resolvers/webpack/package.json @@ -34,9 +34,7 @@ "debug": "^3.2.7", "enhanced-resolve": "^0.9.1", "find-root": "^1.1.0", - "hasown": "^2.0.0", "interpret": "^1.4.0", - "is-core-module": "^2.13.1", "is-regex": "^1.1.4", "lodash": "^4.17.21", "resolve": "^2.0.0-next.5", @@ -55,6 +53,6 @@ "webpack": "https://gist.github.com/ljharb/9cdb687f3806f8e6cb8a365d0b7840eb" }, "engines": { - "node": ">= 6" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } } diff --git a/src/core/importType.js b/src/core/importType.js index 32e200f1d..f6662e337 100644 --- a/src/core/importType.js +++ b/src/core/importType.js @@ -1,5 +1,5 @@ +import { isBuiltin } from 'node:module'; import { isAbsolute as nodeIsAbsolute, relative, resolve as nodeResolve } from 'path'; -import isCoreModule from 'is-core-module'; import resolve from 'eslint-module-utils/resolve'; import { getContextPackagePath } from './packagePath'; @@ -32,7 +32,7 @@ export function isBuiltIn(name, settings, path) { if (path || !name) { return false; } const base = baseModule(name); const extras = settings && settings['import/core-modules'] || []; - return isCoreModule(base) || extras.indexOf(base) > -1; + return isBuiltin(base) || extras.indexOf(base) > -1; } const moduleRegExp = /^\w/; diff --git a/src/exportMap/visitor.js b/src/exportMap/visitor.js index 21c1a7c64..e5cea8191 100644 --- a/src/exportMap/visitor.js +++ b/src/exportMap/visitor.js @@ -1,4 +1,3 @@ -import includes from 'array-includes'; import { SourceCode } from 'eslint'; import { availableDocStyleParsers, captureDoc } from './doc'; import Namespace from './namespace'; @@ -121,11 +120,11 @@ export default class ImportExportVisitorBuilder { 'TSAbstractClassDeclaration', 'TSModuleDeclaration', ]; - const exportedDecls = this.ast.body.filter(({ type, id, declarations }) => includes(declTypes, type) && ( + const exportedDecls = this.ast.body.filter(({ type, id, declarations }) => declTypes.includes(type) && ( id && id.name === exportedName || declarations && declarations.find((d) => d.id.name === exportedName) )); if (exportedDecls.length === 0) { - // Export is not referencing any local declaration, must be re-exporting + // Export is not referencing any local declaration, must be re-exported this.exportMap.namespace.set('default', captureDoc(this.source, this.docStyleParsers, astNode)); return; } diff --git a/src/rules/export.js b/src/rules/export.js index fbbc39d75..570fcb6eb 100644 --- a/src/rules/export.js +++ b/src/rules/export.js @@ -1,7 +1,6 @@ import ExportMapBuilder from '../exportMap/builder'; import recursivePatternCapture from '../exportMap/patternCapture'; import docsUrl from '../docsUrl'; -import includes from 'array-includes'; /* Notes on TypeScript namespaces aka TSModuleDeclaration: @@ -157,10 +156,10 @@ module.exports = { const isTypeVariableDecl = node.declaration.kind === 'type'; if (node.declaration.id != null) { - if (includes([ + if ([ 'TSTypeAliasDeclaration', 'TSInterfaceDeclaration', - ], node.declaration.type)) { + ].includes(node.declaration.type)) { addNamed(node.declaration.id.name, node.declaration.id, parent, true); } else { addNamed(node.declaration.id.name, node.declaration.id, parent, isTypeVariableDecl); diff --git a/src/rules/exports-last.js b/src/rules/exports-last.js index 1e79f8339..e1555b74f 100644 --- a/src/rules/exports-last.js +++ b/src/rules/exports-last.js @@ -1,5 +1,3 @@ -import findLastIndex from 'array.prototype.findlastindex'; - import docsUrl from '../docsUrl'; function isNonExportStatement({ type }) { @@ -22,7 +20,7 @@ module.exports = { create(context) { return { Program({ body }) { - const lastNonExportStatementIndex = findLastIndex(body, isNonExportStatement); + const lastNonExportStatementIndex = body.findLastIndex(isNonExportStatement); if (lastNonExportStatementIndex !== -1) { body.slice(0, lastNonExportStatementIndex).forEach((node) => { diff --git a/src/rules/group-exports.js b/src/rules/group-exports.js index 7978130d3..171678a30 100644 --- a/src/rules/group-exports.js +++ b/src/rules/group-exports.js @@ -1,6 +1,4 @@ import docsUrl from '../docsUrl'; -import values from 'object.values'; -import flat from 'array.prototype.flat'; const meta = { type: 'suggestion', @@ -107,8 +105,9 @@ function create(context) { } // Report multiple `aggregated exports` from the same module (ES2015 modules) - flat(values(nodes.modules.sources) - .filter((nodesWithSource) => Array.isArray(nodesWithSource) && nodesWithSource.length > 1)) + Object.values(nodes.modules.sources) + .filter((nodesWithSource) => Array.isArray(nodesWithSource) && nodesWithSource.length > 1) + .flat() .forEach((node) => { context.report({ node, @@ -127,8 +126,9 @@ function create(context) { } // Report multiple `aggregated type exports` from the same module (FLOW ES2015 modules) - flat(values(nodes.types.sources) - .filter((nodesWithSource) => Array.isArray(nodesWithSource) && nodesWithSource.length > 1)) + Object.values(nodes.types.sources) + .filter((nodesWithSource) => Array.isArray(nodesWithSource) && nodesWithSource.length > 1) + .flat() .forEach((node) => { context.report({ node, diff --git a/src/rules/no-anonymous-default-export.js b/src/rules/no-anonymous-default-export.js index 4f6947e81..0233b9cb9 100644 --- a/src/rules/no-anonymous-default-export.js +++ b/src/rules/no-anonymous-default-export.js @@ -3,10 +3,6 @@ * @author Duncan Beevers */ -import hasOwn from 'hasown'; -import values from 'object.values'; -import fromEntries from 'object.fromentries'; - import docsUrl from '../docsUrl'; const defs = { @@ -60,12 +56,12 @@ const defs = { }, }; -const schemaProperties = fromEntries(values(defs).map((def) => [def.option, { +const schemaProperties = Object.fromEntries(Object.values(defs).map((def) => [def.option, { description: def.description, type: 'boolean', }])); -const defaults = fromEntries(values(defs).map((def) => [def.option, hasOwn(def, 'default') ? def.default : false])); +const defaults = Object.fromEntries(Object.values(defs).map((def) => [def.option, Object.hasOwn(def, 'default') ? def.default : false])); module.exports = { meta: { diff --git a/src/rules/no-duplicates.js b/src/rules/no-duplicates.js index b8c8d848c..a50518ca8 100644 --- a/src/rules/no-duplicates.js +++ b/src/rules/no-duplicates.js @@ -1,7 +1,6 @@ import { getSourceCode } from 'eslint-module-utils/contextCompat'; import resolve from 'eslint-module-utils/resolve'; import semver from 'semver'; -import flatMap from 'array.prototype.flatmap'; import docsUrl from '../docsUrl'; @@ -95,7 +94,7 @@ function getFix(first, rest, sourceCode, context) { } const defaultImportNames = new Set( - flatMap([].concat(first, rest || []), (x) => getDefaultImportName(x) || []), + [].concat(first, rest || []).flatMap((x) => getDefaultImportName(x) || []), ); // Bail if there are multiple different default import names – it's up to the diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js index 358726299..3c82b667e 100644 --- a/src/rules/no-unused-modules.js +++ b/src/rules/no-unused-modules.js @@ -10,9 +10,6 @@ import resolve from 'eslint-module-utils/resolve'; import visit from 'eslint-module-utils/visit'; import { dirname, join, resolve as resolvePath } from 'path'; import readPkgUp from 'eslint-module-utils/readPkgUp'; -import values from 'object.values'; -import includes from 'array-includes'; -import flatMap from 'array.prototype.flatmap'; import { walkSync } from '../core/fsWalk'; import ExportMapBuilder from '../exportMap/builder'; @@ -97,8 +94,7 @@ function listFilesWithLegacyFunctions(src, extensions) { listFilesToProcess: originalListFilesToProcess, } = require('eslint/lib/util/glob-util'); const patterns = src.concat( - flatMap( - src, + src.flatMap( (pattern) => extensions.map((extension) => (/\*\*|\*\./).test(pattern) ? pattern : `${pattern}/**/*${extension}`), ), ); @@ -310,7 +306,7 @@ function resolveFiles(src, ignoreExports, context) { // prepare list of source files, don't consider files from node_modules const resolvedFiles = srcFileList.length && typeof srcFileList[0] === 'string' ? srcFileList.filter((filePath) => !isNodeModule(filePath)) - : flatMap(srcFileList, ({ filename }) => isNodeModule(filename) ? [] : filename); + : srcFileList.flatMap(({ filename }) => isNodeModule(filename) ? [] : filename); return new Set(resolvedFiles); } @@ -494,9 +490,9 @@ const fileIsInPkg = (file) => { }; const checkPkgFieldObject = (pkgField) => { - const pkgFieldFiles = flatMap(values(pkgField), (value) => typeof value === 'boolean' ? [] : join(basePath, value)); + const pkgFieldFiles = Object.values(pkgField).flatMap((value) => typeof value === 'boolean' ? [] : join(basePath, value)); - if (includes(pkgFieldFiles, file)) { + if (pkgFieldFiles.includes(file)) { return true; } }; diff --git a/src/rules/order.js b/src/rules/order.js index d6f25ddd3..90a4c17ab 100644 --- a/src/rules/order.js +++ b/src/rules/order.js @@ -1,10 +1,8 @@ 'use strict'; import minimatch from 'minimatch'; -import includes from 'array-includes'; import groupBy from 'object.groupby'; import { getScope, getSourceCode } from 'eslint-module-utils/contextCompat'; -import trimEnd from 'string.prototype.trimend'; import importType from '../core/importType'; import isStaticRequire from '../core/staticRequire'; @@ -326,7 +324,7 @@ function fixOutOfOrder(context, firstNode, secondNode, order, category) { const secondTrivia = sourceCode.text.slice(secondRoot.range[1], secondRootEnd); if (order === 'before') { - const trimmedTrivia = trimEnd(secondTrivia); + const trimmedTrivia = secondTrivia.trimEnd(); const gapCode = sourceCode.text.slice(firstRootEnd, secondRootStart - 1); const whitespaces = secondTrivia.slice(trimmedTrivia.length); context.report({ @@ -338,7 +336,7 @@ function fixOutOfOrder(context, firstNode, secondNode, order, category) { ), }); } else if (order === 'after') { - const trimmedTrivia = trimEnd(firstTrivia); + const trimmedTrivia = firstTrivia.trimEnd(); const gapCode = sourceCode.text.slice(secondRootEnd + 1, firstRootStart); const whitespaces = firstTrivia.slice(trimmedTrivia.length); context.report({ @@ -433,7 +431,7 @@ function getSorter(alphabetizeOptions) { const importB = getNormalizedValue(nodeB, alphabetizeOptions.caseInsensitive); let result = 0; - if (!includes(importA, '/') && !includes(importB, '/')) { + if (!importA.includes('/') && !importB.includes('/')) { result = compareString(importA, importB); } else { const A = importA.split('/'); diff --git a/tests/dep-time-travel.sh b/tests/dep-time-travel.sh index 665ca1ccf..ceb95be0e 100755 --- a/tests/dep-time-travel.sh +++ b/tests/dep-time-travel.sh @@ -2,7 +2,7 @@ # expected: ESLINT_VERSION numeric env var -echo "installing ${ESLINT_VERSION} in node ${TRAVIS_NODE_VERSION} with TS parser ${TS_PARSER:-default}..." +echo "installing ${ESLINT_VERSION} with TS parser ${TS_PARSER:-default}..." export NPM_CONFIG_LEGACY_PEER_DEPS=true @@ -19,10 +19,6 @@ if [[ -n "$TS_PARSER" ]]; then # if TS parser is manually set, always use it elif [[ "$ESLINT_VERSION" -lt "5" ]]; then # completely remove the new TypeScript parser for ESLint < v5 echo "Removing @typescript-eslint/parser..." npm uninstall --no-save @typescript-eslint/parser -elif [[ "$TRAVIS_NODE_VERSION" -lt "10" ]]; then # TS parser 3 requires node 10+ - npm i --no-save "@typescript-eslint/parser@3" -elif [[ "$TRAVIS_NODE_VERSION" -lt "12" ]]; then # TS parser 4 requires node 12+ - npm i --no-save "@typescript-eslint/parser@4" fi # use these alternate TypeScript dependencies for ESLint < v4 @@ -37,12 +33,6 @@ elif [[ "$ESLINT_VERSION" -lt "7" ]]; then npm i --no-save typescript-eslint-parser@20 fi -# typescript-eslint-parser 1.1.1+ is not compatible with node 6 -if [[ "$TRAVIS_NODE_VERSION" -lt "8" ]]; then - echo "Downgrading eslint-import-resolver-typescript..." - npm i --no-save eslint-import-resolver-typescript@1.0.2 -fi - if [ "${ESLINT_VERSION}" = '8' ]; then # This is a workaround for the crash in the initial processing of the ESLint class. echo "Installing self" diff --git a/tests/src/core/importType.js b/tests/src/core/importType.js index c4dca866e..a8ae90ae9 100644 --- a/tests/src/core/importType.js +++ b/tests/src/core/importType.js @@ -1,6 +1,6 @@ import { expect } from 'chai'; +import { isBuiltin } from 'node:module'; import * as path from 'path'; -import isCoreModule from 'is-core-module'; import importType, { isExternalModule, isScoped, isAbsolute } from 'core/importType'; @@ -17,9 +17,9 @@ describe('importType(name)', function () { }); it("should return 'builtin' for node.js modules", function () { - ['fs', 'fs/promises', 'path'].filter((x) => isCoreModule(x)).forEach((x) => { + ['fs', 'fs/promises', 'path'].filter((x) => isBuiltin(x)).forEach((x) => { expect(importType(x, context)).to.equal('builtin'); - if (isCoreModule(`node:${x}`)) { + if (isBuiltin(`node:${x}`)) { expect(importType(`node:${x}`, context)).to.equal('builtin'); } }); diff --git a/tests/src/rules/namespace.js b/tests/src/rules/namespace.js index 2a31d57e1..c6930318c 100644 --- a/tests/src/rules/namespace.js +++ b/tests/src/rules/namespace.js @@ -1,6 +1,5 @@ import { test, SYNTAX_CASES, getTSParsers, testVersion, testFilePath, parsers } from '../utils'; import { RuleTester } from '../rule-tester'; -import flatMap from 'array.prototype.flatmap'; const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } }); const rule = require('rules/namespace'); @@ -143,7 +142,7 @@ const valid = [ }), // Typescript - ...flatMap(getTSParsers(), (parser) => [ + ...getTSParsers().flatMap((parser) => [ test({ code: ` import * as foo from "./typescript-declare-nested" diff --git a/tests/src/rules/newline-after-import.js b/tests/src/rules/newline-after-import.js index 984e89855..9e0c1d550 100644 --- a/tests/src/rules/newline-after-import.js +++ b/tests/src/rules/newline-after-import.js @@ -1,5 +1,4 @@ import { RuleTester, withoutAutofixOutput } from '../rule-tester'; -import flatMap from 'array.prototype.flatmap'; import semver from 'semver'; import { version as tsEslintVersion } from 'typescript-eslint-parser/package.json'; @@ -275,7 +274,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), { parserOptions: { sourceType: 'module' }, parser: parsers.BABEL_OLD, }, - flatMap(getTSParsers(), (parser) => [].concat( + getTSParsers().flatMap((parser) => [].concat( { code: ` import { ExecaReturnValue } from 'execa'; diff --git a/tests/src/rules/no-cycle.js b/tests/src/rules/no-cycle.js index ae4baab66..ce9da2322 100644 --- a/tests/src/rules/no-cycle.js +++ b/tests/src/rules/no-cycle.js @@ -1,7 +1,6 @@ import { parsers, test as _test, testFilePath, testVersion as _testVersion } from '../utils'; import { RuleTester } from '../rule-tester'; -import flatMap from 'array.prototype.flatmap'; const ruleTester = new RuleTester(); const rule = require('rules/no-cycle'); @@ -56,7 +55,7 @@ const cases = { }, }), - flatMap(testDialects, (testDialect) => [ + testDialects.flatMap((testDialect) => [ test({ code: `import { foo } from "./${testDialect}/depth-two"`, options: [{ maxDepth: 1 }], @@ -143,10 +142,10 @@ const cases = { }), // Ensure behavior does not change for those tests, with or without ` - flatMap(testDialects, (testDialect) => flatMap([ + testDialects.flatMap((testDialect) => [ {}, { allowUnsafeDynamicCyclicDependency: true }, - ], (opts) => [ + ].flatMap((opts) => [ test({ code: `import { foo } from "./${testDialect}/depth-one"`, options: [{ ...opts }], @@ -285,7 +284,7 @@ const cases = { }; ruleTester.run('no-cycle', rule, { - valid: flatMap(cases.valid, (testCase) => [ + valid: cases.valid.flatMap((testCase) => [ testCase, { ...testCase, @@ -297,7 +296,7 @@ ruleTester.run('no-cycle', rule, { }, ]), - invalid: flatMap(cases.invalid, (testCase) => [ + invalid: cases.invalid.flatMap((testCase) => [ testCase, { ...testCase, diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js index cf57a3d59..400dce542 100644 --- a/tests/src/rules/no-duplicates.js +++ b/tests/src/rules/no-duplicates.js @@ -5,7 +5,6 @@ import jsxConfig from '../../../config/react'; import { RuleTester, withoutAutofixOutput } from '../rule-tester'; import eslintPkg from 'eslint/package.json'; import semver from 'semver'; -import flatMap from 'array.prototype.flatmap'; const ruleTester = new RuleTester(); const rule = require('rules/no-duplicates'); @@ -131,7 +130,7 @@ ruleTester.run('no-duplicates', rule, { }), // These test cases use duplicate import identifiers, which causes a fatal parsing error using ESPREE (default) and TS_OLD. - ...flatMap([parsers.BABEL_OLD, parsers.TS_NEW], (parser) => { + ...[parsers.BABEL_OLD, parsers.TS_NEW].flatMap((parser) => { if (!parser) { return []; } // TS_NEW is not always available return [ // #2347: duplicate identifiers should be removed diff --git a/tests/src/rules/no-dynamic-require.js b/tests/src/rules/no-dynamic-require.js index fc7cf2b06..5f3cffa0a 100644 --- a/tests/src/rules/no-dynamic-require.js +++ b/tests/src/rules/no-dynamic-require.js @@ -1,7 +1,6 @@ import { parsers, test, testVersion } from '../utils'; import { RuleTester } from '../rule-tester'; -import flatMap from 'array.prototype.flatmap'; const ruleTester = new RuleTester(); const rule = require('rules/no-dynamic-require'); @@ -29,7 +28,7 @@ ruleTester.run('no-dynamic-require', rule, { test({ code: 'var foo = require("@scope/foo")' }), //dynamic import - ...flatMap([parsers.ESPREE, parsers.BABEL_OLD], (parser) => { + ...[parsers.ESPREE, parsers.BABEL_OLD].flatMap((parser) => { const _test = parser === parsers.ESPREE ? (testObj) => testVersion('>= 6.2.0', () => testObj) : (testObj) => test(testObj); @@ -141,7 +140,7 @@ ruleTester.run('no-dynamic-require', rule, { }), // dynamic import - ...flatMap([parsers.ESPREE, parsers.BABEL_OLD], (parser) => { + ...[parsers.ESPREE, parsers.BABEL_OLD].flatMap((parser) => { const _test = parser === parsers.ESPREE ? (testObj) => testVersion('>= 6.2.0', () => testObj) : (testObj) => test(testObj); diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js index 4a465eb39..6280f7dfa 100644 --- a/tests/src/rules/no-extraneous-dependencies.js +++ b/tests/src/rules/no-extraneous-dependencies.js @@ -4,7 +4,6 @@ import path from 'path'; import fs from 'fs'; import { RuleTester } from '../rule-tester'; -import flatMap from 'array.prototype.flatmap'; const ruleTester = new RuleTester(); const typescriptRuleTester = new RuleTester(typescriptConfig); @@ -35,7 +34,7 @@ const { ruleTester.run('no-extraneous-dependencies', rule, { valid: [ - ...flatMap(Object.keys(deps).concat(Object.keys(devDeps)), (pkg) => [ + ...Object.keys(deps).concat(Object.keys(devDeps)).flatMap((pkg) => [ test({ code: `import "${pkg}"` }), test({ code: `import foo, { bar } from "${pkg}"` }), test({ code: `require("${pkg}")` }), diff --git a/tests/src/rules/no-internal-modules.js b/tests/src/rules/no-internal-modules.js index 9fa91ea3d..9bcf43292 100644 --- a/tests/src/rules/no-internal-modules.js +++ b/tests/src/rules/no-internal-modules.js @@ -1,5 +1,4 @@ import { RuleTester } from '../rule-tester'; -import flatMap from 'array.prototype.flatmap'; import rule from 'rules/no-internal-modules'; import { test, testFilePath, getTSParsers } from '../utils'; @@ -130,7 +129,7 @@ ruleTester.run('no-internal-modules', rule, { } `, }), - ...flatMap(getTSParsers(), (parser) => [ + ...getTSParsers().flatMap((parser) => [ test({ code: ` export class AuthHelper { diff --git a/tests/src/rules/no-nodejs-modules.js b/tests/src/rules/no-nodejs-modules.js index cf131ffee..68fcb0476 100644 --- a/tests/src/rules/no-nodejs-modules.js +++ b/tests/src/rules/no-nodejs-modules.js @@ -1,7 +1,7 @@ +import { isBuiltin } from 'node:module'; import { test } from '../utils'; import { RuleTester } from '../rule-tester'; -const isCore = require('is-core-module'); const ruleTester = new RuleTester(); const rule = require('rules/no-nodejs-modules'); @@ -56,7 +56,7 @@ ruleTester.run('no-nodejs-modules', rule, { allow: ['path', 'events'], }], }), - isCore('node:events') ? [ + isBuiltin('node:events') ? [ test({ code: 'import events from "node:events"', options: [{ @@ -70,7 +70,7 @@ ruleTester.run('no-nodejs-modules', rule, { }], }), ] : [], - isCore('node:path') ? [ + isBuiltin('node:path') ? [ test({ code: 'import path from "node:path"', options: [{ @@ -84,7 +84,7 @@ ruleTester.run('no-nodejs-modules', rule, { }], }), ] : [], - isCore('node:path') && isCore('node:events') ? test({ + isBuiltin('node:path') && isBuiltin('node:events') ? test({ code: 'import path from "node:path";import events from "node:events"', options: [{ allow: ['node:path', 'node:events'], @@ -115,7 +115,7 @@ ruleTester.run('no-nodejs-modules', rule, { }], errors: [error('Do not import Node.js builtin module "fs"')], }), - isCore('node:path') ? [ + isBuiltin('node:path') ? [ test({ code: 'import path from "node:path"', errors: [error('Do not import Node.js builtin module "node:path"')], @@ -125,7 +125,7 @@ ruleTester.run('no-nodejs-modules', rule, { errors: [error('Do not import Node.js builtin module "node:path"')], }), ] : [], - isCore('node:fs') ? [ + isBuiltin('node:fs') ? [ test({ code: 'import fs from "node:fs"', errors: [error('Do not import Node.js builtin module "node:fs"')], diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js index ea62cec71..82e41c5bd 100644 --- a/tests/src/rules/order.js +++ b/tests/src/rules/order.js @@ -3,9 +3,8 @@ import { test, getTSParsers, getNonDefaultParsers, testFilePath, parsers } from import { RuleTester, withoutAutofixOutput } from '../rule-tester'; import eslintPkg from 'eslint/package.json'; import semver from 'semver'; -import flatMap from 'array.prototype.flatmap'; +import { isBuiltin } from 'node:module'; import { resolve } from 'path'; -import isCoreModule from 'is-core-module'; import { default as babelPresetFlow } from 'babel-preset-flow'; const ruleTester = new RuleTester(); @@ -217,7 +216,7 @@ ruleTester.run('order', rule, { var index = require('./'); `, }), - ...flatMap(getTSParsers(), (parser) => [ + ...getTSParsers().flatMap((parser) => [ // Export equals expressions should be on top alongside with ordinary import-statements. test({ code: ` @@ -853,7 +852,7 @@ ruleTester.run('order', rule, { pathGroupsExcludedImportTypes: [], }], }), - ...flatMap(getTSParsers, (parser) => [ + ...getTSParsers().flatMap((parser) => [ // Order of the `import ... = require(...)` syntax test({ code: ` @@ -1712,7 +1711,7 @@ ruleTester.run('order', rule, { message: '`fs` import should occur after import of `../foo/bar`', }], }), - ...flatMap(getTSParsers(), (parser) => [ + ...getTSParsers().flatMap((parser) => [ // Order of the `import ... = require(...)` syntax test({ code: ` @@ -3261,7 +3260,7 @@ context('TypeScript', function () { }, ], }), - isCoreModule('node:child_process') && isCoreModule('node:fs/promises') ? [ + isBuiltin('node:child_process') && isBuiltin('node:fs/promises') ? [ test({ code: ` import express from 'express'; @@ -3598,7 +3597,7 @@ context('TypeScript', function () { }), ] : [], - isCoreModule('node:child_process') && isCoreModule('node:fs/promises') ? [ + isBuiltin('node:child_process') && isBuiltin('node:fs/promises') ? [ test({ code: ` import express from 'express';