From 9d6b13e4b01957552c9fff66f873fa1de22a9a44 Mon Sep 17 00:00:00 2001
From: Brian DeHamer <bdehamer@github.com>
Date: Tue, 31 Dec 2024 12:45:24 -0800
Subject: [PATCH] refactor eslint config

Signed-off-by: Brian DeHamer <bdehamer@github.com>
---
 .github/workflows/ci.yml                     |   4 +-
 eslint.config.mjs                            |  66 +++---
 package-lock.json                            | 217 +++++++++++--------
 package.json                                 |   5 +-
 packages/cli/package.json                    |   2 +-
 packages/cli/src/commands/download-target.ts |  10 +-
 packages/cli/tsconfig.json                   |   2 +-
 packages/client/src/fetcher.ts               |   3 +-
 packages/client/src/store.ts                 |  10 +
 packages/models/src/file.ts                  |   2 +-
 packages/models/src/metadata.ts              |   1 +
 packages/models/tests/base.test.ts           |   9 +-
 packages/models/tests/key.test.ts            |   2 +-
 packages/models/tests/role.test.ts           |   6 +-
 packages/models/tests/verify.test.ts         |  11 +-
 packages/repo-mock/tests/index.test.ts       |   4 +
 16 files changed, 204 insertions(+), 150 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 0227e4ef..ed39e980 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -23,12 +23,12 @@ jobs:
           cache: npm
       - name: Install dependencies
         run: npm ci
+      - name: Run build
+        run: npm run build
       - name: Run linter
         run: npm run lint:check
       - name: Run formatter
         run: npm run prettier:check
-      - name: Run build
-        run: npm run build
 
   run-tests:
     name: Run tests
diff --git a/eslint.config.mjs b/eslint.config.mjs
index 87b0bf98..94695170 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -1,42 +1,32 @@
-import typescriptEslint from "@typescript-eslint/eslint-plugin";
-import tsParser from "@typescript-eslint/parser";
-import path from "node:path";
-import { fileURLToPath } from "node:url";
-import js from "@eslint/js";
-import { FlatCompat } from "@eslint/eslintrc";
-
-const __filename = fileURLToPath(import.meta.url);
-const __dirname = path.dirname(__filename);
-const compat = new FlatCompat({
-    baseDirectory: __dirname,
-    recommendedConfig: js.configs.recommended,
-    allConfig: js.configs.all
-});
-
-export default [{
-    ignores: ["**/node_modules", "**/dist", "**/*.js"],
-}, ...compat.extends(
-    "eslint:recommended",
-    "plugin:@typescript-eslint/eslint-recommended",
-    "plugin:@typescript-eslint/recommended",
-), {
-    files: ["**/*.ts", "**/*.tsx"],
-
-    plugins: {
-        "@typescript-eslint": typescriptEslint,
-    },
-
+import eslint from '@eslint/js';
+import tseslint from 'typescript-eslint';
+export default tseslint.config(
+  {
+    ignores: [
+      '**/coverage',
+      '**/dist',
+      '**/__fixtures__',
+      '**/jest.config.js',
+      '**/jest.config.base.js',
+      'examples',
+      'packages/canonical-json',
+      'eslint.config.mjs',
+    ],
+  },
+  eslint.configs.recommended,
+  tseslint.configs.recommendedTypeChecked,
+  {
     languageOptions: {
-        parser: tsParser,
-        sourceType: "module",
-
-        parserOptions: {
-            project: "tsconfig.base.json",
-        },
+      parserOptions: {
+        projectService: ['./packages/*/tsconfig.json'],
+        tsconfigRootDir: import.meta.dirname,
+      },
     },
-
     rules: {
-        "@typescript-eslint/require-await": "error",
-        "@typescript-eslint/no-unused-vars": ["error", { "caughtErrors": "none" }]
+      "@typescript-eslint/no-base-to-string": "off",
+      "@typescript-eslint/no-unused-vars": ["error", { "caughtErrors": "none" }],
+      "@typescript-eslint/require-await": "error",
+      "@typescript-eslint/restrict-template-expressions": "off",
     },
-}];
\ No newline at end of file
+  }
+);
diff --git a/package-lock.json b/package-lock.json
index 61c3925f..e3acee2f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15,14 +15,13 @@
         "@tsconfig/node18": "^18.2.4",
         "@types/jest": "^29.5.14",
         "@types/node": "^22.10.2",
-        "@typescript-eslint/eslint-plugin": "^8.18.0",
-        "@typescript-eslint/parser": "^8.18.0",
         "eslint": "^9.17.0",
         "jest": "^29.7.0",
         "nock": "^13.5.5",
         "prettier": "^3.4.2",
         "ts-jest": "^29.2.5",
