Radish alpha
r
Radicle web interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
Update eslint config to flat config
Sebastian Martinez committed 1 year ago
commit 0c7ea70c1be9771a9ec8a6d05abb71dc934493c4
parent ffd49e82ee77a981ebf711b1e1bc9967e59d9841
22 files changed +370 -276
deleted .eslintignore
@@ -1,3 +0,0 @@
-
node_modules
-
build
-
public
deleted .eslintrc.cjs
@@ -1,121 +0,0 @@
-
module.exports = {
-
  env: {
-
    es6: true,
-
    browser: true,
-
    node: true,
-
  },
-
  extends: [
-
    "eslint:recommended",
-
    "plugin:@typescript-eslint/recommended",
-
    "plugin:svelte/recommended",
-
    "prettier",
-
  ],
-
  parser: "@typescript-eslint/parser",
-
  parserOptions: {
-
    ecmaVersion: 2020,
-
    sourceType: "module",
-
    project: ["./tsconfig.json"],
-
    tsconfigRootDir: __dirname,
-
    extraFileExtensions: [".svelte"],
-
  },
-
  overrides: [
-
    {
-
      files: ["*.svelte"],
-
      parser: "svelte-eslint-parser",
-
      parserOptions: {
-
        parser: "@typescript-eslint/parser",
-
      },
-
    },
-
  ],
-
  settings: {
-
    svelte: {
-
      ignoreWarnings: ["svelte/no-at-html-tags"],
-
    },
-
  },
-
  // Workaround until $$Generic is supported:
-
  // https://github.com/sveltejs/svelte-eslint-parser/issues/306#issuecomment-1480844814
-
  globals: {
-
    $$Generic: "readonly",
-
  },
-
  plugins: ["@typescript-eslint", "no-only-tests"],
-
  rules: {
-
    "no-only-tests/no-only-tests": "warn",
-
    "no-implicit-globals": ["error"],
-
    "no-restricted-globals": [
-
      "error",
-
      "name",
-
      "event",
-
      "frames",
-
      "history",
-
      "length",
-
      "content",
-
      "origin",
-
      "status",
-
    ],
-
    "@typescript-eslint/no-floating-promises": "warn",
-
    "@typescript-eslint/naming-convention": [
-
      "warn",
-
      {
-
        selector: "enumMember",
-
        format: ["PascalCase"],
-
      },
-
      {
-
        selector: "objectLiteralProperty",
-
        format: ["PascalCase", "camelCase"],
-
      },
-
      {
-
        selector: "default",
-
        format: ["camelCase"],
-
        leadingUnderscore: "allow",
-
        trailingUnderscore: "allow",
-
      },
-
      {
-
        selector: "variable",
-
        modifiers: ["const"],
-
        format: ["camelCase", "PascalCase", "UPPER_CASE"],
-
        leadingUnderscore: "allow",
-
        trailingUnderscore: "allow",
-
      },
-
      {
-
        selector: "typeLike",
-
        format: ["PascalCase"],
-
      },
-
      // Disable @typescript-eslint/naming-convention format for imports
-
      // https://github.com/typescript-eslint/typescript-eslint/pull/7269#issuecomment-1777628591
-
      // https://github.com/typescript-eslint/typescript-eslint/issues/7892
-
      { selector: "import", format: null },
-
      {
-
        selector: ["objectLiteralProperty"],
-
        modifiers: ["requiresQuotes"],
-
        format: null,
-
      },
-
    ],
-
    "@typescript-eslint/no-explicit-any": "off",
-
    "@typescript-eslint/no-namespace": ["error", { allowDeclarations: true }],
-
    "@typescript-eslint/member-ordering": [
-
      "warn",
-
      { default: ["field", "signature", "constructor", "method"] },
-
    ],
-

-
    "@typescript-eslint/no-invalid-void-type": ["warn"],
-
    // Disallow Unused Variables.
-
    // https://eslint.org/docs/rules/no-unused-vars
-
    "@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_" }],
-
    // Require using arrow functions as callbacks.
-
    // https://eslint.org/docs/rules/prefer-arrow-callback
-
    "prefer-arrow-callback": "warn",
-
    // Require using const for variables that are never modified after declared.
-
    // https://eslint.org/docs/rules/prefer-const
-
    "prefer-const": "warn",
-
    // Disallow modifying variables that are declared using const.
-
    // https://eslint.org/docs/rules/no-const-assign
-
    "no-const-assign": "error",
-
    // Require let or const instead of var.
-
    // https://eslint.org/docs/rules/no-var
-
    "no-var": "warn",
-
    // Require `===` and `!==` comparisons.
-
    eqeqeq: "warn",
-
    // Allow explict type annotations for additional clarity.
-
    "@typescript-eslint/no-inferrable-types": "off",
-
  },
-
};
added eslint.config.js
@@ -0,0 +1,138 @@
+
import globals from "globals";
+
import js from "@eslint/js";
+
import prettier from "eslint-config-prettier";
+
import svelte from "eslint-plugin-svelte";
+
import svelteParser from "svelte-eslint-parser";
+
import ts from "typescript-eslint";
+

