diff --git a/.github/workflows/node-4+.yml b/.github/workflows/node-4+.yml index 2925adda8..c1e46e31a 100644 --- a/.github/workflows/node-4+.yml +++ b/.github/workflows/node-4+.yml @@ -17,7 +17,9 @@ jobs: with: versionsAsRoot: true type: majors - preset: '>= 6' # preset: '>=4' # see https://github.com/import-js/eslint-plugin-import/issues/2053 + # preset: '>= 6' # preset: '>=4' # see https://github.com/import-js/eslint-plugin-import/issues/2053 + # target Node.js 12 now, see https://github.com/un-es/eslint-plugin-i/issues/10 & https://github.com/un-es/eslint-plugin-i/pull/11 + preset: '>= 12' latest: needs: [matrix] @@ -31,11 +33,6 @@ jobs: eslint: - 8 - 7 - - 6 - - 5 - - 4 - - 3 - - 2 include: - node-version: 'lts/*' eslint: 7 diff --git a/package.json b/package.json index f58cbcfd8..e28a2cda5 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "A fork of `eslint-plugin-import` using `get-tsconfig` to replace `tsconfig-paths` and heavy `typescript` under the hood.", "funding": "https://opencollective.com/unts", "engines": { - "node": ">=4" + "node": ">=12" }, "main": "lib/index.js", "directories": { @@ -85,6 +85,7 @@ "fs-copy-file-sync": "^1.1.1", "glob": "^7.2.3", "in-publish": "^2.0.1", + "is-core-module": "^2.12.1", "linklocal": "^2.8.2", "lodash.isarray": "^4.0.0", "mocha": "^3.5.3", @@ -98,26 +99,17 @@ "typescript-eslint-parser": "^15 || ^20 || ^22" }, "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + "eslint": "^7.2.0 || ^8" }, "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.findlastindex": "^1.2.2", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.7", "eslint-module-utils": "^2.8.0", - "get-tsconfig": "^4.6.0", - "has": "^1.0.3", - "is-core-module": "^2.12.1", + "get-tsconfig": "^4.6.2", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.fromentries": "^2.0.6", - "object.groupby": "^1.0.0", - "object.values": "^1.1.6", "resolve": "^1.22.3", - "semver": "^6.3.1" + "semver": "^7.5.3" } } diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js index 8eb2db5ad..dd1ccb371 100644 --- a/resolvers/webpack/index.js +++ b/resolvers/webpack/index.js @@ -10,9 +10,10 @@ const fs = require('fs'); const isCore = require('is-core-module'); const resolve = require('resolve'); const semver = require('semver'); -const has = require('has'); const isRegex = require('is-regex'); +const has = Function.bind.bind(Function.prototype.call)(Object.prototype.hasOwnProperty); + const log = require('debug')('eslint-plugin-import:resolver:webpack'); exports.interfaceVersion = 2; diff --git a/src/ExportMap.js b/src/ExportMap.js index 1b1de70ae..f41615d13 100644 --- a/src/ExportMap.js +++ b/src/ExportMap.js @@ -17,7 +17,7 @@ import * as unambiguous from 'eslint-module-utils/unambiguous'; import { getTsconfig } from 'get-tsconfig'; -import includes from 'array-includes'; +const includes = Function.bind.bind(Function.prototype.call)(Array.prototype.includes); const log = debug('eslint-plugin-import:ExportMap'); diff --git a/src/core/importType.js b/src/core/importType.js index 6a37d1bb1..61530cdef 100644 --- a/src/core/importType.js +++ b/src/core/importType.js @@ -1,8 +1,14 @@ 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'; +import { Module } from 'module'; + +const isCoreModule = (pkg) => Module.builtinModules.includes( + pkg.startsWith('node:') + ? pkg.slice(5) + : pkg, +); function baseModule(name) { if (isScoped(name)) { diff --git a/src/rules/export.js b/src/rules/export.js index c540f1e3c..d1db11997 100644 --- a/src/rules/export.js +++ b/src/rules/export.js @@ -1,7 +1,8 @@ import ExportMap, { recursivePatternCapture } from '../ExportMap'; import docsUrl from '../docsUrl'; -import includes from 'array-includes'; -import flatMap from 'array.prototype.flatmap'; + +const includes = Function.bind.bind(Function.prototype.call)(Array.prototype.includes); +const flatMap = Function.bind.bind(Function.prototype.call)(Array.prototype.flatMap); /* Notes on TypeScript namespaces aka TSModuleDeclaration: diff --git a/src/rules/exports-last.js b/src/rules/exports-last.js index 1e79f8339..7e9d006e3 100644 --- a/src/rules/exports-last.js +++ b/src/rules/exports-last.js @@ -1,7 +1,16 @@ -import findLastIndex from 'array.prototype.findlastindex'; - import docsUrl from '../docsUrl'; +const findLastIndex = (array, predicate) => { + let i = array.length - 1; + while (i >= 0) { + if (predicate(array[i])) { + return i; + } + i--; + } + return -1; +}; + function isNonExportStatement({ type }) { return type !== 'ExportDefaultDeclaration' && type !== 'ExportNamedDeclaration' diff --git a/src/rules/group-exports.js b/src/rules/group-exports.js index 7978130d3..0c35ee154 100644 --- a/src/rules/group-exports.js +++ b/src/rules/group-exports.js @@ -1,6 +1,7 @@ import docsUrl from '../docsUrl'; -import values from 'object.values'; -import flat from 'array.prototype.flat'; + +const { values } = Object; +const flat = Function.bind.bind(Function.prototype.call)(Array.prototype.flat); const meta = { type: 'suggestion', diff --git a/src/rules/no-anonymous-default-export.js b/src/rules/no-anonymous-default-export.js index 59a3cbfda..80a73c86b 100644 --- a/src/rules/no-anonymous-default-export.js +++ b/src/rules/no-anonymous-default-export.js @@ -3,12 +3,11 @@ * @author Duncan Beevers */ -import has from 'has'; -import values from 'object.values'; -import fromEntries from 'object.fromentries'; - import docsUrl from '../docsUrl'; +const has = Function.bind.bind(Function.prototype.call)(Object.prototype.hasOwnProperty); +const { fromEntries, values } = Object; + const defs = { ArrayExpression: { option: 'allowArray', diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js index ecba3a19c..60fb1952f 100644 --- a/src/rules/no-unused-modules.js +++ b/src/rules/no-unused-modules.js @@ -9,9 +9,10 @@ import resolve from 'eslint-module-utils/resolve'; import visit from 'eslint-module-utils/visit'; import { dirname, join } 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'; + +const { values } = Object; +const includes = Function.bind.bind(Function.prototype.call)(Array.prototype.includes); +const flatMap = Function.bind.bind(Function.prototype.call)(Array.prototype.flatMap); import Exports, { recursivePatternCapture } from '../ExportMap'; import docsUrl from '../docsUrl'; diff --git a/src/rules/order.js b/src/rules/order.js index 6f70db263..c656584f4 100644 --- a/src/rules/order.js +++ b/src/rules/order.js @@ -1,13 +1,19 @@ 'use strict'; import minimatch from 'minimatch'; -import includes from 'array-includes'; -import groupBy from 'object.groupby'; import importType from '../core/importType'; import isStaticRequire from '../core/staticRequire'; import docsUrl from '../docsUrl'; +const includes = Function.bind.bind(Function.prototype.call)(Array.prototype.includes); +// This is a **non-spec compliant** but works in practice replacement of `object.groupby` package. +const groupBy = (array, grouper) => array.reduce((acc, curr, index) => { + const key = grouper(curr, index); + (acc[key] = acc[key] || []).push(curr); + return acc; +}, {}); + const defaultGroups = ['builtin', 'external', 'parent', 'sibling', 'index']; // REPORTING AND FIXING diff --git a/tests/src/rules/namespace.js b/tests/src/rules/namespace.js index 1475ae9b7..43a5cbad0 100644 --- a/tests/src/rules/namespace.js +++ b/tests/src/rules/namespace.js @@ -1,6 +1,7 @@ import { test, SYNTAX_CASES, getTSParsers, testVersion, testFilePath, parsers } from '../utils'; import { RuleTester } from 'eslint'; -import flatMap from 'array.prototype.flatmap'; + +const flatMap = Function.bind.bind(Function.prototype.call)(Array.prototype.flatMap); const ruleTester = new RuleTester({ env: { es6: true } }); const rule = require('rules/namespace'); diff --git a/tests/src/rules/newline-after-import.js b/tests/src/rules/newline-after-import.js index 8f3338eee..cda55ff59 100644 --- a/tests/src/rules/newline-after-import.js +++ b/tests/src/rules/newline-after-import.js @@ -1,10 +1,11 @@ import { RuleTester } from 'eslint'; -import flatMap from 'array.prototype.flatmap'; import semver from 'semver'; import { version as tsEslintVersion } from 'typescript-eslint-parser/package.json'; import { getTSParsers, parsers, testVersion } from '../utils'; +const flatMap = Function.bind.bind(Function.prototype.call)(Array.prototype.flatMap); + const IMPORT_ERROR_MESSAGE = 'Expected 1 empty line after import statement not followed by another import.'; const IMPORT_ERROR_MESSAGE_MULTIPLE = (count) => `Expected ${count} empty lines after import statement not followed by another import.`; const REQUIRE_ERROR_MESSAGE = 'Expected 1 empty line after require statement not followed by another require.'; diff --git a/tests/src/rules/no-cycle.js b/tests/src/rules/no-cycle.js index d2adbf61f..d1c184919 100644 --- a/tests/src/rules/no-cycle.js +++ b/tests/src/rules/no-cycle.js @@ -1,7 +1,8 @@ import { parsers, test as _test, testFilePath, testVersion as _testVersion } from '../utils'; import { RuleTester } from 'eslint'; -import flatMap from 'array.prototype.flatmap'; + +const flatMap = Function.bind.bind(Function.prototype.call)(Array.prototype.flatMap); const ruleTester = new RuleTester(); const rule = require('rules/no-cycle'); diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js index d61fda86e..8316f67fe 100644 --- a/tests/src/rules/no-duplicates.js +++ b/tests/src/rules/no-duplicates.js @@ -5,7 +5,8 @@ import jsxConfig from '../../../config/react'; import { RuleTester } from 'eslint'; import eslintPkg from 'eslint/package.json'; import semver from 'semver'; -import flatMap from 'array.prototype.flatmap'; + +const flatMap = Function.bind.bind(Function.prototype.call)(Array.prototype.flatMap); const ruleTester = new RuleTester(); const rule = require('rules/no-duplicates'); diff --git a/tests/src/rules/no-dynamic-require.js b/tests/src/rules/no-dynamic-require.js index e316470ec..3ecc4275d 100644 --- a/tests/src/rules/no-dynamic-require.js +++ b/tests/src/rules/no-dynamic-require.js @@ -1,7 +1,8 @@ import { parsers, test, testVersion } from '../utils'; import { RuleTester } from 'eslint'; -import flatMap from 'array.prototype.flatmap'; + +const flatMap = Function.bind.bind(Function.prototype.call)(Array.prototype.flatMap); const ruleTester = new RuleTester(); const rule = require('rules/no-dynamic-require'); diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js index 21561615c..6cf9e2403 100644 --- a/tests/src/rules/no-extraneous-dependencies.js +++ b/tests/src/rules/no-extraneous-dependencies.js @@ -4,7 +4,8 @@ import path from 'path'; import fs from 'fs'; import { RuleTester } from 'eslint'; -import flatMap from 'array.prototype.flatmap'; + +const flatMap = Function.bind.bind(Function.prototype.call)(Array.prototype.flatMap); const ruleTester = new RuleTester(); const typescriptRuleTester = new RuleTester(typescriptConfig); diff --git a/tests/src/rules/no-internal-modules.js b/tests/src/rules/no-internal-modules.js index c1c301545..c3d23332f 100644 --- a/tests/src/rules/no-internal-modules.js +++ b/tests/src/rules/no-internal-modules.js @@ -1,9 +1,10 @@ import { RuleTester } from 'eslint'; -import flatMap from 'array.prototype.flatmap'; import rule from 'rules/no-internal-modules'; import { test, testFilePath, getTSParsers } from '../utils'; +const flatMap = Function.bind.bind(Function.prototype.call)(Array.prototype.flatMap); + const ruleTester = new RuleTester(); ruleTester.run('no-internal-modules', rule, { diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js index 2a44aa06a..20cdbc232 100644 --- a/tests/src/rules/order.js +++ b/tests/src/rules/order.js @@ -3,11 +3,12 @@ import { test, getTSParsers, getNonDefaultParsers, testFilePath, parsers } from import { RuleTester } from 'eslint'; import eslintPkg from 'eslint/package.json'; import semver from 'semver'; -import flatMap from 'array.prototype.flatmap'; import { resolve } from 'path'; import isCoreModule from 'is-core-module'; import { default as babelPresetFlow } from 'babel-preset-flow'; +const flatMap = Function.bind.bind(Function.prototype.call)(Array.prototype.flatMap); + const ruleTester = new RuleTester(); const flowRuleTester = new RuleTester({ parser: resolve(__dirname, '../../../node_modules/babel-eslint'),