-        "typescript": "^5.7.2"
+        "typescript": "^5.7.2",
+        "typescript-eslint": "^8.19.0"
       },
       "engines": {
         "node": "^18.17.0 || >=20.5.0"
@@ -5565,16 +5564,17 @@
       "license": "MIT"
     },
     "node_modules/@typescript-eslint/eslint-plugin": {
-      "version": "8.18.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.18.0.tgz",
-      "integrity": "sha512-NR2yS7qUqCL7AIxdJUQf2MKKNDVNaig/dEB0GBLU7D+ZdHgK1NoH/3wsgO3OnPVipn51tG3MAwaODEGil70WEw==",
+      "version": "8.19.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.19.0.tgz",
+      "integrity": "sha512-NggSaEZCdSrFddbctrVjkVZvFC6KGfKfNK0CU7mNK/iKHGKbzT4Wmgm08dKpcZECBu9f5FypndoMyRHkdqfT1Q==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "@eslint-community/regexpp": "^4.10.0",
-        "@typescript-eslint/scope-manager": "8.18.0",
-        "@typescript-eslint/type-utils": "8.18.0",
-        "@typescript-eslint/utils": "8.18.0",
-        "@typescript-eslint/visitor-keys": "8.18.0",
+        "@typescript-eslint/scope-manager": "8.19.0",
+        "@typescript-eslint/type-utils": "8.19.0",
+        "@typescript-eslint/utils": "8.19.0",
+        "@typescript-eslint/visitor-keys": "8.19.0",
         "graphemer": "^1.4.0",
         "ignore": "^5.3.1",
         "natural-compare": "^1.4.0",
@@ -5594,15 +5594,16 @@
       }
     },
     "node_modules/@typescript-eslint/parser": {
-      "version": "8.18.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.18.0.tgz",
-      "integrity": "sha512-hgUZ3kTEpVzKaK3uNibExUYm6SKKOmTU2BOxBSvOYwtJEPdVQ70kZJpPjstlnhCHcuc2WGfSbpKlb/69ttyN5Q==",
+      "version": "8.19.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.19.0.tgz",
+      "integrity": "sha512-6M8taKyOETY1TKHp0x8ndycipTVgmp4xtg5QpEZzXxDhNvvHOJi5rLRkLr8SK3jTgD5l4fTlvBiRdfsuWydxBw==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
-        "@typescript-eslint/scope-manager": "8.18.0",
-        "@typescript-eslint/types": "8.18.0",
-        "@typescript-eslint/typescript-estree": "8.18.0",
-        "@typescript-eslint/visitor-keys": "8.18.0",
+        "@typescript-eslint/scope-manager": "8.19.0",
+        "@typescript-eslint/types": "8.19.0",
+        "@typescript-eslint/typescript-estree": "8.19.0",
+        "@typescript-eslint/visitor-keys": "8.19.0",
         "debug": "^4.3.4"
       },
       "engines": {
@@ -5618,13 +5619,14 @@
       }
     },
     "node_modules/@typescript-eslint/scope-manager": {
-      "version": "8.18.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.18.0.tgz",
-      "integrity": "sha512-PNGcHop0jkK2WVYGotk/hxj+UFLhXtGPiGtiaWgVBVP1jhMoMCHlTyJA+hEj4rszoSdLTK3fN4oOatrL0Cp+Xw==",
+      "version": "8.19.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.19.0.tgz",
+      "integrity": "sha512-hkoJiKQS3GQ13TSMEiuNmSCvhz7ujyqD1x3ShbaETATHrck+9RaDdUbt+osXaUuns9OFwrDTTrjtwsU8gJyyRA==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
-        "@typescript-eslint/types": "8.18.0",
-        "@typescript-eslint/visitor-keys": "8.18.0"
+        "@typescript-eslint/types": "8.19.0",
+        "@typescript-eslint/visitor-keys": "8.19.0"
       },
       "engines": {
         "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -5635,13 +5637,14 @@
       }
     },
     "node_modules/@typescript-eslint/type-utils": {
-      "version": "8.18.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.18.0.tgz",
-      "integrity": "sha512-er224jRepVAVLnMF2Q7MZJCq5CsdH2oqjP4dT7K6ij09Kyd+R21r7UVJrF0buMVdZS5QRhDzpvzAxHxabQadow==",
+      "version": "8.19.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.19.0.tgz",
+      "integrity": "sha512-TZs0I0OSbd5Aza4qAMpp1cdCYVnER94IziudE3JU328YUHgWu9gwiwhag+fuLeJ2LkWLXI+F/182TbG+JaBdTg==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
-        "@typescript-eslint/typescript-estree": "8.18.0",
-        "@typescript-eslint/utils": "8.18.0",
+        "@typescript-eslint/typescript-estree": "8.19.0",
+        "@typescript-eslint/utils": "8.19.0",
         "debug": "^4.3.4",
         "ts-api-utils": "^1.3.0"
       },