+
export default [
+
  ...[
+
    js.configs.recommended,
+
    ...ts.configs.recommended,
+
    prettier,
+
    {
+
      languageOptions: {
+
        parser: ts.parser,
+
        parserOptions: {
+
          project: "./tsconfig.json",
+
          tsconfigRootDir: import.meta.dirname,
+
          extraFileExtensions: [".svelte"],
+
        },
+
        globals: { ...globals.browser, ...globals.node },
+
      },
+
      rules: {
+
        "no-implicit-globals": "error",
+
        "no-restricted-globals": [
+
          "error",
+
          "name",
+
          "event",
+
          "frames",
+
          "history",
+
          "length",
+
          "content",
+
          "origin",
+
          "status",
+
        ],
+
        // Require using arrow functions as callbacks.
+
        // https://eslint.org/docs/rules/prefer-arrow-callback
+
        "prefer-arrow-callback": "warn",
+
        // Require using const for variables that are never modified after declared.
+
        // https://eslint.org/docs/rules/prefer-const
+
        "prefer-const": "warn",
+
        // Disallow modifying variables that are declared using const.
+
        // https://eslint.org/docs/rules/no-const-assign
+
        "no-const-assign": "error",
+
        // Require let or const instead of var.
+
        // https://eslint.org/docs/rules/no-var
+
        "no-var": "warn",
+
        // Require `===` and `!==` comparisons.
+
        eqeqeq: "warn",
+
        "@typescript-eslint/no-floating-promises": "warn",
+
        "@typescript-eslint/no-empty-function": "warn",
+
        "@typescript-eslint/naming-convention": [
+
          "warn",
+
          {
+
            selector: "enumMember",
+
            format: ["PascalCase"],
+
          },
+
          {
+
            selector: "objectLiteralProperty",
+
            format: ["PascalCase", "camelCase"],
+
          },
+
          {
+
            selector: "default",
+
            format: ["camelCase"],
+
            leadingUnderscore: "allow",
+
            trailingUnderscore: "allow",
+
          },
+
          {
+
            selector: "variable",
+
            modifiers: ["const"],
+
            format: ["camelCase", "PascalCase", "UPPER_CASE"],
+
            leadingUnderscore: "allow",
+
            trailingUnderscore: "allow",
+
          },
+
          {
+
            selector: "typeLike",
+
            format: ["PascalCase"],
+
          },
+
          // Disable @typescript-eslint/naming-convention format for imports
+
          // https://github.com/typescript-eslint/typescript-eslint/pull/7269#issuecomment-1777628591
+
          // https://github.com/typescript-eslint/typescript-eslint/issues/7892
+
          { selector: "import", format: null },
+
          {
+
            selector: ["objectLiteralProperty"],
+
            modifiers: ["requiresQuotes"],
+
            format: null,
+
          },
+
        ],
+
        "@typescript-eslint/no-namespace": [
+
          "error",
+
          { allowDeclarations: true },
+
        ],
+
        "@typescript-eslint/member-ordering": [
+
          "warn",
+
          { default: ["field", "signature", "constructor", "method"] },
+
        ],
+
        // Allow explict type annotations for additional clarity.
+
        "@typescript-eslint/no-inferrable-types": "off",
+
        "@typescript-eslint/no-invalid-void-type": ["warn"],
+
        // Disallow Unused Variables.
+
        // https://eslint.org/docs/rules/no-unused-vars
+
        "@typescript-eslint/no-unused-vars": [
+
          "warn",
+
          { argsIgnorePattern: "^_" },
+
        ],
+
      },
+
    },
+
  ].map(conf => ({
+
    ...conf,
+
    linterOptions: {
+
      reportUnusedDisableDirectives: "error",
+
    },
+
    files: ["**/*.js", "**/*.ts", "**/*.svelte"],
+
  })),
+
  ...svelte.configs["flat/recommended"],
+
  ...svelte.configs["flat/prettier"],
+
  {
+
    files: ["*.svelte", "**/*.svelte"],
+
    languageOptions: {
+
      parser: svelteParser,
+
      parserOptions: {
+
        parser: ts.parser,
+
        project: "./tsconfig.json",
+
        tsconfigRootDir: import.meta.dirname,
+
        svelteFeatures: {
+
          experimentalGenerics: true,
+
        },
+
      },
+
    },
+
    rules: {
+
      "svelte/no-at-html-tags": "off",
+
      "@typescript-eslint/no-explicit-any": "error",
+
    },
+
  },
+
  {
+
    ignores: ["node_modules/**/*", "build/**/*", "public/**/*"],
+
  },
+
];
modified httpd-client/lib/fetcher.ts
@@ -20,10 +20,11 @@ export class ResponseError extends Error {
  public body: unknown;

  public constructor(method: string, response: Response, body_: unknown) {
-
    const body: any = body_;
+
    const body: unknown = body_;
    if (
      typeof body === "object" &&
      body !== null &&
+
      "message" in body &&
      typeof body.message === "string"
    ) {
      super(body.message);
modified httpd-client/tests/support/support.ts
@@ -38,7 +38,7 @@ export async function createPatchToBeModified(
}
export async function assertIssue(
  oid: string,
-
  change: Record<string, any>,
+
  change: Record<string, unknown>,
  api: HttpdClient,
) {
  expect(
@@ -49,7 +49,7 @@ export async function assertIssue(

export async function assertPatch(
  oid: string,
-
  change: Record<string, any>,
+
  change: Record<string, unknown>,
  api: HttpdClient,
) {
  expect(
modified package-lock.json
@@ -31,6 +31,7 @@
        "zod": "^3.22.4"
      },
      "devDependencies": {
+
        "@eslint/js": "^9.3.0",
        "@playwright/test": "^1.42.1",
        "@sveltejs/vite-plugin-svelte": "^3.0.2",
        "@tsconfig/svelte": "^5.0.3",
@@ -42,21 +43,23 @@
        "@types/node": "^20.11.30",
        "@types/sinon": "^17.0.3",
        "@types/wait-on": "^5.3.4",
-
        "@typescript-eslint/eslint-plugin": "^7.4.0",
+
        "@typescript-eslint/parser": "^7.10.0",
        "chalk": "^5.3.0",
        "config": "^3.3.11",
        "eslint": "^8.57.0",
        "eslint-config-prettier": "^9.1.0",
-
        "eslint-plugin-no-only-tests": "^3.1.0",
-
        "eslint-plugin-svelte": "^2.35.1",
+
        "eslint-plugin-svelte": "^2.39.0",
        "execa": "^9.0.0",
        "get-port": "^7.1.0",
+
        "globals": "^15.3.0",
        "happy-dom": "^14.3.8",
        "prettier": "^3.2.5",
        "prettier-plugin-svelte": "^3.2.2",
        "sinon": "^17.0.1",
        "svelte-check": "^3.6.8",
+
        "svelte-eslint-parser": "^0.36.0",
        "typescript": "^5.4.3",
+
        "typescript-eslint": "^7.10.0",
        "vite": "^5.2.6",
        "vite-plugin-virtual": "^0.3.0",
        "vitest": "^1.4.0",
@@ -529,6 +532,21 @@
        "concat-map": "0.0.1"
      }
    },
+
    "node_modules/@eslint/eslintrc/node_modules/globals": {
+
      "version": "13.24.0",
+
      "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
+
      "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
+
      "dev": true,
+
      "dependencies": {
+
        "type-fest": "^0.20.2"
+
      },
+
      "engines": {
+
        "node": ">=8"
+
      },
+
      "funding": {
+
        "url": "https://github.com/sponsors/sindresorhus"
+
      }
+
    },
    "node_modules/@eslint/eslintrc/node_modules/minimatch": {
      "version": "3.1.2",
      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -542,12 +560,12 @@
      }
    },
    "node_modules/@eslint/js": {
-
      "version": "8.57.0",
-
      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz",
-
      "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==",
+
      "version": "9.3.0",
+
      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.3.0.tgz",
+
      "integrity": "sha512-niBqk8iwv96+yuTwjM6bWg8ovzAPF9qkICsGtcoa5/dmqcEMfdwNAX7+/OHcJHc7wj7XqPxH98oAHytFYlw6Sw==",
      "dev": true,
      "engines": {
-
        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+
        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
      }
    },
    "node_modules/@hapi/hoek": {
@@ -1070,12 +1088,6 @@
        "@types/unist": "*"
      }
    },
-
    "node_modules/@types/json-schema": {
-
      "version": "7.0.15",
-
      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
-
      "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
-
      "dev": true
-
    },
    "node_modules/@types/katex": {
      "version": "0.16.7",
      "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.7.tgz",
@@ -1121,12 +1133,6 @@
      "integrity": "sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==",
      "dev": true
    },
-
    "node_modules/@types/semver": {
-
      "version": "7.5.8",
-
      "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz",
-
      "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==",
-
      "dev": true
-
    },
    "node_modules/@types/sinon": {
      "version": "17.0.3",
      "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-17.0.3.tgz",
@@ -1163,22 +1169,20 @@
      }
    },
    "node_modules/@typescript-eslint/eslint-plugin": {
-
      "version": "7.4.0",
-
      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.4.0.tgz",
-
      "integrity": "sha512-yHMQ/oFaM7HZdVrVm/M2WHaNPgyuJH4WelkSVEWSSsir34kxW2kDJCxlXRhhGWEsMN0WAW/vLpKfKVcm8k+MPw==",
+
      "version": "7.10.0",
+
      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.10.0.tgz",
+
      "integrity": "sha512-PzCr+a/KAef5ZawX7nbyNwBDtM1HdLIT53aSA2DDlxmxMngZ43O8SIePOeX8H5S+FHXeI6t97mTt/dDdzY4Fyw==",
      "dev": true,
      "dependencies": {
-
        "@eslint-community/regexpp": "^4.5.1",
-
        "@typescript-eslint/scope-manager": "7.4.0",
-
        "@typescript-eslint/type-utils": "7.4.0",
-
        "@typescript-eslint/utils": "7.4.0",
-
        "@typescript-eslint/visitor-keys": "7.4.0",
-
        "debug": "^4.3.4",
+
        "@eslint-community/regexpp": "^4.10.0",
+
        "@typescript-eslint/scope-manager": "7.10.0",
+
        "@typescript-eslint/type-utils": "7.10.0",
+
        "@typescript-eslint/utils": "7.10.0",
+
        "@typescript-eslint/visitor-keys": "7.10.0",
        "graphemer": "^1.4.0",
-
        "ignore": "^5.2.4",
+
        "ignore": "^5.3.1",
        "natural-compare": "^1.4.0",
-
        "semver": "^7.5.4",
-
        "ts-api-utils": "^1.0.1"
+
        "ts-api-utils": "^1.3.0"
      },
      "engines": {
        "node": "^18.18.0 || >=20.0.0"
@@ -1198,16 +1202,15 @@
      }
    },
    "node_modules/@typescript-eslint/parser": {
-
      "version": "7.4.0",
-
      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.4.0.tgz",
-
      "integrity": "sha512-ZvKHxHLusweEUVwrGRXXUVzFgnWhigo4JurEj0dGF1tbcGh6buL+ejDdjxOQxv6ytcY1uhun1p2sm8iWStlgLQ==",
+
      "version": "7.10.0",
+
      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.10.0.tgz",
+
      "integrity": "sha512-2EjZMA0LUW5V5tGQiaa2Gys+nKdfrn2xiTIBLR4fxmPmVSvgPcKNW+AE/ln9k0A4zDUti0J/GZXMDupQoI+e1w==",
      "dev": true,
-
      "peer": true,
      "dependencies": {
-
        "@typescript-eslint/scope-manager": "7.4.0",
-
        "@typescript-eslint/types": "7.4.0",
-
        "@typescript-eslint/typescript-estree": "7.4.0",
-
        "@typescript-eslint/visitor-keys": "7.4.0",
+
        "@typescript-eslint/scope-manager": "7.10.0",
+
        "@typescript-eslint/types": "7.10.0",
+
        "@typescript-eslint/typescript-estree": "7.10.0",
+
        "@typescript-eslint/visitor-keys": "7.10.0",
        "debug": "^4.3.4"
      },
      "engines": {
@@ -1227,13 +1230,13 @@
      }
    },
    "node_modules/@typescript-eslint/scope-manager": {
-
      "version": "7.4.0",
-
      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz",
-
      "integrity": "sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw==",
+
      "version": "7.10.0",
+
      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.10.0.tgz",
+
      "integrity": "sha512-7L01/K8W/VGl7noe2mgH0K7BE29Sq6KAbVmxurj8GGaPDZXPr8EEQ2seOeAS+mEV9DnzxBQB6ax6qQQ5C6P4xg==",
      "dev": true,
      "dependencies": {
-
        "@typescript-eslint/types": "7.4.0",
-
        "@typescript-eslint/visitor-keys": "7.4.0"
+
        "@typescript-eslint/types": "7.10.0",
+
        "@typescript-eslint/visitor-keys": "7.10.0"
      },
      "engines": {
        "node": "^18.18.0 || >=20.0.0"
@@ -1244,15 +1247,15 @@
      }
    },
    "node_modules/@typescript-eslint/type-utils": {
-
      "version": "7.4.0",
-
      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.4.0.tgz",
-
      "integrity": "sha512-247ETeHgr9WTRMqHbbQdzwzhuyaJ8dPTuyuUEMANqzMRB1rj/9qFIuIXK7l0FX9i9FXbHeBQl/4uz6mYuCE7Aw==",
+
      "version": "7.10.0",
+
      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.10.0.tgz",
+
      "integrity": "sha512-D7tS4WDkJWrVkuzgm90qYw9RdgBcrWmbbRkrLA4d7Pg3w0ttVGDsvYGV19SH8gPR5L7OtcN5J1hTtyenO9xE9g==",
      "dev": true,
      "dependencies": {
-
        "@typescript-eslint/typescript-estree": "7.4.0",
-
        "@typescript-eslint/utils": "7.4.0",
+
        "@typescript-eslint/typescript-estree": "7.10.0",
+
        "@typescript-eslint/utils": "7.10.0",
        "debug": "^4.3.4",
-
        "ts-api-utils": "^1.0.1"
+
        "ts-api-utils": "^1.3.0"
      },
      "engines": {
        "node": "^18.18.0 || >=20.0.0"
@@ -1271,9 +1274,9 @@
      }
    },
    "node_modules/@typescript-eslint/types": {
-
      "version": "7.4.0",
-
      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.4.0.tgz",
-
      "integrity": "sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw==",
+
      "version": "7.10.0",
+
      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.10.0.tgz",
+
      "integrity": "sha512-7fNj+Ya35aNyhuqrA1E/VayQX9Elwr8NKZ4WueClR3KwJ7Xx9jcCdOrLW04h51de/+gNbyFMs+IDxh5xIwfbNg==",
      "dev": true,
      "engines": {
        "node": "^18.18.0 || >=20.0.0"
@@ -1284,19 +1287,19 @@
      }
    },
    "node_modules/@typescript-eslint/typescript-estree": {
-
      "version": "7.4.0",
-
      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz",
-
      "integrity": "sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg==",
+
      "version": "7.10.0",
+
      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.10.0.tgz",
+
      "integrity": "sha512-LXFnQJjL9XIcxeVfqmNj60YhatpRLt6UhdlFwAkjNc6jSUlK8zQOl1oktAP8PlWFzPQC1jny/8Bai3/HPuvN5g==",
      "dev": true,
      "dependencies": {
-
        "@typescript-eslint/types": "7.4.0",
-
        "@typescript-eslint/visitor-keys": "7.4.0",
+
        "@typescript-eslint/types": "7.10.0",
+
        "@typescript-eslint/visitor-keys": "7.10.0",
        "debug": "^4.3.4",
        "globby": "^11.1.0",
        "is-glob": "^4.0.3",
-
        "minimatch": "9.0.3",
-
        "semver": "^7.5.4",
-
        "ts-api-utils": "^1.0.1"
+
        "minimatch": "^9.0.4",
+
        "semver": "^7.6.0",
+
        "ts-api-utils": "^1.3.0"
      },
      "engines": {
        "node": "^18.18.0 || >=20.0.0"
@@ -1312,18 +1315,15 @@
      }
    },
    "node_modules/@typescript-eslint/utils": {
-
      "version": "7.4.0",
-
      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.4.0.tgz",
-
      "integrity": "sha512-NQt9QLM4Tt8qrlBVY9lkMYzfYtNz8/6qwZg8pI3cMGlPnj6mOpRxxAm7BMJN9K0AiY+1BwJ5lVC650YJqYOuNg==",
+
      "version": "7.10.0",
+
      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.10.0.tgz",
+
      "integrity": "sha512-olzif1Fuo8R8m/qKkzJqT7qwy16CzPRWBvERS0uvyc+DHd8AKbO4Jb7kpAvVzMmZm8TrHnI7hvjN4I05zow+tg==",
      "dev": true,
      "dependencies": {
        "@eslint-community/eslint-utils": "^4.4.0",
-
        "@types/json-schema": "^7.0.12",
-
        "@types/semver": "^7.5.0",
-
        "@typescript-eslint/scope-manager": "7.4.0",
-
        "@typescript-eslint/types": "7.4.0",
-
        "@typescript-eslint/typescript-estree": "7.4.0",
-
        "semver": "^7.5.4"
+
        "@typescript-eslint/scope-manager": "7.10.0",
+
        "@typescript-eslint/types": "7.10.0",
+
        "@typescript-eslint/typescript-estree": "7.10.0"
      },
      "engines": {
        "node": "^18.18.0 || >=20.0.0"
@@ -1337,13 +1337,13 @@
      }
    },
    "node_modules/@typescript-eslint/visitor-keys": {
-
      "version": "7.4.0",
-
      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz",
-
      "integrity": "sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA==",
+
      "version": "7.10.0",
+
      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.10.0.tgz",
+
      "integrity": "sha512-9ntIVgsi6gg6FIq9xjEO4VQJvwOqA3jaBFQJ/6TK5AvEup2+cECI6Fh7QiBxmfMHXU0V0J4RyPeOU1VDNzl9cg==",
      "dev": true,
      "dependencies": {
-
        "@typescript-eslint/types": "7.4.0",
-
        "eslint-visitor-keys": "^3.4.1"
+
        "@typescript-eslint/types": "7.10.0",
+
        "eslint-visitor-keys": "^3.4.3"
      },
      "engines": {
        "node": "^18.18.0 || >=20.0.0"
@@ -2232,10 +2232,13 @@
      }
    },
    "node_modules/eslint-compat-utils": {
-
      "version": "0.1.2",
-
      "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.1.2.tgz",
-
      "integrity": "sha512-Jia4JDldWnFNIru1Ehx1H5s9/yxiRHY/TimCuUc0jNexew3cF1gI6CYZil1ociakfWO3rRqFjl1mskBblB3RYg==",
+
      "version": "0.5.0",
+
      "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.5.0.tgz",
+
      "integrity": "sha512-dc6Y8tzEcSYZMHa+CMPLi/hyo1FzNeonbhJL7Ol0ccuKQkwopJcJBA9YL/xmMTLU1eKigXo9vj9nALElWYSowg==",
      "dev": true,
+
      "dependencies": {
+
        "semver": "^7.5.4"
+
      },
      "engines": {
        "node": ">=12"
      },
@@ -2255,33 +2258,24 @@
        "eslint": ">=7.0.0"
      }
    },
-
    "node_modules/eslint-plugin-no-only-tests": {
-
      "version": "3.1.0",
-
      "resolved": "https://registry.npmjs.org/eslint-plugin-no-only-tests/-/eslint-plugin-no-only-tests-3.1.0.tgz",
-
      "integrity": "sha512-Lf4YW/bL6Un1R6A76pRZyE1dl1vr31G/ev8UzIc/geCgFWyrKil8hVjYqWVKGB/UIGmb6Slzs9T0wNezdSVegw==",
-
      "dev": true,
-
      "engines": {
-
        "node": ">=5.0.0"
-
      }
-
    },
    "node_modules/eslint-plugin-svelte": {
-
      "version": "2.35.1",
-
      "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-2.35.1.tgz",
-
      "integrity": "sha512-IF8TpLnROSGy98Z3NrsKXWDSCbNY2ReHDcrYTuXZMbfX7VmESISR78TWgO9zdg4Dht1X8coub5jKwHzP0ExRug==",
+
      "version": "2.39.0",
+
      "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-2.39.0.tgz",
+
      "integrity": "sha512-FXktBLXsrxbA+6ZvJK2z/sQOrUKyzSg3fNWK5h0reSCjr2fjAsc9ai/s/JvSl4Hgvz3nYVtTIMwarZH5RcB7BA==",
      "dev": true,
      "dependencies": {
-
        "@eslint-community/eslint-utils": "^4.2.0",
-
        "@jridgewell/sourcemap-codec": "^1.4.14",
-
        "debug": "^4.3.1",
-
        "eslint-compat-utils": "^0.1.2",
+
        "@eslint-community/eslint-utils": "^4.4.0",
+
        "@jridgewell/sourcemap-codec": "^1.4.15",
+
        "debug": "^4.3.4",
+
        "eslint-compat-utils": "^0.5.0",
        "esutils": "^2.0.3",
-
        "known-css-properties": "^0.29.0",
-
        "postcss": "^8.4.5",
+
        "known-css-properties": "^0.31.0",
+
        "postcss": "^8.4.38",
        "postcss-load-config": "^3.1.4",
        "postcss-safe-parser": "^6.0.0",
-
        "postcss-selector-parser": "^6.0.11",
-
        "semver": "^7.5.3",
-
        "svelte-eslint-parser": ">=0.33.0 <1.0.0"
+
        "postcss-selector-parser": "^6.0.16",
+
        "semver": "^7.6.0",
+
        "svelte-eslint-parser": ">=0.36.0 <1.0.0"
      },
      "engines": {
        "node": "^14.17.0 || >=16.0.0"
@@ -2290,8 +2284,8 @@
        "url": "https://github.com/sponsors/ota-meshi"
      },
      "peerDependencies": {
-
        "eslint": "^7.0.0 || ^8.0.0-0",
-
        "svelte": "^3.37.0 || ^4.0.0"
+
        "eslint": "^7.0.0 || ^8.0.0-0 || ^9.0.0-0",
+
        "svelte": "^3.37.0 || ^4.0.0 || ^5.0.0-next.112"
      },
      "peerDependenciesMeta": {
        "svelte": {
@@ -2327,6 +2321,15 @@
        "url": "https://opencollective.com/eslint"
      }
    },
+
    "node_modules/eslint/node_modules/@eslint/js": {
+
      "version": "8.57.0",
+
      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz",
+
      "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==",
+
      "dev": true,
+
      "engines": {
+
        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+
      }
+
    },
    "node_modules/eslint/node_modules/ansi-styles": {
      "version": "4.3.0",
      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
@@ -2368,6 +2371,21 @@
        "url": "https://github.com/chalk/chalk?sponsor=1"
      }
    },
+
    "node_modules/eslint/node_modules/globals": {
+
      "version": "13.24.0",
+
      "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
+
      "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
+
      "dev": true,
+
      "dependencies": {
+
        "type-fest": "^0.20.2"
+
      },
+
      "engines": {
+
        "node": ">=8"
+
      },
+
      "funding": {
+
        "url": "https://github.com/sponsors/sindresorhus"
+
      }
+
    },
    "node_modules/eslint/node_modules/minimatch": {
      "version": "3.1.2",
      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -2781,15 +2799,12 @@
      }
    },
    "node_modules/globals": {
-
      "version": "13.24.0",
-
      "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
-
      "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
+
      "version": "15.3.0",
+
      "resolved": "https://registry.npmjs.org/globals/-/globals-15.3.0.tgz",
+
      "integrity": "sha512-cCdyVjIUVTtX8ZsPkq1oCsOsLmGIswqnjZYMJJTGaNApj1yHtLSymKhwH51ttirREn75z3p4k051clwg7rvNKA==",
      "dev": true,
-
      "dependencies": {
-
        "type-fest": "^0.20.2"
-
      },
      "engines": {
-
        "node": ">=8"
+
        "node": ">=18"
      },
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
@@ -3323,9 +3338,9 @@
      }
    },
    "node_modules/known-css-properties": {
-
      "version": "0.29.0",
-
      "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.29.0.tgz",
-
      "integrity": "sha512-Ne7wqW7/9Cz54PDt4I3tcV+hAyat8ypyOGzYRJQfdxnnjeWsTxt1cy8pjvvKeI5kfXuyvULyeeAvwvvtAX3ayQ==",
+
      "version": "0.31.0",
+
      "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.31.0.tgz",
+
      "integrity": "sha512-sBPIUGTNF0czz0mwGGUoKKJC8Q7On1GPbCSFPfyEsfHb2DyBG0Y4QtV+EVWpINSaiGKZblDNuF5AezxSgOhesQ==",
      "dev": true
    },
    "node_modules/levn": {
@@ -3656,9 +3671,9 @@
      }
    },
    "node_modules/minimatch": {
-
      "version": "9.0.3",
-
      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
-
      "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+
      "version": "9.0.4",
+
      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz",
+
      "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==",
      "dev": true,
      "dependencies": {
        "brace-expansion": "^2.0.1"
@@ -4691,16 +4706,16 @@
      }
    },
    "node_modules/svelte-eslint-parser": {
-
      "version": "0.33.1",
-
      "resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-0.33.1.tgz",
-
      "integrity": "sha512-vo7xPGTlKBGdLH8T5L64FipvTrqv3OQRx9d2z5X05KKZDlF4rQk8KViZO4flKERY+5BiVdOh7zZ7JGJWo5P0uA==",
+
      "version": "0.36.0",
+
      "resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-0.36.0.tgz",
+
      "integrity": "sha512-/6YmUSr0FAVxW8dXNdIMydBnddPMHzaHirAZ7RrT21XYdgGGZMh0LQG6CZsvAFS4r2Y4ItUuCQc8TQ3urB30mQ==",
      "dev": true,
      "dependencies": {
-
        "eslint-scope": "^7.0.0",
-
        "eslint-visitor-keys": "^3.0.0",
-
        "espree": "^9.0.0",
-
        "postcss": "^8.4.29",
-
        "postcss-scss": "^4.0.8"
+
        "eslint-scope": "^7.2.2",
+
        "eslint-visitor-keys": "^3.4.3",
+
        "espree": "^9.6.1",
+
        "postcss": "^8.4.38",
+
        "postcss-scss": "^4.0.9"
      },
      "engines": {
        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -4709,7 +4724,7 @@
        "url": "https://github.com/sponsors/ota-meshi"
      },
      "peerDependencies": {
-
        "svelte": "^3.37.0 || ^4.0.0"
+
        "svelte": "^3.37.0 || ^4.0.0 || ^5.0.0-next.115"
      },
      "peerDependenciesMeta": {
        "svelte": {
@@ -4922,6 +4937,32 @@
        "node": ">=14.17"
      }
    },
+
    "node_modules/typescript-eslint": {
+
      "version": "7.10.0",
+
      "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.10.0.tgz",
+
      "integrity": "sha512-thO8nyqptXdfWHQrMJJiJyftpW8aLmwRNs11xA8pSrXneoclFPstQZqXvDWuH1WNL4CHffqHvYUeCHTit6yfhQ==",
+
      "dev": true,
+
      "dependencies": {
+
        "@typescript-eslint/eslint-plugin": "7.10.0",
+
        "@typescript-eslint/parser": "7.10.0",
+
        "@typescript-eslint/utils": "7.10.0"
+
      },
+
      "engines": {
+
        "node": "^18.18.0 || >=20.0.0"
+
      },
+
      "funding": {
+
        "type": "opencollective",
+
        "url": "https://opencollective.com/typescript-eslint"
+
      },
+
      "peerDependencies": {
+
        "eslint": "^8.56.0"
+
      },
+
      "peerDependenciesMeta": {
+
        "typescript": {
+
          "optional": true
+
        }
+
      }
+
    },
    "node_modules/uc.micro": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
modified package.json
@@ -18,6 +18,7 @@
    "node": ">=18.17.1"
  },
  "devDependencies": {
+
    "@eslint/js": "^9.3.0",
    "@playwright/test": "^1.42.1",
    "@sveltejs/vite-plugin-svelte": "^3.0.2",
    "@tsconfig/svelte": "^5.0.3",
@@ -29,21 +30,23 @@
    "@types/node": "^20.11.30",
    "@types/sinon": "^17.0.3",
    "@types/wait-on": "^5.3.4",
-
    "@typescript-eslint/eslint-plugin": "^7.4.0",
+
    "@typescript-eslint/parser": "^7.10.0",
    "chalk": "^5.3.0",
    "config": "^3.3.11",
    "eslint": "^8.57.0",
    "eslint-config-prettier": "^9.1.0",
-
    "eslint-plugin-no-only-tests": "^3.1.0",
-
    "eslint-plugin-svelte": "^2.35.1",
+
    "eslint-plugin-svelte": "^2.39.0",
    "execa": "^9.0.0",
    "get-port": "^7.1.0",
+
    "globals": "^15.3.0",
    "happy-dom": "^14.3.8",
    "prettier": "^3.2.5",
    "prettier-plugin-svelte": "^3.2.2",
    "sinon": "^17.0.1",
    "svelte-check": "^3.6.8",
+
    "svelte-eslint-parser": "^0.36.0",
    "typescript": "^5.4.3",
+
    "typescript-eslint": "^7.10.0",
    "vite": "^5.2.6",
    "vite-plugin-virtual": "^0.3.0",
    "vitest": "^1.4.0",
modified src/components/DropdownList.svelte
@@ -1,6 +1,4 @@
-
<script lang="ts">
-
  type T = $$Generic;
-

+
<script lang="ts" generics="T">
  export let items: T[];
  export let styleDropdownMinWidth: string | undefined = undefined;
</script>
modified src/components/HoverPopover.svelte
@@ -1,6 +1,7 @@
<script lang="ts">
  import debounce from "lodash/debounce";

+
  // eslint-disable-next-line @typescript-eslint/no-empty-function
  export let onShow: () => void = () => {};
  export let stylePopoverPositionLeft: string | undefined = undefined;
  export let stylePopoverPositionRight: string | undefined = undefined;
modified src/components/List.svelte
@@ -1,6 +1,4 @@
-
<script lang="ts">
-
  type T = $$Generic;
-

+
<script lang="ts" generics="T">
  export let items: T[];
</script>

modified src/components/Markdown.svelte
@@ -32,6 +32,7 @@
  export let breaks: boolean = false;

  let container: HTMLElement;
+
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  let frontMatter: [string, any][] | undefined = undefined;

  $: {
modified src/lib/utils.ts
@@ -286,10 +286,12 @@ export function twemoji(
  { exclude }: { exclude: string[] } = { exclude: [] },
) {
  twemojiModule.parse(node, {
-
    callback: (icon, options: Record<string, any>) => {
-
      return exclude.includes(icon)
-
        ? false
-
        : "".concat(options.base, options.size, "/", icon, options.ext);
+
    callback: (icon, options) => {
+
      const { base, size, ext } = options as Record<string, string>;
+
      if (!exclude.includes(icon)) {
+
        return `${base}${size}/${icon}${ext}`;
+
      }
+
      return false;
    },
    base: "/",
    folder: "twemoji",
modified src/views/nodes/router.ts
@@ -1,10 +1,12 @@
import type { BaseUrl, NodeStats, Policy, Scope } from "@httpd-client";
import type { ErrorRoute, NotFoundRoute } from "@app/lib/router/definitions";

-
import { HttpdClient } from "@httpd-client";
import config from "virtual:config";
+
import { HttpdClient } from "@httpd-client";
+
import { ResponseError, ResponseParseError } from "@httpd-client/lib/fetcher";
import { baseUrlToString } from "@app/lib/utils";
import { handleError } from "@app/views/nodes/error";
+
import { unreachableError } from "@app/views/projects/error";

export interface NodesRouteParams {
  baseUrl: BaseUrl;
@@ -58,7 +60,15 @@ export async function loadNodeRoute(
        scope: node.config?.scope,
      },
    };
-
  } catch (error: any) {
-
    return handleError(error, baseUrlToString(api.baseUrl));
+
  } catch (error) {
+
    if (
+
      error instanceof Error ||
+
      error instanceof ResponseError ||
+
      error instanceof ResponseParseError
+
    ) {
+
      return handleError(error, baseUrlToString(api.baseUrl));
+
    } else {
+
      return unreachableError();
+
    }
  }
}
modified src/views/projects/Cob/CobStateButton.svelte
@@ -1,4 +1,4 @@
-
<script lang="ts">
+
<script lang="ts" generics="CobState">
  import IconSmall from "@app/components/IconSmall.svelte";

  import isEqual from "lodash/isEqual";
@@ -11,8 +11,6 @@
  import Icon from "@app/components/Icon.svelte";
  import Button from "@app/components/Button.svelte";

-
  type CobState = $$Generic;
-

  export let state: CobState;
  export let selectedItem: [string, CobState];
  export let items: [string, CobState][];
modified src/views/projects/Cob/Revision.svelte
@@ -122,6 +122,7 @@
  type State = "read" | "submit" | "edit";

  let response: DiffResponse | undefined = undefined;
+
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  let error: any | undefined = undefined;
  let loading: boolean = false;
  let revisionState: State = "read";
@@ -135,6 +136,7 @@
    try {
      loading = true;
      response = await api.project.getDiff(projectId, fromCommit, revisionOid);
+
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
    } catch (err: any) {
      error = err;
    } finally {
modified src/views/projects/History.svelte
@@ -35,6 +35,7 @@

  const api = new HttpdClient(baseUrl);

+
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  let error: any;
  let page = 0;
  let loading = false;
modified src/views/projects/Issues.svelte
@@ -30,6 +30,7 @@

  let loading = false;
  let page = 0;
+
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  let error: any;
  let allIssues: Issue[];

modified src/views/projects/Patches.svelte
@@ -31,6 +31,7 @@

  let loading = false;
  let page = 0;
+
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  let error: any;
  let allPatches: Patch[];

modified src/views/projects/error.ts
@@ -73,3 +73,15 @@ export function handleError(
    };
  }
}
+

+
export function unreachableError(): NotFoundRoute | ErrorRoute {
+
  return {
+
    resource: "error",
+
    params: {
+
      error: undefined,
+
      title: "Could not load this route",
+
      description:
+
        "You stumbled on an unknown error, we aren't exactly sure what happened.",
+
    },
+
  };
+
}
modified src/views/projects/router.ts
@@ -23,12 +23,12 @@ import type {
import * as Syntax from "@app/lib/syntax";
import * as httpd from "@app/lib/httpd";
import { HttpdClient } from "@httpd-client";
-
import { ResponseError } from "@httpd-client/lib/fetcher";
-
import { handleError } from "@app/views/projects/error";
+
import { ResponseError, ResponseParseError } from "@httpd-client/lib/fetcher";
+
import { experimental } from "@app/lib/appearance";
+
import { get } from "svelte/store";
+
import { handleError, unreachableError } from "@app/views/projects/error";
import { nodePath } from "@app/views/nodes/router";
import { unreachable } from "@app/lib/utils";
-
import { get } from "svelte/store";
-
import { experimental } from "@app/lib/appearance";

export const COMMITS_PER_PAGE = 30;
export const PATCHES_PER_PAGE = 10;
@@ -315,8 +315,16 @@ export async function loadProjectRoute(
    } else {
      return unreachable(route);
    }
-
  } catch (error: any) {
-
    return handleError(error, route);
+
  } catch (error) {
+
    if (
+
      error instanceof Error ||
+
      error instanceof ResponseError ||
+
      error instanceof ResponseParseError
+
    ) {
+
      return handleError(error, route);
+
    } else {
+
      return unreachableError();
+
    }
  }
}

modified tests/support/peerManager.ts
@@ -331,6 +331,7 @@ export class RadiclePeer {

  public async stopNode() {
    // Don’t leak unhandled rejections when forcefully killing the process
+
    // eslint-disable-next-line @typescript-eslint/no-empty-function
    this.#nodeProcess?.catch(() => {});
    this.#nodeProcess?.kill("SIGTERM");

@@ -350,6 +351,7 @@ export class RadiclePeer {
    // processes are running anymore.
    this.#childProcesses.forEach(p => {
      // Don’t leak unhandled rejections when forcefully killing the process
+
      // eslint-disable-next-line @typescript-eslint/no-empty-function
      p.catch(() => {});
      p.kill("SIGKILL");
    });
modified tests/unit/mutexExecutor.test.ts
@@ -95,7 +95,7 @@ describe("worker", () => {
    });

    const outputs: number[] = [];
-
    w.output.onValue((value: any) => outputs.push(value));
+
    w.output.onValue((value: never) => outputs.push(value));

    await w.submit(1);
    await w.submit(2);