From c9dafc85fde2ac5700585a8bbb7f9af92f5cf145 Mon Sep 17 00:00:00 2001 From: James Brunton Date: Wed, 25 Feb 2026 14:30:40 +0000 Subject: [PATCH] Switch to use ESLint 10 (#5794) --- frontend/package-lock.json | 321 +++++------------- frontend/package.json | 12 +- .../pageEditor/hooks/usePageDocument.ts | 39 ++- .../src/core/components/shared/LocalIcon.tsx | 3 +- .../tools/addStamp/StampPreviewUtils.ts | 3 +- .../tools/fullscreen/CompactToolItem.tsx | 3 +- .../tools/fullscreen/DetailedToolItem.tsx | 5 +- .../tools/convert/useConvertParameters.ts | 2 +- .../useRemoveAnnotationsOperation.ts | 7 +- .../hooks/tools/shared/useToolApiCalls.ts | 2 +- .../validateSignature/signatureReportPdf.ts | 4 +- frontend/src/core/hooks/useCookieConsent.ts | 8 +- frontend/src/core/services/fileStorage.ts | 4 +- .../src/core/services/pdfExportService.ts | 10 +- frontend/src/core/services/zipFileService.ts | 5 +- .../tools/pdfTextEditor/PdfTextEditor.tsx | 12 +- frontend/src/core/utils/automationExecutor.ts | 4 +- frontend/src/core/utils/imageToPdfUtils.ts | 3 +- frontend/src/core/workers/compareWorker.ts | 11 +- frontend/src/desktop/services/authService.ts | 32 +- 20 files changed, 173 insertions(+), 317 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index a3d912bbef..8f04217e93 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -77,7 +77,7 @@ "web-vitals": "^5.1.0" }, "devDependencies": { - "@eslint/js": "^9.36.0", + "@eslint/js": "^10.0.1", "@iconify-json/material-symbols": "^1.2.53", "@iconify/utils": "^3.1.0", "@playwright/test": "^1.55.0", @@ -98,8 +98,7 @@ "@vitejs/plugin-react-swc": "^4.1.0", "@vitest/coverage-v8": "^3.2.4", "dpdm": "^3.14.0", - "eslint": "^9.36.0", - "eslint-plugin-react-hooks": "^5.2.0", + "eslint": "^10.0.2", "jsdom": "^27.0.0", "license-checker": "^25.0.1", "madge": "^8.0.0", @@ -1682,190 +1681,89 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", - "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.2.tgz", + "integrity": "sha512-YF+fE6LV4v5MGWRGj7G404/OZzGNepVF8fxk7jqmqo3lrza7a0uUcDnROGRBG1WFC1omYUS/Wp1f42i0M+3Q3A==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.7", + "@eslint/object-schema": "^3.0.2", "debug": "^4.3.1", - "minimatch": "^3.1.2" + "minimatch": "^10.2.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-array/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.3.tgz", - "integrity": "sha512-M2GCs7Vk83NxkUyQV1bkABc4yxgz9kILhHImZiBPAZ9ybuvCb0/H7lEl5XvIg3g+9d4eNotkZA5IWwYl0tibaA==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@eslint/config-helpers": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", - "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.2.tgz", + "integrity": "sha512-a5MxrdDXEvqnIq+LisyCX6tQMPF/dSJpCfBgBauY+pNZ28yCtSsTvyTYrMhaI+LK26bVyCJfJkT0u8KIj2i1dQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.17.0" + "@eslint/core": "^1.1.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@eslint/core": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", - "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.1.0.tgz", + "integrity": "sha512-/nr9K9wkr3P1EzFTdFdMoLuo1PmIxjmwvPozwoSodjNBdefGujXQUF93u1DDZpEaTuDvMsIQddsd35BwtrW9Xw==", "dev": true, "license": "Apache-2.0", "dependencies": { "@types/json-schema": "^7.0.15" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.4.tgz", - "integrity": "sha512-4h4MVF8pmBsncB60r0wSJiIeUKTSD4m7FmTFThG8RHlsg9ajqckLm9OraguFGZE4vVdpiI1Q4+hFnisopmG6gQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.14.0", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.1", - "minimatch": "^3.1.3", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.3.tgz", - "integrity": "sha512-M2GCs7Vk83NxkUyQV1bkABc4yxgz9kILhHImZiBPAZ9ybuvCb0/H7lEl5XvIg3g+9d4eNotkZA5IWwYl0tibaA==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@eslint/js": { - "version": "9.39.3", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.3.tgz", - "integrity": "sha512-1B1VkCq6FuUNlQvlBYb+1jDu/gV297TIs/OeiaSR9l1H27SVW55ONE1e1Vp16NqP683+xEGzxYtv4XCiDPaQiw==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz", + "integrity": "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==", "dev": true, "license": "MIT", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "eslint": "^10.0.0" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, "node_modules/@eslint/object-schema": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", - "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.2.tgz", + "integrity": "sha512-HOy56KJt48Bx8KmJ+XGQNSUMT/6dZee/M54XyUyuvTvPXJmsERRvBchsUVx1UMe1WwIH49XLAczNC7V2INsuUw==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@eslint/plugin-kit": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", - "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.6.0.tgz", + "integrity": "sha512-bIZEUzOI1jkhviX2cp5vNyXQc6olzb2ohewQubuYlMXZ2Q/XjBO0x0XhGPvc9fjSIiUN0vw+0hq53BJ4eQSJKQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.17.0", + "@eslint/core": "^1.1.0", "levn": "^0.4.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@exodus/bytes": { @@ -4732,6 +4630,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/esrecurse": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", + "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -7246,33 +7151,30 @@ } }, "node_modules/eslint": { - "version": "9.39.3", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.3.tgz", - "integrity": "sha512-VmQ+sifHUbI/IcSopBCF/HO3YiHQx/AVd3UVyYL6weuwW+HvON9VYn5l6Zl1WZzPWXPNZrSQpxwkkZ/VuvJZzg==", + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.0.2.tgz", + "integrity": "sha512-uYixubwmqJZH+KLVYIVKY1JQt7tysXhtj21WSvjcSmU5SVNzMus1bgLe+pAt816yQ8opKfheVVoPLqvVMGejYw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.1", - "@eslint/config-helpers": "^0.4.2", - "@eslint/core": "^0.17.0", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.39.3", - "@eslint/plugin-kit": "^0.4.1", + "@eslint-community/regexpp": "^4.12.2", + "@eslint/config-array": "^0.23.2", + "@eslint/config-helpers": "^0.5.2", + "@eslint/core": "^1.1.0", + "@eslint/plugin-kit": "^0.6.0", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", - "ajv": "^6.12.4", - "chalk": "^4.0.0", + "ajv": "^6.14.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.4.0", - "eslint-visitor-keys": "^4.2.1", - "espree": "^10.4.0", - "esquery": "^1.5.0", + "eslint-scope": "^9.1.1", + "eslint-visitor-keys": "^5.0.1", + "espree": "^11.1.1", + "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", @@ -7282,8 +7184,7 @@ "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", + "minimatch": "^10.2.1", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, @@ -7291,7 +7192,7 @@ "eslint": "bin/eslint.js" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://eslint.org/donate" @@ -7305,31 +7206,20 @@ } } }, - "node_modules/eslint-plugin-react-hooks": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", - "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" - } - }, "node_modules/eslint-scope": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.1.tgz", + "integrity": "sha512-GaUN0sWim5qc8KVErfPBWmc31LEsOkrUJbvJZV+xuL3u2phMUK4HIvXlWAakfC8W4nzlK+chPEAkYOYb5ZScIw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { + "@types/esrecurse": "^4.3.1", + "@types/estree": "^1.0.8", "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" @@ -7348,32 +7238,14 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" @@ -7389,19 +7261,6 @@ "node": ">= 4" } }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.3.tgz", - "integrity": "sha512-M2GCs7Vk83NxkUyQV1bkABc4yxgz9kILhHImZiBPAZ9ybuvCb0/H7lEl5XvIg3g+9d4eNotkZA5IWwYl0tibaA==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/esm-env": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz", @@ -7410,31 +7269,31 @@ "peer": true }, "node_modules/espree": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", - "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.1.1.tgz", + "integrity": "sha512-AVHPqQoZYc+RUM4/3Ly5udlZY/U4LS8pIG05jEjWM2lQMU/oaZ7qshzAl2YP1tfNmXfftH3ohurfwNAug+MnsQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.15.0", + "acorn": "^8.16.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.1" + "eslint-visitor-keys": "^5.0.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" @@ -9367,13 +9226,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" - }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -12030,19 +11882,6 @@ "node": ">=8" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/strip-literal": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.1.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index 330307e66d..2cec377c79 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -111,13 +111,6 @@ "update:interactive": "npx npm-check-updates -i", "update:minor-strict": "npx npm-check-updates -u --target minor && npm install" }, - "eslintConfig": { - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended", - "plugin:react-hooks/recommended" - ] - }, "browserslist": { "production": [ ">0.2%", @@ -131,7 +124,7 @@ ] }, "devDependencies": { - "@eslint/js": "^9.36.0", + "@eslint/js": "^10.0.1", "@iconify-json/material-symbols": "^1.2.53", "@iconify/utils": "^3.1.0", "@playwright/test": "^1.55.0", @@ -152,8 +145,7 @@ "@vitejs/plugin-react-swc": "^4.1.0", "@vitest/coverage-v8": "^3.2.4", "dpdm": "^3.14.0", - "eslint": "^9.36.0", - "eslint-plugin-react-hooks": "^5.2.0", + "eslint": "^10.0.2", "jsdom": "^27.0.0", "license-checker": "^25.0.1", "madge": "^8.0.0", diff --git a/frontend/src/core/components/pageEditor/hooks/usePageDocument.ts b/frontend/src/core/components/pageEditor/hooks/usePageDocument.ts index 4e32557644..6494e7bd0a 100644 --- a/frontend/src/core/components/pageEditor/hooks/usePageDocument.ts +++ b/frontend/src/core/components/pageEditor/hooks/usePageDocument.ts @@ -217,7 +217,7 @@ export function usePageDocument(): PageDocumentHook { }); // Build pages by interleaving original pages with insertions - let pages: PDFPage[] = []; + let pages: PDFPage[]; // Helper function to create pages from a file (or placeholder if deselected) const createPagesFromFile = (fileId: FileId, startPageNumber: number, isSelected: boolean): PDFPage[] => { @@ -242,11 +242,10 @@ export function usePageDocument(): PageDocumentHook { } const processedFile = stirlingFileStub.processedFile; - let filePages: PDFPage[] = []; if (processedFile?.pages && processedFile.pages.length > 0) { // Use fully processed pages with thumbnails - filePages = processedFile.pages.map((page, pageIndex) => ({ + return processedFile.pages.map((page, pageIndex) => ({ id: `${fileId}-${pageIndex + 1}`, pageNumber: startPageNumber + pageIndex, thumbnail: page.thumbnail || null, @@ -259,9 +258,11 @@ export function usePageDocument(): PageDocumentHook { originalFileId: fileId, isPlaceholder: false, })); - } else if (processedFile?.totalPages) { + } + + if (processedFile?.totalPages) { // Fallback: create pages without thumbnails but with correct count - filePages = Array.from({ length: processedFile.totalPages }, (_, pageIndex) => ({ + return Array.from({ length: processedFile.totalPages }, (_, pageIndex) => ({ id: `${fileId}-${pageIndex + 1}`, pageNumber: startPageNumber + pageIndex, originalPageNumber: pageIndex + 1, @@ -272,23 +273,21 @@ export function usePageDocument(): PageDocumentHook { splitAfter: false, isPlaceholder: false, })); - } else { - // No processedFile yet - create a single loading placeholder - // This will be replaced when processing completes - filePages = [{ - id: `${fileId}-loading`, - pageNumber: startPageNumber, - originalPageNumber: 1, - originalFileId: fileId, - rotation: 0, - thumbnail: null, - selected: false, - splitAfter: false, - isPlaceholder: true, - }]; } - return filePages; + // No processedFile yet - create a single loading placeholder + // This will be replaced when processing completes + return [{ + id: `${fileId}-loading`, + pageNumber: startPageNumber, + originalPageNumber: 1, + originalFileId: fileId, + rotation: 0, + thumbnail: null, + selected: false, + splitAfter: false, + isPlaceholder: true, + }]; }; // Collect all pages from original files, respecting their previous positions diff --git a/frontend/src/core/components/shared/LocalIcon.tsx b/frontend/src/core/components/shared/LocalIcon.tsx index a9b7198fc2..ff7ca493af 100644 --- a/frontend/src/core/components/shared/LocalIcon.tsx +++ b/frontend/src/core/components/shared/LocalIcon.tsx @@ -4,13 +4,12 @@ import iconSet from '../../../assets/material-symbols-icons.json'; // eslint-dis // Load icons synchronously at import time - guaranteed to be ready on first render let iconsLoaded = false; -let localIconCount = 0; try { if (iconSet) { addCollection(iconSet); iconsLoaded = true; - localIconCount = Object.keys(iconSet.icons || {}).length; + const localIconCount = Object.keys(iconSet.icons || {}).length; console.info(`✅ Local icons loaded: ${localIconCount} icons (${Math.round(JSON.stringify(iconSet).length / 1024)}KB)`); } } catch { diff --git a/frontend/src/core/components/tools/addStamp/StampPreviewUtils.ts b/frontend/src/core/components/tools/addStamp/StampPreviewUtils.ts index 768df7120e..6d22ba0d7e 100644 --- a/frontend/src/core/components/tools/addStamp/StampPreviewUtils.ts +++ b/frontend/src/core/components/tools/addStamp/StampPreviewUtils.ts @@ -110,7 +110,7 @@ export function computeStampPreviewStyle( // Convert measured px width back to PDF points using horizontal scale widthPtsContent = measuredWidthPx / scaleX; - let adjustmentFactor = 1.0; + let adjustmentFactor: number; switch (parameters.alphabet) { case 'roman': adjustmentFactor = 0.90; @@ -126,6 +126,7 @@ export function computeStampPreviewStyle( break; default: adjustmentFactor = 0.93; + break; } widthPtsContent *= adjustmentFactor; } diff --git a/frontend/src/core/components/tools/fullscreen/CompactToolItem.tsx b/frontend/src/core/components/tools/fullscreen/CompactToolItem.tsx index e89587c66a..d52fac33b7 100644 --- a/frontend/src/core/components/tools/fullscreen/CompactToolItem.tsx +++ b/frontend/src/core/components/tools/fullscreen/CompactToolItem.tsx @@ -22,7 +22,7 @@ const CompactToolItem: React.FC = ({ id, tool, isSelected, const iconBg = getIconBackground(categoryColor, false); const iconClasses = 'tool-panel__fullscreen-list-icon'; - let iconNode: React.ReactNode = null; + let iconNode: React.ReactNode; if (React.isValidElement<{ style?: React.CSSProperties }>(tool.icon)) { const element = tool.icon as React.ReactElement<{ style?: React.CSSProperties }>; iconNode = React.cloneElement(element, { @@ -120,4 +120,3 @@ const CompactToolItem: React.FC = ({ id, tool, isSelected, export default CompactToolItem; - diff --git a/frontend/src/core/components/tools/fullscreen/DetailedToolItem.tsx b/frontend/src/core/components/tools/fullscreen/DetailedToolItem.tsx index 19866e41ca..1ff93fbdf8 100644 --- a/frontend/src/core/components/tools/fullscreen/DetailedToolItem.tsx +++ b/frontend/src/core/components/tools/fullscreen/DetailedToolItem.tsx @@ -21,7 +21,7 @@ const DetailedToolItem: React.FC = ({ id, tool, isSelecte const iconBg = getIconBackground(categoryColor, true); const iconClasses = 'tool-panel__fullscreen-icon'; - let iconNode: React.ReactNode = null; + let iconNode: React.ReactNode; if (React.isValidElement<{ style?: React.CSSProperties }>(tool.icon)) { const element = tool.icon as React.ReactElement<{ style?: React.CSSProperties }>; iconNode = React.cloneElement(element, { @@ -70,7 +70,7 @@ const DetailedToolItem: React.FC = ({ id, tool, isSelecte color="orange" > {/* we can add more translations for different badges in future, like beta, etc. */} - {t('toolPanel.alpha', 'Alpha')} + {t('toolPanel.alpha', 'Alpha')} )} @@ -106,4 +106,3 @@ const DetailedToolItem: React.FC = ({ id, tool, isSelecte export default DetailedToolItem; - diff --git a/frontend/src/core/hooks/tools/convert/useConvertParameters.ts b/frontend/src/core/hooks/tools/convert/useConvertParameters.ts index ee812927f5..ed9df40513 100644 --- a/frontend/src/core/hooks/tools/convert/useConvertParameters.ts +++ b/frontend/src/core/hooks/tools/convert/useConvertParameters.ts @@ -133,7 +133,7 @@ const validateParameters = (params: ConvertParameters): boolean => { if (!fromExtension || !toExtension) return false; // Handle dynamic format identifiers (file-) - let supportedToExtensions: string[] = []; + let supportedToExtensions: string[]; if (fromExtension.startsWith('file-')) { // Dynamic format - use 'any' conversion options supportedToExtensions = CONVERSION_MATRIX['any'] || []; diff --git a/frontend/src/core/hooks/tools/removeAnnotations/useRemoveAnnotationsOperation.ts b/frontend/src/core/hooks/tools/removeAnnotations/useRemoveAnnotationsOperation.ts index 359f134b51..99bf65dd23 100644 --- a/frontend/src/core/hooks/tools/removeAnnotations/useRemoveAnnotationsOperation.ts +++ b/frontend/src/core/hooks/tools/removeAnnotations/useRemoveAnnotationsOperation.ts @@ -71,7 +71,10 @@ const removeAnnotationsProcessor = async (_parameters: RemoveAnnotationsParamete processedFiles.push(processedFile); } catch (error) { console.error('Error processing file:', file.name, error); - throw new Error(`Failed to process ${file.name}: ${error instanceof Error ? error.message : 'Unknown error'}`); + throw new Error( + `Failed to process ${file.name}: ${error instanceof Error ? error.message : 'Unknown error'}`, + { cause: error } + ); } } @@ -96,4 +99,4 @@ export const useRemoveAnnotationsOperation = () => { ...removeAnnotationsOperationConfig, getErrorMessage: createStandardErrorHandler(t('removeAnnotations.error.failed', 'An error occurred while removing annotations from the PDF.')) }); -}; \ No newline at end of file +}; diff --git a/frontend/src/core/hooks/tools/shared/useToolApiCalls.ts b/frontend/src/core/hooks/tools/shared/useToolApiCalls.ts index 1ab8925f14..ee79122e28 100644 --- a/frontend/src/core/hooks/tools/shared/useToolApiCalls.ts +++ b/frontend/src/core/hooks/tools/shared/useToolApiCalls.ts @@ -77,7 +77,7 @@ export const useToolApiCalls = () => { } catch (error) { if (axios.isCancel(error)) { - throw new Error('Operation was cancelled'); + throw new Error('Operation was cancelled', { cause: error }); } console.error('[processFiles] Failed', { name: file.name, error }); failedFiles.push(file.name); diff --git a/frontend/src/core/hooks/tools/validateSignature/signatureReportPdf.ts b/frontend/src/core/hooks/tools/validateSignature/signatureReportPdf.ts index 486c0ccd00..589b437cc8 100644 --- a/frontend/src/core/hooks/tools/validateSignature/signatureReportPdf.ts +++ b/frontend/src/core/hooks/tools/validateSignature/signatureReportPdf.ts @@ -71,7 +71,7 @@ export const createReportPdf = async ( cursorY -= 16; if (entry.error) { - cursorY = drawCenteredMessage({ + drawCenteredMessage({ page, font, fontBold, @@ -86,7 +86,7 @@ export const createReportPdf = async ( } if (entry.signatures.length === 0) { - cursorY = drawCenteredMessage({ + drawCenteredMessage({ page, font, fontBold, diff --git a/frontend/src/core/hooks/useCookieConsent.ts b/frontend/src/core/hooks/useCookieConsent.ts index 40c1a196dc..d74a33dc05 100644 --- a/frontend/src/core/hooks/useCookieConsent.ts +++ b/frontend/src/core/hooks/useCookieConsent.ts @@ -71,8 +71,7 @@ export const useCookieConsent = ({ const hasDarkClass = document.documentElement.classList.contains('dark'); const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; - let isDarkMode = false; - + let isDarkMode: boolean; if (mantineScheme) { isDarkMode = mantineScheme === 'dark'; } else if (hasLightClass) { @@ -94,9 +93,8 @@ export const useCookieConsent = ({ return; } - let themeObserver: MutationObserver | null = null; if (!forceLightMode) { - themeObserver = new MutationObserver((mutations) => { + const themeObserver = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.type === 'attributes' && (mutation.attributeName === 'data-mantine-color-scheme' || @@ -241,7 +239,7 @@ export const useCookieConsent = ({ const hasDarkClass = document.documentElement.classList.contains('dark'); const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; - let isDarkMode = false; + let isDarkMode: boolean; if (mantineScheme) { isDarkMode = mantineScheme === 'dark'; } else if (hasLightClass) { diff --git a/frontend/src/core/services/fileStorage.ts b/frontend/src/core/services/fileStorage.ts index 3668f5cf2d..e7b5a203a9 100644 --- a/frontend/src/core/services/fileStorage.ts +++ b/frontend/src/core/services/fileStorage.ts @@ -335,10 +335,10 @@ class FileStorageService { * Get storage statistics */ async getStorageStats(): Promise { - let used = 0; + let used: number; + let fileCount: number; let available = 0; let quota: number | undefined; - let fileCount = 0; try { // Get browser quota for context diff --git a/frontend/src/core/services/pdfExportService.ts b/frontend/src/core/services/pdfExportService.ts index f0b66c2cb5..c5fdb02f42 100644 --- a/frontend/src/core/services/pdfExportService.ts +++ b/frontend/src/core/services/pdfExportService.ts @@ -37,7 +37,10 @@ export class PDFExportService { return { blob, filename: exportFilename }; } catch (error) { console.error('PDF export error:', error); - throw new Error(`Failed to export PDF: ${error instanceof Error ? error.message : 'Unknown error'}`); + throw new Error( + `Failed to export PDF: ${error instanceof Error ? error.message : 'Unknown error'}`, + { cause: error } + ); } } @@ -68,7 +71,10 @@ export class PDFExportService { return { blob, filename: exportFilename }; } catch (error) { console.error('Multi-file PDF export error:', error); - throw new Error(`Failed to export PDF: ${error instanceof Error ? error.message : 'Unknown error'}`); + throw new Error( + `Failed to export PDF: ${error instanceof Error ? error.message : 'Unknown error'}`, + { cause: error } + ); } } diff --git a/frontend/src/core/services/zipFileService.ts b/frontend/src/core/services/zipFileService.ts index f4ed398652..565e90e754 100644 --- a/frontend/src/core/services/zipFileService.ts +++ b/frontend/src/core/services/zipFileService.ts @@ -162,7 +162,10 @@ export class ZipFileService { return { zipFile, size: zipFile.size }; } catch (error) { - throw new Error(`Failed to create ZIP file: ${error instanceof Error ? error.message : 'Unknown error'}`); + throw new Error( + `Failed to create ZIP file: ${error instanceof Error ? error.message : 'Unknown error'}`, + { cause: error } + ); } } diff --git a/frontend/src/core/tools/pdfTextEditor/PdfTextEditor.tsx b/frontend/src/core/tools/pdfTextEditor/PdfTextEditor.tsx index deeb28ca71..9b09f27d00 100644 --- a/frontend/src/core/tools/pdfTextEditor/PdfTextEditor.tsx +++ b/frontend/src/core/tools/pdfTextEditor/PdfTextEditor.tsx @@ -687,7 +687,7 @@ const PdfTextEditor = ({ onComplete, onError }: BaseToolProps) => { message: pollError?.message, }); if (pollError?.response?.status === 404) { - throw new Error('Job not found on server'); + throw new Error('Job not found on server', { cause: pollError }); } } } @@ -1164,7 +1164,9 @@ const PdfTextEditor = ({ onComplete, onError }: BaseToolProps) => { return; } catch (incrementalError) { if (isLazyMode && cachedJobIdRef.current) { - throw new Error('Incremental export failed for cached document. Please reload and retry.'); + throw new Error('Incremental export failed for cached document. Please reload and retry.', { + cause: incrementalError, + }); } console.warn( '[handleGeneratePdf] Incremental export failed, falling back to full export', @@ -1340,7 +1342,9 @@ const PdfTextEditor = ({ onComplete, onError }: BaseToolProps) => { pdfBlob = response.data; } catch (incrementalError) { if (isLazyMode && cachedJobId) { - throw new Error('Incremental export failed for cached document. Please reload and retry.'); + throw new Error('Incremental export failed for cached document. Please reload and retry.', { + cause: incrementalError, + }); } console.warn( '[handleSaveToWorkbench] Incremental export failed, falling back to full export', @@ -1354,7 +1358,7 @@ const PdfTextEditor = ({ onComplete, onError }: BaseToolProps) => { const payload = buildPayload(); if (!payload) { - throw new Error('Failed to build payload'); + throw new Error('Failed to build payload', { cause: incrementalError }); } const { document, filename } = payload; diff --git a/frontend/src/core/utils/automationExecutor.ts b/frontend/src/core/utils/automationExecutor.ts index 7f88015595..24679bdb71 100644 --- a/frontend/src/core/utils/automationExecutor.ts +++ b/frontend/src/core/utils/automationExecutor.ts @@ -174,7 +174,9 @@ export const executeToolOperationWithPrefix = async ( } catch (error: any) { console.error(`❌ ${operationName} failed:`, error); - throw new Error(`${operationName} operation failed: ${error.response?.data || error.message}`); + throw new Error(`${operationName} operation failed: ${error.response?.data || error.message}`, { + cause: error, + }); } }; diff --git a/frontend/src/core/utils/imageToPdfUtils.ts b/frontend/src/core/utils/imageToPdfUtils.ts index 26b3848ec2..1139553c7a 100644 --- a/frontend/src/core/utils/imageToPdfUtils.ts +++ b/frontend/src/core/utils/imageToPdfUtils.ts @@ -139,7 +139,8 @@ export async function convertImageToPdf( } catch (error) { console.error('Error converting image to PDF:', error); throw new Error( - `Failed to convert image to PDF: ${error instanceof Error ? error.message : 'Unknown error'}` + `Failed to convert image to PDF: ${error instanceof Error ? error.message : 'Unknown error'}`, + { cause: error } ); } } diff --git a/frontend/src/core/workers/compareWorker.ts b/frontend/src/core/workers/compareWorker.ts index 0e3a323e1c..edf378180e 100644 --- a/frontend/src/core/workers/compareWorker.ts +++ b/frontend/src/core/workers/compareWorker.ts @@ -167,10 +167,10 @@ const chunkedDiff = ( const remaining2 = Math.max(0, words2.length - index2); let windowSize = Math.max(dynamicChunkSize, buffer1.length, buffer2.length); - let window1: string[] = []; - let window2: string[] = []; - let chunkTokens: CompareDiffToken[] = []; - let reachedEnd = false; + let window1: string[]; + let window2: string[]; + let chunkTokens: CompareDiffToken[]; + let reachedEnd: boolean; while (true) { const take1 = Math.min(Math.max(0, windowSize - buffer1.length), remaining1); @@ -220,7 +220,6 @@ const chunkedDiff = ( flushRemainder(); return; } - windowSize = Math.min(windowSize + dynamicStep, dynamicMaxWindow); stallIterations += 1; if (stallIterations >= 3) { increaseChunkSizes(); @@ -422,7 +421,7 @@ self.onmessage = (event: MessageEvent) => { }, { maxProcessedTokens: runtimeMaxProcessedTokens, minUnchangedRatio: runtimeMinUnchangedRatio } ); - } catch (err) { + } catch (err) { const error = err as Error & { __earlyStop?: boolean }; if (error && (error.__earlyStop || error.message === 'EARLY_STOP_TOO_DISSIMILAR')) { const response: CompareWorkerResponse = { diff --git a/frontend/src/desktop/services/authService.ts b/frontend/src/desktop/services/authService.ts index c02d67bb65..5489f169b9 100644 --- a/frontend/src/desktop/services/authService.ts +++ b/frontend/src/desktop/services/authService.ts @@ -247,9 +247,9 @@ export class AuthService { error.response?.data?.msg || error.response?.data?.message || error.message; - throw new Error(message || 'Sign up failed'); + throw new Error(message || 'Sign up failed', { cause: error }); } - throw error instanceof Error ? error : new Error('Sign up failed'); + throw error instanceof Error ? error : new Error('Sign up failed', { cause: error }); } } @@ -282,7 +282,7 @@ export class AuthService { await this.saveTokenEverywhere(token); } catch (error) { console.error('[Desktop AuthService] Failed to save token:', error); - throw new Error('Failed to save authentication token'); + throw new Error('Failed to save authentication token', { cause: error }); } // Save user info to store @@ -320,37 +320,49 @@ export class AuthService { // Authentication errors if (errMsg.includes('401') || errMsg.includes('unauthorized') || errMsg.includes('invalid credentials')) { this.setAuthStatus('unauthenticated', null); - throw new Error('Invalid username or password. Please check your credentials and try again.'); + throw new Error('Invalid username or password. Please check your credentials and try again.', { + cause: error, + }); } // Server not found or unreachable else if (errMsg.includes('connection refused') || errMsg.includes('econnrefused')) { this.setAuthStatus('unauthenticated', null); - throw new Error('Cannot connect to server. Please check the server URL and ensure the server is running.'); + throw new Error('Cannot connect to server. Please check the server URL and ensure the server is running.', { + cause: error, + }); } // Timeout else if (errMsg.includes('timeout') || errMsg.includes('timed out')) { this.setAuthStatus('unauthenticated', null); - throw new Error('Login request timed out. Please check your network connection and try again.'); + throw new Error('Login request timed out. Please check your network connection and try again.', { + cause: error, + }); } // DNS failure else if (errMsg.includes('getaddrinfo') || errMsg.includes('dns') || errMsg.includes('not found') || errMsg.includes('enotfound')) { this.setAuthStatus('unauthenticated', null); - throw new Error('Cannot resolve server address. Please check the server URL is correct.'); + throw new Error('Cannot resolve server address. Please check the server URL is correct.', { cause: error }); } // SSL/TLS errors else if (errMsg.includes('ssl') || errMsg.includes('tls') || errMsg.includes('certificate') || errMsg.includes('cert')) { this.setAuthStatus('unauthenticated', null); - throw new Error('SSL/TLS certificate error. Server may have an invalid or self-signed certificate.'); + throw new Error('SSL/TLS certificate error. Server may have an invalid or self-signed certificate.', { + cause: error, + }); } // 404 - endpoint not found else if (errMsg.includes('404') || errMsg.includes('not found')) { this.setAuthStatus('unauthenticated', null); - throw new Error('Login endpoint not found. Please ensure you are connecting to a valid Stirling PDF server.'); + throw new Error('Login endpoint not found. Please ensure you are connecting to a valid Stirling PDF server.', { + cause: error, + }); } // 403 - security disabled else if (errMsg.includes('403') || errMsg.includes('forbidden')) { this.setAuthStatus('unauthenticated', null); - throw new Error('Login is not enabled on this server. Please enable security mode (DOCKER_ENABLE_SECURITY=true).'); + throw new Error('Login is not enabled on this server. Please enable security mode (DOCKER_ENABLE_SECURITY=true).', { + cause: error, + }); } }