@@ -5658,10 +5661,11 @@
       }
     },
     "node_modules/@typescript-eslint/types": {
-      "version": "8.18.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.18.0.tgz",
-      "integrity": "sha512-FNYxgyTCAnFwTrzpBGq+zrnoTO4x0c1CKYY5MuUTzpScqmY5fmsh2o3+57lqdI3NZucBDCzDgdEbIaNfAjAHQA==",
+      "version": "8.19.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.19.0.tgz",
+      "integrity": "sha512-8XQ4Ss7G9WX8oaYvD4OOLCjIQYgRQxO+qCiR2V2s2GxI9AUpo7riNwo6jDhKtTcaJjT8PY54j2Yb33kWtSJsmA==",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
       },
@@ -5671,13 +5675,14 @@
       }
     },
     "node_modules/@typescript-eslint/typescript-estree": {
-      "version": "8.18.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.0.tgz",
-      "integrity": "sha512-rqQgFRu6yPkauz+ms3nQpohwejS8bvgbPyIDq13cgEDbkXt4LH4OkDMT0/fN1RUtzG8e8AKJyDBoocuQh8qNeg==",
+      "version": "8.19.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.19.0.tgz",
+      "integrity": "sha512-WW9PpDaLIFW9LCbucMSdYUuGeFUz1OkWYS/5fwZwTA+l2RwlWFdJvReQqMUMBw4yJWJOfqd7An9uwut2Oj8sLw==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
-        "@typescript-eslint/types": "8.18.0",
-        "@typescript-eslint/visitor-keys": "8.18.0",
+        "@typescript-eslint/types": "8.19.0",
+        "@typescript-eslint/visitor-keys": "8.19.0",
         "debug": "^4.3.4",
         "fast-glob": "^3.3.2",
         "is-glob": "^4.0.3",
@@ -5701,6 +5706,7 @@
       "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
       "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
       "dev": true,
+      "license": "ISC",
       "bin": {
         "semver": "bin/semver.js"
       },
@@ -5709,15 +5715,16 @@
       }
     },
     "node_modules/@typescript-eslint/utils": {
-      "version": "8.18.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.18.0.tgz",
-      "integrity": "sha512-p6GLdY383i7h5b0Qrfbix3Vc3+J2k6QWw6UMUeY5JGfm3C5LbZ4QIZzJNoNOfgyRe0uuYKjvVOsO/jD4SJO+xg==",
+      "version": "8.19.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.19.0.tgz",
+      "integrity": "sha512-PTBG+0oEMPH9jCZlfg07LCB2nYI0I317yyvXGfxnvGvw4SHIOuRnQ3kadyyXY6tGdChusIHIbM5zfIbp4M6tCg==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "@eslint-community/eslint-utils": "^4.4.0",
-        "@typescript-eslint/scope-manager": "8.18.0",
-        "@typescript-eslint/types": "8.18.0",
-        "@typescript-eslint/typescript-estree": "8.18.0"
+        "@typescript-eslint/scope-manager": "8.19.0",
+        "@typescript-eslint/types": "8.19.0",
+        "@typescript-eslint/typescript-estree": "8.19.0"
       },
       "engines": {
         "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -5732,12 +5739,13 @@
       }
     },
     "node_modules/@typescript-eslint/visitor-keys": {
-      "version": "8.18.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.0.tgz",
-      "integrity": "sha512-pCh/qEA8Lb1wVIqNvBke8UaRjJ6wrAWkJO5yyIbs8Yx6TNGYyfNjOo61tLv+WwLvoLPp4BQ8B7AHKijl8NGUfw==",
+      "version": "8.19.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.19.0.tgz",
+      "integrity": "sha512-mCFtBbFBJDCNCWUl5y6sZSCHXw1DEFEk3c/M3nRK2a4XUB8StGFtmcEMizdjKuBzB6e/smJAAWYug3VrdLMr1w==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
-        "@typescript-eslint/types": "8.18.0",
+        "@typescript-eslint/types": "8.19.0",
         "eslint-visitor-keys": "^4.2.0"
       },
       "engines": {
@@ -5753,6 +5761,7 @@
       "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
       "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
       "dev": true,
+      "license": "Apache-2.0",
       "engines": {
         "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
       },
@@ -10734,6 +10743,29 @@
         "node": ">=14.17"
       }
     },
