Repository: un-ts/eslint-plugin-import-x
Pull request #56 (2024-03-18 17:40:11)

ci: run more tests

changeset-bot[bot]: ###  ⚠️  No Changeset found

Latest commit: 676f0756c93789ada055b8e099bcc562614c7445

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. **If these changes should result in a version bump, you need to add a changeset.**

<details><summary>This PR includes no changesets</summary>

  When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

</details>

[Click here to learn what changesets are, and how to add one](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add a changeset to this PR](https://github.com/un-ts/eslint-plugin-import-x/new/ci/test?filename=.changeset/rotten-doors-battle.md&value=---%0A%22eslint-plugin-import-x%22%3A%20patch%0A---%0A%0Aci%3A%20run%20more%20tests%0A)


codesandbox-ci[bot]: This pull request is automatically built and testable in [CodeSandbox](https://codesandbox.io).

  To see build info of the built libraries, click [here](https://ci.codesandbox.io/status/un-ts/eslint-plugin-import-x/pr/56/builds/484877) or the icon next to each commit SHA.

Patch:
diff --git a/.changeset/tricky-spiders-happen.md b/.changeset/tricky-spiders-happen.md
new file mode 100644
index 00000000..fa1f023e
--- /dev/null
+++ b/.changeset/tricky-spiders-happen.md
@@ -0,0 +1,5 @@
+---
+"eslint-plugin-import-x": patch
+---
+
+fix: known compatibility issues
diff --git a/.eslintrc.js b/.eslintrc.js
index 191df857..eb4d6d70 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -1,7 +1,9 @@
+const eslintPkg = require('eslint/package.json')
+const semver = require('semver')
+
 /**
  * @type {import('eslint').Linter.Config}
  */
-// eslint-disable-next-line unicorn/prefer-module
 module.exports = {
   root: true,
   extends: [
@@ -10,9 +12,11 @@ module.exports = {
     'plugin:eslint-plugin/recommended',
     'plugin:import-x/recommended',
     'plugin:n/recommended',
-    'plugin:unicorn/recommended',
+    semver.satisfies(eslintPkg.version, '>=8')
+      ? 'plugin:unicorn/recommended'
+      : undefined,
     'plugin:prettier/recommended',
-  ],
+  ].filter(Boolean),
   env: {
     node: true,
     es6: true,
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 84dfb151..895579bf 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -6,14 +6,21 @@ on:
 
 jobs:
   ci:
-    name: Lint and Test with Node.js ${{ matrix.node }} on ${{ matrix.os }}
+    name: Lint and Test with Node.js ${{ matrix.node }} and ESLint ${{ matrix.eslint }} on ${{ matrix.os }}
     strategy:
       matrix:
         os:
+          - macos-latest
           - ubuntu-latest
+          # - windows-latest
         node:
+          - 16
           - 18
           - 20
+        eslint:
+          - 7.2
+          - 7
+          - 8
     runs-on: ${{ matrix.os }}
     steps:
       - name: Checkout Repo
@@ -31,20 +38,29 @@ jobs:
           # https://github.com/actions/setup-node/issues/531#issuecomment-1819151412
           SKIP_YARN_COREPACK_CHECK: 1
 
+      - name: Install ESLint ${{ matrix.eslint }}
+        run: |
+          yarn add -D --ignore-engines eslint@${{ matrix.eslint }}
+
       - name: Install Dependencies
-        run: yarn --immutable
+        run: yarn --ignore-engines
         env:
           SKIP_YARN_COREPACK_CHECK: 1
 
-      - name: Build, Lint and Test
+      - name: Build and Test
         run: |
-          yarn build
-          yarn lint
+          yarn test-compiled
           yarn test
+        env:
+          SKIP_YARN_COREPACK_CHECK: 1
+
+      - name: Lint
+        run: yarn lint
         env:
           EFF_NO_LINK_RULES: true
           PARSER_NO_WATCH: true
           SKIP_YARN_COREPACK_CHECK: 1
+        if: ${{ matrix.node == 20 && matrix.eslint == 8 }}
 
       - name: Codecov
         uses: codecov/codecov-action@v3
diff --git a/src/rules/exports-last.ts b/src/rules/exports-last.ts
index b8bc0b1c..a5dca9be 100644
--- a/src/rules/exports-last.ts
+++ b/src/rules/exports-last.ts
@@ -2,6 +2,17 @@ import type { TSESTree } from '@typescript-eslint/utils'
 
 import { createRule } from '../utils'
 
+const findLastIndex = <T>(array: T[], predicate: (item: T) => boolean) => {
+  let i = array.length - 1
+  while (i >= 0) {
+    if (predicate(array[i])) {
+      return i
+    }
+    i--
+  }
+  return -1
+}
+
 function isNonExportStatement({ type }: TSESTree.Node) {
   return (
     type !== 'ExportDefaultDeclaration' &&
@@ -27,8 +38,10 @@ export = createRule({
   create(context) {
     return {
       Program({ body }) {
-        const lastNonExportStatementIndex =
-          body.findLastIndex(isNonExportStatement)
+        const lastNonExportStatementIndex = findLastIndex(
+          body,
+          isNonExportStatement,
+        )
 
         if (lastNonExportStatementIndex !== -1) {
           for (const node of body.slice(0, lastNonExportStatementIndex)) {
diff --git a/src/rules/no-unused-modules.ts b/src/rules/no-unused-modules.ts
index 0064d499..4112f208 100644
--- a/src/rules/no-unused-modules.ts
+++ b/src/rules/no-unused-modules.ts
@@ -6,7 +6,6 @@
 import path from 'node:path'
 
 import { TSESTree } from '@typescript-eslint/utils'
-import { FileEnumerator } from 'eslint/use-at-your-own-risk'
 
 import type { FileExtension, RuleContext } from '../types'
 import {
@@ -20,11 +19,20 @@ import {
 } from '../utils'
 
 function listFilesToProcess(src: string[], extensions: FileExtension[]) {
-  const e = new FileEnumerator({
+  // eslint-disable-next-line @typescript-eslint/consistent-type-imports
+  let FileEnumerator: typeof import('eslint/use-at-your-own-risk').FileEnumerator
+
+  try {
+    ;({ FileEnumerator } = require('eslint/use-at-your-own-risk'))
+  } catch {
+    ;({ FileEnumerator } = require('eslint/lib/cli-engine/file-enumerator'))
+  }
+
+  const enumerator = new FileEnumerator({
     extensions,
   })
 
-  return Array.from(e.iterateFiles(src), ({ filePath, ignored }) => ({
+  return Array.from(enumerator.iterateFiles(src), ({ filePath, ignored }) => ({
     ignored,
     filename: filePath,
   }))
diff --git a/tsconfig.base.json b/tsconfig.base.json
index ad0cff87..0f523819 100644
--- a/tsconfig.base.json
+++ b/tsconfig.base.json
@@ -1,6 +1,7 @@
 {
   "extends": "@1stg/tsconfig/node",
   "compilerOptions": {
+    "lib": ["ES2022"],
     "paths": {
       "eslint-plugin-import-x": ["./src"],
       "eslint-plugin-import-x/package.json": ["./package.json"],


Test patch:
diff --git a/test/rules/no-unused-modules.spec.ts b/test/rules/no-unused-modules.spec.ts
index 6b6bb85e..79c58e29 100644
--- a/test/rules/no-unused-modules.spec.ts
+++ b/test/rules/no-unused-modules.spec.ts
@@ -1,8 +1,6 @@
 import fs from 'node:fs'
 
 import { TSESLint } from '@typescript-eslint/utils'
-// @ts-expect-error - no types yet
-import { FlatRuleTester } from 'eslint/use-at-your-own-risk'
 
 import { test, testVersion, testFilePath, parsers } from '../utils'
 
@@ -1525,8 +1523,21 @@ describe('parser ignores prefixes like BOM and hashbang', () => {
     invalid: [],
   })
 })
-describe('supports flat eslint', () => {
-  const flatRuleTester = new FlatRuleTester() as TSESLint.RuleTester
+
+let FlatRuleTester: typeof TSESLint.RuleTester | undefined
+
+try {
+  ;({ FlatRuleTester } = require('eslint/use-at-your-own-risk'))
+} catch {
+  //
+}
+
+;(FlatRuleTester ? describe : describe.skip)('supports flat eslint', () => {
+  if (typeof FlatRuleTester !== 'function') {
+    return
+  }
+
+  const flatRuleTester = new FlatRuleTester()
   flatRuleTester.run('no-unused-modules', rule, {
     valid: [
       {