+    "node_modules/typescript-eslint": {
+      "version": "8.19.0",
+      "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.19.0.tgz",
+      "integrity": "sha512-Ni8sUkVWYK4KAcTtPjQ/UTiRk6jcsuDhPpxULapUDi8A/l8TSBk+t1GtJA1RsCzIJg0q6+J7bf35AwQigENWRQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@typescript-eslint/eslint-plugin": "8.19.0",
+        "@typescript-eslint/parser": "8.19.0",
+        "@typescript-eslint/utils": "8.19.0"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependencies": {
+        "eslint": "^8.57.0 || ^9.0.0",
+        "typescript": ">=4.8.4 <5.8.0"
+      }
+    },
     "node_modules/undici-types": {
       "version": "6.20.0",
       "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
@@ -15545,16 +15577,16 @@
       "dev": true
     },
     "@typescript-eslint/eslint-plugin": {
-      "version": "8.18.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.18.0.tgz",
-      "integrity": "sha512-NR2yS7qUqCL7AIxdJUQf2MKKNDVNaig/dEB0GBLU7D+ZdHgK1NoH/3wsgO3OnPVipn51tG3MAwaODEGil70WEw==",
+      "version": "8.19.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.19.0.tgz",
+      "integrity": "sha512-NggSaEZCdSrFddbctrVjkVZvFC6KGfKfNK0CU7mNK/iKHGKbzT4Wmgm08dKpcZECBu9f5FypndoMyRHkdqfT1Q==",
       "dev": true,
       "requires": {
         "@eslint-community/regexpp": "^4.10.0",
-        "@typescript-eslint/scope-manager": "8.18.0",
-        "@typescript-eslint/type-utils": "8.18.0",
-        "@typescript-eslint/utils": "8.18.0",
-        "@typescript-eslint/visitor-keys": "8.18.0",
+        "@typescript-eslint/scope-manager": "8.19.0",
+        "@typescript-eslint/type-utils": "8.19.0",
+        "@typescript-eslint/utils": "8.19.0",
+        "@typescript-eslint/visitor-keys": "8.19.0",
         "graphemer": "^1.4.0",
         "ignore": "^5.3.1",
         "natural-compare": "^1.4.0",
@@ -15562,54 +15594,54 @@
       }
     },
     "@typescript-eslint/parser": {
-      "version": "8.18.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.18.0.tgz",
-      "integrity": "sha512-hgUZ3kTEpVzKaK3uNibExUYm6SKKOmTU2BOxBSvOYwtJEPdVQ70kZJpPjstlnhCHcuc2WGfSbpKlb/69ttyN5Q==",
+      "version": "8.19.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.19.0.tgz",
+      "integrity": "sha512-6M8taKyOETY1TKHp0x8ndycipTVgmp4xtg5QpEZzXxDhNvvHOJi5rLRkLr8SK3jTgD5l4fTlvBiRdfsuWydxBw==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/scope-manager": "8.18.0",
-        "@typescript-eslint/types": "8.18.0",
-        "@typescript-eslint/typescript-estree": "8.18.0",
-        "@typescript-eslint/visitor-keys": "8.18.0",
+        "@typescript-eslint/scope-manager": "8.19.0",
+        "@typescript-eslint/types": "8.19.0",
+        "@typescript-eslint/typescript-estree": "8.19.0",
+        "@typescript-eslint/visitor-keys": "8.19.0",
         "debug": "^4.3.4"
       }
     },
     "@typescript-eslint/scope-manager": {
-      "version": "8.18.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.18.0.tgz",
-      "integrity": "sha512-PNGcHop0jkK2WVYGotk/hxj+UFLhXtGPiGtiaWgVBVP1jhMoMCHlTyJA+hEj4rszoSdLTK3fN4oOatrL0Cp+Xw==",
+      "version": "8.19.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.19.0.tgz",
+      "integrity": "sha512-hkoJiKQS3GQ13TSMEiuNmSCvhz7ujyqD1x3ShbaETATHrck+9RaDdUbt+osXaUuns9OFwrDTTrjtwsU8gJyyRA==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/types": "8.18.0",
-        "@typescript-eslint/visitor-keys": "8.18.0"
+        "@typescript-eslint/types": "8.19.0",
+        "@typescript-eslint/visitor-keys": "8.19.0"
       }
     },
     "@typescript-eslint/type-utils": {
-      "version": "8.18.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.18.0.tgz",
-      "integrity": "sha512-er224jRepVAVLnMF2Q7MZJCq5CsdH2oqjP4dT7K6ij09Kyd+R21r7UVJrF0buMVdZS5QRhDzpvzAxHxabQadow==",
+      "version": "8.19.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.19.0.tgz",
+      "integrity": "sha512-TZs0I0OSbd5Aza4qAMpp1cdCYVnER94IziudE3JU328YUHgWu9gwiwhag+fuLeJ2LkWLXI+F/182TbG+JaBdTg==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/typescript-estree": "8.18.0",
-        "@typescript-eslint/utils": "8.18.0",
+        "@typescript-eslint/typescript-estree": "8.19.0",
+        "@typescript-eslint/utils": "8.19.0",
         "debug": "^4.3.4",
         "ts-api-utils": "^1.3.0"
       }
     },
     "@typescript-eslint/types": {
-      "version": "8.18.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.18.0.tgz",
-      "integrity": "sha512-FNYxgyTCAnFwTrzpBGq+zrnoTO4x0c1CKYY5MuUTzpScqmY5fmsh2o3+57lqdI3NZucBDCzDgdEbIaNfAjAHQA==",
+      "version": "8.19.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.19.0.tgz",
+      "integrity": "sha512-8XQ4Ss7G9WX8oaYvD4OOLCjIQYgRQxO+qCiR2V2s2GxI9AUpo7riNwo6jDhKtTcaJjT8PY54j2Yb33kWtSJsmA==",
       "dev": true
     },
     "@typescript-eslint/typescript-estree": {
-      "version": "8.18.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.0.tgz",
-      "integrity": "sha512-rqQgFRu6yPkauz+ms3nQpohwejS8bvgbPyIDq13cgEDbkXt4LH4OkDMT0/fN1RUtzG8e8AKJyDBoocuQh8qNeg==",
+      "version": "8.19.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.19.0.tgz",
+      "integrity": "sha512-WW9PpDaLIFW9LCbucMSdYUuGeFUz1OkWYS/5fwZwTA+l2RwlWFdJvReQqMUMBw4yJWJOfqd7An9uwut2Oj8sLw==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/types": "8.18.0",
-        "@typescript-eslint/visitor-keys": "8.18.0",
+        "@typescript-eslint/types": "8.19.0",
+        "@typescript-eslint/visitor-keys": "8.19.0",
         "debug": "^4.3.4",
         "fast-glob": "^3.3.2",
         "is-glob": "^4.0.3",
@@ -15627,24 +15659,24 @@
       }
     },
     "@typescript-eslint/utils": {
-      "version": "8.18.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.18.0.tgz",
-      "integrity": "sha512-p6GLdY383i7h5b0Qrfbix3Vc3+J2k6QWw6UMUeY5JGfm3C5LbZ4QIZzJNoNOfgyRe0uuYKjvVOsO/jD4SJO+xg==",
+      "version": "8.19.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.19.0.tgz",
+      "integrity": "sha512-PTBG+0oEMPH9jCZlfg07LCB2nYI0I317yyvXGfxnvGvw4SHIOuRnQ3kadyyXY6tGdChusIHIbM5zfIbp4M6tCg==",
       "dev": true,
       "requires": {
         "@eslint-community/eslint-utils": "^4.4.0",
-        "@typescript-eslint/scope-manager": "8.18.0",
-        "@typescript-eslint/types": "8.18.0",
-        "@typescript-eslint/typescript-estree": "8.18.0"
+        "@typescript-eslint/scope-manager": "8.19.0",
+        "@typescript-eslint/types": "8.19.0",
+        "@typescript-eslint/typescript-estree": "8.19.0"
       }
     },
     "@typescript-eslint/visitor-keys": {
-      "version": "8.18.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.0.tgz",
-      "integrity": "sha512-pCh/qEA8Lb1wVIqNvBke8UaRjJ6wrAWkJO5yyIbs8Yx6TNGYyfNjOo61tLv+WwLvoLPp4BQ8B7AHKijl8NGUfw==",
+      "version": "8.19.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.19.0.tgz",
+      "integrity": "sha512-mCFtBbFBJDCNCWUl5y6sZSCHXw1DEFEk3c/M3nRK2a4XUB8StGFtmcEMizdjKuBzB6e/smJAAWYug3VrdLMr1w==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/types": "8.18.0",
+        "@typescript-eslint/types": "8.19.0",
         "eslint-visitor-keys": "^4.2.0"
       },
       "dependencies": {
@@ -19151,6 +19183,17 @@
       "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==",
       "dev": true
     },
+    "typescript-eslint": {
+      "version": "8.19.0",
+      "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.19.0.tgz",
+      "integrity": "sha512-Ni8sUkVWYK4KAcTtPjQ/UTiRk6jcsuDhPpxULapUDi8A/l8TSBk+t1GtJA1RsCzIJg0q6+J7bf35AwQigENWRQ==",
+      "dev": true,
+      "requires": {
+        "@typescript-eslint/eslint-plugin": "8.19.0",
+        "@typescript-eslint/parser": "8.19.0",
+        "@typescript-eslint/utils": "8.19.0"
+      }
+    },
     "undici-types": {
       "version": "6.20.0",
       "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
diff --git a/package.json b/package.json
index b3ab2142..366bfdb6 100644
--- a/package.json
+++ b/package.json
@@ -20,14 +20,13 @@
     "@tsconfig/node18": "^18.2.4",
     "@types/jest": "^29.5.14",
     "@types/node": "^22.10.2",
-    "@typescript-eslint/eslint-plugin": "^8.18.0",
-    "@typescript-eslint/parser": "^8.18.0",
     "eslint": "^9.17.0",
     "jest": "^29.7.0",
     "nock": "^13.5.5",
     "prettier": "^3.4.2",
     "ts-jest": "^29.2.5",
-    "typescript": "^5.7.2"
+    "typescript": "^5.7.2",
+    "typescript-eslint": "^8.19.0"
   },
   "workspaces": [
     "./packages/*"
diff --git a/packages/cli/package.json b/packages/cli/package.json
index 67eca021..8a7c3d05 100644
--- a/packages/cli/package.json
+++ b/packages/cli/package.json
@@ -19,7 +19,7 @@
     "provenance": true
   },
   "scripts": {
-    "clean": "shx rm -rf dist && shx rm tsconfig.build.tsbuildinfo",
+    "clean": "shx rm -rf dist",
     "prebuild": "npm run clean",
     "build": "tsc --build",
     "postpack": "shx rm -f oclif.manifest.json",
diff --git a/packages/cli/src/commands/download-target.ts b/packages/cli/src/commands/download-target.ts
index 08c805da..0ea3b86b 100644
--- a/packages/cli/src/commands/download-target.ts
+++ b/packages/cli/src/commands/download-target.ts
@@ -1,8 +1,8 @@
 import { Command, Flags } from '@oclif/core';
-import fs from 'fs';
+import * as fs from 'fs';
 import fetch from 'make-fetch-happen';
-import os from 'os';
-import path from 'path';
+import * as os from 'os';
+import * as path from 'path';
 import { Updater } from 'tuf-js';
 
 export default class DownloadTarget extends Command {
@@ -69,7 +69,9 @@ export default class DownloadTarget extends Command {
 
     if (flags['unsafe-root-download']) {
       const rootUrl = flags['metadata-base-url'] + '/1.root.json';
-      const rootJSON = await fetch(rootUrl).then((res) => res.json());
+      const rootJSON = (await fetch(rootUrl).then((res) =>
+        res.json()
+      )) as object;
       fs.writeFileSync(
         path.join(metadataPath, 'root.json'),
         JSON.stringify(rootJSON, null, 2)
diff --git a/packages/cli/tsconfig.json b/packages/cli/tsconfig.json
index fc8520e7..d8faaf50 100644
--- a/packages/cli/tsconfig.json
+++ b/packages/cli/tsconfig.json
@@ -1,3 +1,3 @@
 {
-  "extends": "./tsconfig.json"
+  "extends": "./tsconfig.build.json"
 }
diff --git a/packages/client/src/fetcher.ts b/packages/client/src/fetcher.ts
index 3cd62dd2..0cee6bab 100644
--- a/packages/client/src/fetcher.ts
+++ b/packages/client/src/fetcher.ts
@@ -54,6 +54,7 @@ export abstract class BaseFetcher implements Fetcher {
         }
       } finally {
         // Make sure we always close the stream
+        // eslint-disable-next-line @typescript-eslint/unbound-method
         await util.promisify(fileStream.close).bind(fileStream)();
       }
 
@@ -67,7 +68,7 @@ export abstract class BaseFetcher implements Fetcher {
       const stream = fs.createReadStream(file);
       const chunks: Buffer[] = [];
 
-      for await (const chunk of stream) {
+      for await (const chunk of stream as AsyncIterable<Buffer>) {
         chunks.push(chunk);
       }
 
diff --git a/packages/client/src/store.ts b/packages/client/src/store.ts
index e1ef2612..570df07c 100644
--- a/packages/client/src/store.ts
+++ b/packages/client/src/store.ts
@@ -57,7 +57,9 @@ export class TrustedMetadataStore {
   }
 
   public updateRoot(bytesBuffer: Buffer): Metadata<Root> {
+    // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
     const data = JSON.parse(bytesBuffer.toString('utf8'));
+    // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
     const newRoot = Metadata.fromJSON(MetadataKind.Root, data);
     if (newRoot.signed.type != MetadataKind.Root) {
       throw new RepositoryError(`Expected 'root', got ${newRoot.signed.type}`);
@@ -92,7 +94,9 @@ export class TrustedMetadataStore {
       throw new ExpiredMetadataError('Final root.json is expired');
     }
 
+    // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
     const data = JSON.parse(bytesBuffer.toString('utf8'));
+    // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
     const newTimestamp = Metadata.fromJSON(MetadataKind.Timestamp, data);
 
     if (newTimestamp.signed.type != MetadataKind.Timestamp) {
@@ -164,7 +168,9 @@ export class TrustedMetadataStore {
       snapshotMeta.verify(bytesBuffer);
     }
 
+    // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
     const data = JSON.parse(bytesBuffer.toString('utf8'));
+    // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
     const newSnapshot = Metadata.fromJSON(MetadataKind.Snapshot, data);
 
     if (newSnapshot.signed.type != MetadataKind.Snapshot) {
@@ -235,7 +241,9 @@ export class TrustedMetadataStore {
     // Client workflow 5.6.2: check against snapshot role's targets hash
     meta.verify(bytesBuffer);
 
+    // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
     const data = JSON.parse(bytesBuffer.toString('utf8'));
+    // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
     const newDelegate = Metadata.fromJSON(MetadataKind.Targets, data);
 
     if (newDelegate.signed.type != MetadataKind.Targets) {
@@ -266,7 +274,9 @@ export class TrustedMetadataStore {
   // Verifies and loads data as trusted root metadata.
   // Note that an expired initial root is still considered valid.
   private loadTrustedRoot(bytesBuffer: Buffer) {
+    // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
     const data = JSON.parse(bytesBuffer.toString('utf8'));
+    // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
     const root = Metadata.fromJSON(MetadataKind.Root, data);
 
     if (root.signed.type != MetadataKind.Root) {
diff --git a/packages/models/src/file.ts b/packages/models/src/file.ts
index 3007a3aa..c61f3128 100644
--- a/packages/models/src/file.ts
+++ b/packages/models/src/file.ts
@@ -187,7 +187,7 @@ export class TargetFile {
     );
 
     // Read stream chunk by chunk
-    for await (const chunk of stream) {
+    for await (const chunk of stream as AsyncIterable<Buffer>) {
       // Keep running tally of stream length
       observedLength += chunk.length;
 
diff --git a/packages/models/src/metadata.ts b/packages/models/src/metadata.ts
index d521c268..a6ab5b42 100644
--- a/packages/models/src/metadata.ts
+++ b/packages/models/src/metadata.ts
@@ -127,6 +127,7 @@ export class Metadata<T extends MetadataType> implements Signable {
       return false;
     }
     return (
+      // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
       this.signed.equals(other.signed) &&
       util.isDeepStrictEqual(this.signatures, other.signatures) &&
       util.isDeepStrictEqual(this.unrecognizedFields, other.unrecognizedFields)
diff --git a/packages/models/tests/base.test.ts b/packages/models/tests/base.test.ts
index 71e0ea36..f7da1bdc 100644
--- a/packages/models/tests/base.test.ts
+++ b/packages/models/tests/base.test.ts
@@ -148,10 +148,11 @@ describe('Signed', () => {
     describe('when the version is not included', () => {
       it('throws an error', () => {
         expect(() => {
+          // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
           DummySigned.commonFieldsFromJSON({
             ...json,
             version: undefined,
-          } as any); /* eslint-disable-line @typescript-eslint/no-explicit-any */
+          } as any); // eslint-disable-line @typescript-eslint/no-explicit-any
         }).toThrow(ValueError);
       });
     });
@@ -167,10 +168,11 @@ describe('Signed', () => {
     describe('when the spec_version is not included', () => {
       it('throws an error', () => {
         expect(() => {
+          // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
           DummySigned.commonFieldsFromJSON({
             ...json,
             spec_version: undefined,
-          } as any); /* eslint-disable-line @typescript-eslint/no-explicit-any */
+          } as any); // eslint-disable-line @typescript-eslint/no-explicit-any
         }).toThrow(ValueError);
       });
     });
@@ -186,10 +188,11 @@ describe('Signed', () => {
     describe('when the expires is not included', () => {
       it('throws an error', () => {
         expect(() => {
+          // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
           DummySigned.commonFieldsFromJSON({
             ...json,
             expires: undefined,
-          } as any); /* eslint-disable-line @typescript-eslint/no-explicit-any */
+          } as any); // eslint-disable-line @typescript-eslint/no-explicit-any
         }).toThrow(ValueError);
       });
     });
diff --git a/packages/models/tests/key.test.ts b/packages/models/tests/key.test.ts
index 7b88ae82..c60f9438 100644
--- a/packages/models/tests/key.test.ts
+++ b/packages/models/tests/key.test.ts
@@ -125,7 +125,7 @@ describe('Key', () => {
 
     describe('when called with a non-Key object', () => {
       it('returns false', () => {
-        // eslint-disable-next-line @typescript-eslint/no-explicit-any
+        // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument
         expect(key.equals({} as any)).toBeFalsy();
       });
     });
diff --git a/packages/models/tests/role.test.ts b/packages/models/tests/role.test.ts
index 05c5e7e2..dbbe4e23 100644
--- a/packages/models/tests/role.test.ts
+++ b/packages/models/tests/role.test.ts
@@ -64,7 +64,7 @@ describe('Role', () => {
 
     describe('when called with a non-Role object', () => {
       it('returns false', () => {
-        // eslint-disable-next-line @typescript-eslint/no-explicit-any
+        // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument
         expect(role.equals({} as any)).toBeFalsy();
       });
     });
@@ -147,7 +147,7 @@ describe('DelegatedRole', () => {
           new DelegatedRole({
             ...opts,
             paths,
-            // eslint-disable-next-line @typescript-eslint/no-explicit-any
+            // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment
             pathHashPrefixes: pathHashPrefixes as any,
           });
         }).toThrowError(ValueError);
@@ -167,7 +167,7 @@ describe('DelegatedRole', () => {
 
     describe('when called with a non-DelegatedRole object', () => {
       it('returns false', () => {
-        // eslint-disable-next-line @typescript-eslint/no-explicit-any
+        // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument
         expect(role.equals({} as any)).toBeFalsy();
       });
     });
diff --git a/packages/models/tests/verify.test.ts b/packages/models/tests/verify.test.ts
index f168afa7..21a906cf 100644
--- a/packages/models/tests/verify.test.ts
+++ b/packages/models/tests/verify.test.ts
@@ -1,11 +1,12 @@
 import { Metadata, MetadataKind, ValueError } from '../src/index';
+import { JSONObject } from '../src/utils';
 
 /* eslint-disable @typescript-eslint/no-require-imports */
-const rootJSON = require('./__fixtures__/root.json');
-const timestampJSON = require('./__fixtures__/timestamp.json');
-const snapshotJSON = require('./__fixtures__/snapshot.json');
-const targetsJSON = require('./__fixtures__/targets.json');
-const role1JSON = require('./__fixtures__/role1.json');
+const rootJSON = require('./__fixtures__/root.json') as JSONObject;
+const timestampJSON = require('./__fixtures__/timestamp.json') as JSONObject;
+const snapshotJSON = require('./__fixtures__/snapshot.json') as JSONObject;
+const targetsJSON = require('./__fixtures__/targets.json') as JSONObject;
+const role1JSON = require('./__fixtures__/role1.json') as JSONObject;
 /* eslint-enable @typescript-eslint/no-require-imports */
 
 describe('Verify TUF local sample', () => {
diff --git a/packages/repo-mock/tests/index.test.ts b/packages/repo-mock/tests/index.test.ts
index 1d7a1507..ee059e15 100644
--- a/packages/repo-mock/tests/index.test.ts
+++ b/packages/repo-mock/tests/index.test.ts
@@ -22,6 +22,7 @@ describe('mockRepo', () => {
     const rootJSON = mockRepo(baseURL, []);
     expect(rootJSON).toBeTruthy();
 
+    // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
     const rootMeta = Metadata.fromJSON(MetadataKind.Root, JSON.parse(rootJSON));
     expect(rootMeta).toBeTruthy();
     expect(() => rootMeta.verifyDelegate('root', rootMeta)).not.toThrow();
@@ -30,6 +31,7 @@ describe('mockRepo', () => {
     const timestampJSON = await fetch(`${baseURL}/metadata/timestamp.json`);
     const timestampMeta = Metadata.fromJSON(
       MetadataKind.Timestamp,
+      // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
       JSON.parse(timestampJSON)
     );
     expect(timestampMeta).toBeTruthy();
@@ -41,6 +43,7 @@ describe('mockRepo', () => {
     const snapshotJSON = await fetch(`${baseURL}/metadata/snapshot.json`);
     const snapshotMeta = Metadata.fromJSON(
       MetadataKind.Snapshot,
+      // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
       JSON.parse(snapshotJSON)
     );
     expect(snapshotMeta).toBeTruthy();
@@ -52,6 +55,7 @@ describe('mockRepo', () => {
     const targetsJSON = await fetch(`${baseURL}/metadata/targets.json`);
     const targetsMeta = Metadata.fromJSON(
       MetadataKind.Targets,
+      // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
       JSON.parse(targetsJSON)
     );
     expect(targetsMeta).toBeTruthy();