Switch to use ESLint 10 (#5794)

This commit is contained in:
James Brunton
2026-02-25 14:30:40 +00:00
committed by GitHub
parent 5c39acecd8
commit c9dafc85fd
20 changed files with 173 additions and 317 deletions
+80 -241
View File
@@ -77,7 +77,7 @@
"web-vitals": "^5.1.0" "web-vitals": "^5.1.0"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.36.0", "@eslint/js": "^10.0.1",
"@iconify-json/material-symbols": "^1.2.53", "@iconify-json/material-symbols": "^1.2.53",
"@iconify/utils": "^3.1.0", "@iconify/utils": "^3.1.0",
"@playwright/test": "^1.55.0", "@playwright/test": "^1.55.0",
@@ -98,8 +98,7 @@
"@vitejs/plugin-react-swc": "^4.1.0", "@vitejs/plugin-react-swc": "^4.1.0",
"@vitest/coverage-v8": "^3.2.4", "@vitest/coverage-v8": "^3.2.4",
"dpdm": "^3.14.0", "dpdm": "^3.14.0",
"eslint": "^9.36.0", "eslint": "^10.0.2",
"eslint-plugin-react-hooks": "^5.2.0",
"jsdom": "^27.0.0", "jsdom": "^27.0.0",
"license-checker": "^25.0.1", "license-checker": "^25.0.1",
"madge": "^8.0.0", "madge": "^8.0.0",
@@ -1682,190 +1681,89 @@
} }
}, },
"node_modules/@eslint/config-array": { "node_modules/@eslint/config-array": {
"version": "0.21.1", "version": "0.23.2",
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.2.tgz",
"integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", "integrity": "sha512-YF+fE6LV4v5MGWRGj7G404/OZzGNepVF8fxk7jqmqo3lrza7a0uUcDnROGRBG1WFC1omYUS/Wp1f42i0M+3Q3A==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@eslint/object-schema": "^2.1.7", "@eslint/object-schema": "^3.0.2",
"debug": "^4.3.1", "debug": "^4.3.1",
"minimatch": "^3.1.2" "minimatch": "^10.2.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^20.19.0 || ^22.13.0 || >=24"
}
},
"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_modules/@eslint/config-helpers": { "node_modules/@eslint/config-helpers": {
"version": "0.4.2", "version": "0.5.2",
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.2.tgz",
"integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", "integrity": "sha512-a5MxrdDXEvqnIq+LisyCX6tQMPF/dSJpCfBgBauY+pNZ28yCtSsTvyTYrMhaI+LK26bVyCJfJkT0u8KIj2i1dQ==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@eslint/core": "^0.17.0" "@eslint/core": "^1.1.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^20.19.0 || ^22.13.0 || >=24"
} }
}, },
"node_modules/@eslint/core": { "node_modules/@eslint/core": {
"version": "0.17.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.1.0.tgz",
"integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", "integrity": "sha512-/nr9K9wkr3P1EzFTdFdMoLuo1PmIxjmwvPozwoSodjNBdefGujXQUF93u1DDZpEaTuDvMsIQddsd35BwtrW9Xw==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@types/json-schema": "^7.0.15" "@types/json-schema": "^7.0.15"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^20.19.0 || ^22.13.0 || >=24"
}
},
"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_modules/@eslint/js": { "node_modules/@eslint/js": {
"version": "9.39.3", "version": "10.0.1",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.3.tgz", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz",
"integrity": "sha512-1B1VkCq6FuUNlQvlBYb+1jDu/gV297TIs/OeiaSR9l1H27SVW55ONE1e1Vp16NqP683+xEGzxYtv4XCiDPaQiw==", "integrity": "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^20.19.0 || ^22.13.0 || >=24"
}, },
"funding": { "funding": {
"url": "https://eslint.org/donate" "url": "https://eslint.org/donate"
},
"peerDependencies": {
"eslint": "^10.0.0"
},
"peerDependenciesMeta": {
"eslint": {
"optional": true
}
} }
}, },
"node_modules/@eslint/object-schema": { "node_modules/@eslint/object-schema": {
"version": "2.1.7", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.2.tgz",
"integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", "integrity": "sha512-HOy56KJt48Bx8KmJ+XGQNSUMT/6dZee/M54XyUyuvTvPXJmsERRvBchsUVx1UMe1WwIH49XLAczNC7V2INsuUw==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^20.19.0 || ^22.13.0 || >=24"
} }
}, },
"node_modules/@eslint/plugin-kit": { "node_modules/@eslint/plugin-kit": {
"version": "0.4.1", "version": "0.6.0",
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.6.0.tgz",
"integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", "integrity": "sha512-bIZEUzOI1jkhviX2cp5vNyXQc6olzb2ohewQubuYlMXZ2Q/XjBO0x0XhGPvc9fjSIiUN0vw+0hq53BJ4eQSJKQ==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@eslint/core": "^0.17.0", "@eslint/core": "^1.1.0",
"levn": "^0.4.1" "levn": "^0.4.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^20.19.0 || ^22.13.0 || >=24"
} }
}, },
"node_modules/@exodus/bytes": { "node_modules/@exodus/bytes": {
@@ -4732,6 +4630,13 @@
"dev": true, "dev": true,
"license": "MIT" "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": { "node_modules/@types/estree": {
"version": "1.0.8", "version": "1.0.8",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
@@ -7246,33 +7151,30 @@
} }
}, },
"node_modules/eslint": { "node_modules/eslint": {
"version": "9.39.3", "version": "10.0.2",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.3.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.0.2.tgz",
"integrity": "sha512-VmQ+sifHUbI/IcSopBCF/HO3YiHQx/AVd3UVyYL6weuwW+HvON9VYn5l6Zl1WZzPWXPNZrSQpxwkkZ/VuvJZzg==", "integrity": "sha512-uYixubwmqJZH+KLVYIVKY1JQt7tysXhtj21WSvjcSmU5SVNzMus1bgLe+pAt816yQ8opKfheVVoPLqvVMGejYw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1", "@eslint-community/regexpp": "^4.12.2",
"@eslint/config-array": "^0.21.1", "@eslint/config-array": "^0.23.2",
"@eslint/config-helpers": "^0.4.2", "@eslint/config-helpers": "^0.5.2",
"@eslint/core": "^0.17.0", "@eslint/core": "^1.1.0",
"@eslint/eslintrc": "^3.3.1", "@eslint/plugin-kit": "^0.6.0",
"@eslint/js": "9.39.3",
"@eslint/plugin-kit": "^0.4.1",
"@humanfs/node": "^0.16.6", "@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/module-importer": "^1.0.1",
"@humanwhocodes/retry": "^0.4.2", "@humanwhocodes/retry": "^0.4.2",
"@types/estree": "^1.0.6", "@types/estree": "^1.0.6",
"ajv": "^6.12.4", "ajv": "^6.14.0",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.6", "cross-spawn": "^7.0.6",
"debug": "^4.3.2", "debug": "^4.3.2",
"escape-string-regexp": "^4.0.0", "escape-string-regexp": "^4.0.0",
"eslint-scope": "^8.4.0", "eslint-scope": "^9.1.1",
"eslint-visitor-keys": "^4.2.1", "eslint-visitor-keys": "^5.0.1",
"espree": "^10.4.0", "espree": "^11.1.1",
"esquery": "^1.5.0", "esquery": "^1.7.0",
"esutils": "^2.0.2", "esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3", "fast-deep-equal": "^3.1.3",
"file-entry-cache": "^8.0.0", "file-entry-cache": "^8.0.0",
@@ -7282,8 +7184,7 @@
"imurmurhash": "^0.1.4", "imurmurhash": "^0.1.4",
"is-glob": "^4.0.0", "is-glob": "^4.0.0",
"json-stable-stringify-without-jsonify": "^1.0.1", "json-stable-stringify-without-jsonify": "^1.0.1",
"lodash.merge": "^4.6.2", "minimatch": "^10.2.1",
"minimatch": "^3.1.2",
"natural-compare": "^1.4.0", "natural-compare": "^1.4.0",
"optionator": "^0.9.3" "optionator": "^0.9.3"
}, },
@@ -7291,7 +7192,7 @@
"eslint": "bin/eslint.js" "eslint": "bin/eslint.js"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^20.19.0 || ^22.13.0 || >=24"
}, },
"funding": { "funding": {
"url": "https://eslint.org/donate" "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": { "node_modules/eslint-scope": {
"version": "8.4.0", "version": "9.1.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.1.tgz",
"integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "integrity": "sha512-GaUN0sWim5qc8KVErfPBWmc31LEsOkrUJbvJZV+xuL3u2phMUK4HIvXlWAakfC8W4nzlK+chPEAkYOYb5ZScIw==",
"dev": true, "dev": true,
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"dependencies": { "dependencies": {
"@types/esrecurse": "^4.3.1",
"@types/estree": "^1.0.8",
"esrecurse": "^4.3.0", "esrecurse": "^4.3.0",
"estraverse": "^5.2.0" "estraverse": "^5.2.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^20.19.0 || ^22.13.0 || >=24"
}, },
"funding": { "funding": {
"url": "https://opencollective.com/eslint" "url": "https://opencollective.com/eslint"
@@ -7348,32 +7238,14 @@
"url": "https://opencollective.com/eslint" "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": { "node_modules/eslint/node_modules/eslint-visitor-keys": {
"version": "4.2.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
"integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^20.19.0 || ^22.13.0 || >=24"
}, },
"funding": { "funding": {
"url": "https://opencollective.com/eslint" "url": "https://opencollective.com/eslint"
@@ -7389,19 +7261,6 @@
"node": ">= 4" "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": { "node_modules/esm-env": {
"version": "1.2.2", "version": "1.2.2",
"resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz", "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz",
@@ -7410,31 +7269,31 @@
"peer": true "peer": true
}, },
"node_modules/espree": { "node_modules/espree": {
"version": "10.4.0", "version": "11.1.1",
"resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", "resolved": "https://registry.npmjs.org/espree/-/espree-11.1.1.tgz",
"integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "integrity": "sha512-AVHPqQoZYc+RUM4/3Ly5udlZY/U4LS8pIG05jEjWM2lQMU/oaZ7qshzAl2YP1tfNmXfftH3ohurfwNAug+MnsQ==",
"dev": true, "dev": true,
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"dependencies": { "dependencies": {
"acorn": "^8.15.0", "acorn": "^8.16.0",
"acorn-jsx": "^5.3.2", "acorn-jsx": "^5.3.2",
"eslint-visitor-keys": "^4.2.1" "eslint-visitor-keys": "^5.0.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^20.19.0 || ^22.13.0 || >=24"
}, },
"funding": { "funding": {
"url": "https://opencollective.com/eslint" "url": "https://opencollective.com/eslint"
} }
}, },
"node_modules/espree/node_modules/eslint-visitor-keys": { "node_modules/espree/node_modules/eslint-visitor-keys": {
"version": "4.2.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
"integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^20.19.0 || ^22.13.0 || >=24"
}, },
"funding": { "funding": {
"url": "https://opencollective.com/eslint" "url": "https://opencollective.com/eslint"
@@ -9367,13 +9226,6 @@
"url": "https://github.com/sponsors/sindresorhus" "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": { "node_modules/log-symbols": {
"version": "4.1.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
@@ -12030,19 +11882,6 @@
"node": ">=8" "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": { "node_modules/strip-literal": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.1.0.tgz", "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.1.0.tgz",
+2 -10
View File
@@ -111,13 +111,6 @@
"update:interactive": "npx npm-check-updates -i", "update:interactive": "npx npm-check-updates -i",
"update:minor-strict": "npx npm-check-updates -u --target minor && npm install" "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": { "browserslist": {
"production": [ "production": [
">0.2%", ">0.2%",
@@ -131,7 +124,7 @@
] ]
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.36.0", "@eslint/js": "^10.0.1",
"@iconify-json/material-symbols": "^1.2.53", "@iconify-json/material-symbols": "^1.2.53",
"@iconify/utils": "^3.1.0", "@iconify/utils": "^3.1.0",
"@playwright/test": "^1.55.0", "@playwright/test": "^1.55.0",
@@ -152,8 +145,7 @@
"@vitejs/plugin-react-swc": "^4.1.0", "@vitejs/plugin-react-swc": "^4.1.0",
"@vitest/coverage-v8": "^3.2.4", "@vitest/coverage-v8": "^3.2.4",
"dpdm": "^3.14.0", "dpdm": "^3.14.0",
"eslint": "^9.36.0", "eslint": "^10.0.2",
"eslint-plugin-react-hooks": "^5.2.0",
"jsdom": "^27.0.0", "jsdom": "^27.0.0",
"license-checker": "^25.0.1", "license-checker": "^25.0.1",
"madge": "^8.0.0", "madge": "^8.0.0",
@@ -217,7 +217,7 @@ export function usePageDocument(): PageDocumentHook {
}); });
// Build pages by interleaving original pages with insertions // 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) // Helper function to create pages from a file (or placeholder if deselected)
const createPagesFromFile = (fileId: FileId, startPageNumber: number, isSelected: boolean): PDFPage[] => { const createPagesFromFile = (fileId: FileId, startPageNumber: number, isSelected: boolean): PDFPage[] => {
@@ -242,11 +242,10 @@ export function usePageDocument(): PageDocumentHook {
} }
const processedFile = stirlingFileStub.processedFile; const processedFile = stirlingFileStub.processedFile;
let filePages: PDFPage[] = [];
if (processedFile?.pages && processedFile.pages.length > 0) { if (processedFile?.pages && processedFile.pages.length > 0) {
// Use fully processed pages with thumbnails // Use fully processed pages with thumbnails
filePages = processedFile.pages.map((page, pageIndex) => ({ return processedFile.pages.map((page, pageIndex) => ({
id: `${fileId}-${pageIndex + 1}`, id: `${fileId}-${pageIndex + 1}`,
pageNumber: startPageNumber + pageIndex, pageNumber: startPageNumber + pageIndex,
thumbnail: page.thumbnail || null, thumbnail: page.thumbnail || null,
@@ -259,9 +258,11 @@ export function usePageDocument(): PageDocumentHook {
originalFileId: fileId, originalFileId: fileId,
isPlaceholder: false, isPlaceholder: false,
})); }));
} else if (processedFile?.totalPages) { }
if (processedFile?.totalPages) {
// Fallback: create pages without thumbnails but with correct count // 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}`, id: `${fileId}-${pageIndex + 1}`,
pageNumber: startPageNumber + pageIndex, pageNumber: startPageNumber + pageIndex,
originalPageNumber: pageIndex + 1, originalPageNumber: pageIndex + 1,
@@ -272,23 +273,21 @@ export function usePageDocument(): PageDocumentHook {
splitAfter: false, splitAfter: false,
isPlaceholder: 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 // Collect all pages from original files, respecting their previous positions
@@ -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 // Load icons synchronously at import time - guaranteed to be ready on first render
let iconsLoaded = false; let iconsLoaded = false;
let localIconCount = 0;
try { try {
if (iconSet) { if (iconSet) {
addCollection(iconSet); addCollection(iconSet);
iconsLoaded = true; 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)`); console.info(`✅ Local icons loaded: ${localIconCount} icons (${Math.round(JSON.stringify(iconSet).length / 1024)}KB)`);
} }
} catch { } catch {
@@ -110,7 +110,7 @@ export function computeStampPreviewStyle(
// Convert measured px width back to PDF points using horizontal scale // Convert measured px width back to PDF points using horizontal scale
widthPtsContent = measuredWidthPx / scaleX; widthPtsContent = measuredWidthPx / scaleX;
let adjustmentFactor = 1.0; let adjustmentFactor: number;
switch (parameters.alphabet) { switch (parameters.alphabet) {
case 'roman': case 'roman':
adjustmentFactor = 0.90; adjustmentFactor = 0.90;
@@ -126,6 +126,7 @@ export function computeStampPreviewStyle(
break; break;
default: default:
adjustmentFactor = 0.93; adjustmentFactor = 0.93;
break;
} }
widthPtsContent *= adjustmentFactor; widthPtsContent *= adjustmentFactor;
} }
@@ -22,7 +22,7 @@ const CompactToolItem: React.FC<CompactToolItemProps> = ({ id, tool, isSelected,
const iconBg = getIconBackground(categoryColor, false); const iconBg = getIconBackground(categoryColor, false);
const iconClasses = 'tool-panel__fullscreen-list-icon'; const iconClasses = 'tool-panel__fullscreen-list-icon';
let iconNode: React.ReactNode = null; let iconNode: React.ReactNode;
if (React.isValidElement<{ style?: React.CSSProperties }>(tool.icon)) { if (React.isValidElement<{ style?: React.CSSProperties }>(tool.icon)) {
const element = tool.icon as React.ReactElement<{ style?: React.CSSProperties }>; const element = tool.icon as React.ReactElement<{ style?: React.CSSProperties }>;
iconNode = React.cloneElement(element, { iconNode = React.cloneElement(element, {
@@ -120,4 +120,3 @@ const CompactToolItem: React.FC<CompactToolItemProps> = ({ id, tool, isSelected,
export default CompactToolItem; export default CompactToolItem;
@@ -21,7 +21,7 @@ const DetailedToolItem: React.FC<DetailedToolItemProps> = ({ id, tool, isSelecte
const iconBg = getIconBackground(categoryColor, true); const iconBg = getIconBackground(categoryColor, true);
const iconClasses = 'tool-panel__fullscreen-icon'; const iconClasses = 'tool-panel__fullscreen-icon';
let iconNode: React.ReactNode = null; let iconNode: React.ReactNode;
if (React.isValidElement<{ style?: React.CSSProperties }>(tool.icon)) { if (React.isValidElement<{ style?: React.CSSProperties }>(tool.icon)) {
const element = tool.icon as React.ReactElement<{ style?: React.CSSProperties }>; const element = tool.icon as React.ReactElement<{ style?: React.CSSProperties }>;
iconNode = React.cloneElement(element, { iconNode = React.cloneElement(element, {
@@ -70,7 +70,7 @@ const DetailedToolItem: React.FC<DetailedToolItemProps> = ({ id, tool, isSelecte
color="orange" color="orange"
> >
{/* we can add more translations for different badges in future, like beta, etc. */} {/* we can add more translations for different badges in future, like beta, etc. */}
{t('toolPanel.alpha', 'Alpha')} {t('toolPanel.alpha', 'Alpha')}
</Badge> </Badge>
)} )}
</div> </div>
@@ -106,4 +106,3 @@ const DetailedToolItem: React.FC<DetailedToolItemProps> = ({ id, tool, isSelecte
export default DetailedToolItem; export default DetailedToolItem;
@@ -133,7 +133,7 @@ const validateParameters = (params: ConvertParameters): boolean => {
if (!fromExtension || !toExtension) return false; if (!fromExtension || !toExtension) return false;
// Handle dynamic format identifiers (file-<extension>) // Handle dynamic format identifiers (file-<extension>)
let supportedToExtensions: string[] = []; let supportedToExtensions: string[];
if (fromExtension.startsWith('file-')) { if (fromExtension.startsWith('file-')) {
// Dynamic format - use 'any' conversion options // Dynamic format - use 'any' conversion options
supportedToExtensions = CONVERSION_MATRIX['any'] || []; supportedToExtensions = CONVERSION_MATRIX['any'] || [];
@@ -71,7 +71,10 @@ const removeAnnotationsProcessor = async (_parameters: RemoveAnnotationsParamete
processedFiles.push(processedFile); processedFiles.push(processedFile);
} catch (error) { } catch (error) {
console.error('Error processing file:', file.name, 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, ...removeAnnotationsOperationConfig,
getErrorMessage: createStandardErrorHandler(t('removeAnnotations.error.failed', 'An error occurred while removing annotations from the PDF.')) getErrorMessage: createStandardErrorHandler(t('removeAnnotations.error.failed', 'An error occurred while removing annotations from the PDF.'))
}); });
}; };
@@ -77,7 +77,7 @@ export const useToolApiCalls = <TParams = void>() => {
} catch (error) { } catch (error) {
if (axios.isCancel(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 }); console.error('[processFiles] Failed', { name: file.name, error });
failedFiles.push(file.name); failedFiles.push(file.name);
@@ -71,7 +71,7 @@ export const createReportPdf = async (
cursorY -= 16; cursorY -= 16;
if (entry.error) { if (entry.error) {
cursorY = drawCenteredMessage({ drawCenteredMessage({
page, page,
font, font,
fontBold, fontBold,
@@ -86,7 +86,7 @@ export const createReportPdf = async (
} }
if (entry.signatures.length === 0) { if (entry.signatures.length === 0) {
cursorY = drawCenteredMessage({ drawCenteredMessage({
page, page,
font, font,
fontBold, fontBold,
+3 -5
View File
@@ -71,8 +71,7 @@ export const useCookieConsent = ({
const hasDarkClass = document.documentElement.classList.contains('dark'); const hasDarkClass = document.documentElement.classList.contains('dark');
const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
let isDarkMode = false; let isDarkMode: boolean;
if (mantineScheme) { if (mantineScheme) {
isDarkMode = mantineScheme === 'dark'; isDarkMode = mantineScheme === 'dark';
} else if (hasLightClass) { } else if (hasLightClass) {
@@ -94,9 +93,8 @@ export const useCookieConsent = ({
return; return;
} }
let themeObserver: MutationObserver | null = null;
if (!forceLightMode) { if (!forceLightMode) {
themeObserver = new MutationObserver((mutations) => { const themeObserver = new MutationObserver((mutations) => {
mutations.forEach((mutation) => { mutations.forEach((mutation) => {
if (mutation.type === 'attributes' && if (mutation.type === 'attributes' &&
(mutation.attributeName === 'data-mantine-color-scheme' || (mutation.attributeName === 'data-mantine-color-scheme' ||
@@ -241,7 +239,7 @@ export const useCookieConsent = ({
const hasDarkClass = document.documentElement.classList.contains('dark'); const hasDarkClass = document.documentElement.classList.contains('dark');
const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
let isDarkMode = false; let isDarkMode: boolean;
if (mantineScheme) { if (mantineScheme) {
isDarkMode = mantineScheme === 'dark'; isDarkMode = mantineScheme === 'dark';
} else if (hasLightClass) { } else if (hasLightClass) {
+2 -2
View File
@@ -335,10 +335,10 @@ class FileStorageService {
* Get storage statistics * Get storage statistics
*/ */
async getStorageStats(): Promise<StorageStats> { async getStorageStats(): Promise<StorageStats> {
let used = 0; let used: number;
let fileCount: number;
let available = 0; let available = 0;
let quota: number | undefined; let quota: number | undefined;
let fileCount = 0;
try { try {
// Get browser quota for context // Get browser quota for context
@@ -37,7 +37,10 @@ export class PDFExportService {
return { blob, filename: exportFilename }; return { blob, filename: exportFilename };
} catch (error) { } catch (error) {
console.error('PDF export error:', 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 }; return { blob, filename: exportFilename };
} catch (error) { } catch (error) {
console.error('Multi-file PDF export error:', 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 }
);
} }
} }
+4 -1
View File
@@ -162,7 +162,10 @@ export class ZipFileService {
return { zipFile, size: zipFile.size }; return { zipFile, size: zipFile.size };
} catch (error) { } 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 }
);
} }
} }
@@ -687,7 +687,7 @@ const PdfTextEditor = ({ onComplete, onError }: BaseToolProps) => {
message: pollError?.message, message: pollError?.message,
}); });
if (pollError?.response?.status === 404) { 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; return;
} catch (incrementalError) { } catch (incrementalError) {
if (isLazyMode && cachedJobIdRef.current) { 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( console.warn(
'[handleGeneratePdf] Incremental export failed, falling back to full export', '[handleGeneratePdf] Incremental export failed, falling back to full export',
@@ -1340,7 +1342,9 @@ const PdfTextEditor = ({ onComplete, onError }: BaseToolProps) => {
pdfBlob = response.data; pdfBlob = response.data;
} catch (incrementalError) { } catch (incrementalError) {
if (isLazyMode && cachedJobId) { 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( console.warn(
'[handleSaveToWorkbench] Incremental export failed, falling back to full export', '[handleSaveToWorkbench] Incremental export failed, falling back to full export',
@@ -1354,7 +1358,7 @@ const PdfTextEditor = ({ onComplete, onError }: BaseToolProps) => {
const payload = buildPayload(); const payload = buildPayload();
if (!payload) { if (!payload) {
throw new Error('Failed to build payload'); throw new Error('Failed to build payload', { cause: incrementalError });
} }
const { document, filename } = payload; const { document, filename } = payload;
@@ -174,7 +174,9 @@ export const executeToolOperationWithPrefix = async (
} catch (error: any) { } catch (error: any) {
console.error(`${operationName} failed:`, error); 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,
});
} }
}; };
+2 -1
View File
@@ -139,7 +139,8 @@ export async function convertImageToPdf(
} catch (error) { } catch (error) {
console.error('Error converting image to PDF:', error); console.error('Error converting image to PDF:', error);
throw new 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 }
); );
} }
} }
+5 -6
View File
@@ -167,10 +167,10 @@ const chunkedDiff = (
const remaining2 = Math.max(0, words2.length - index2); const remaining2 = Math.max(0, words2.length - index2);
let windowSize = Math.max(dynamicChunkSize, buffer1.length, buffer2.length); let windowSize = Math.max(dynamicChunkSize, buffer1.length, buffer2.length);
let window1: string[] = []; let window1: string[];
let window2: string[] = []; let window2: string[];
let chunkTokens: CompareDiffToken[] = []; let chunkTokens: CompareDiffToken[];
let reachedEnd = false; let reachedEnd: boolean;
while (true) { while (true) {
const take1 = Math.min(Math.max(0, windowSize - buffer1.length), remaining1); const take1 = Math.min(Math.max(0, windowSize - buffer1.length), remaining1);
@@ -220,7 +220,6 @@ const chunkedDiff = (
flushRemainder(); flushRemainder();
return; return;
} }
windowSize = Math.min(windowSize + dynamicStep, dynamicMaxWindow);
stallIterations += 1; stallIterations += 1;
if (stallIterations >= 3) { if (stallIterations >= 3) {
increaseChunkSizes(); increaseChunkSizes();
@@ -422,7 +421,7 @@ self.onmessage = (event: MessageEvent<CompareWorkerRequest>) => {
}, },
{ maxProcessedTokens: runtimeMaxProcessedTokens, minUnchangedRatio: runtimeMinUnchangedRatio } { maxProcessedTokens: runtimeMaxProcessedTokens, minUnchangedRatio: runtimeMinUnchangedRatio }
); );
} catch (err) { } catch (err) {
const error = err as Error & { __earlyStop?: boolean }; const error = err as Error & { __earlyStop?: boolean };
if (error && (error.__earlyStop || error.message === 'EARLY_STOP_TOO_DISSIMILAR')) { if (error && (error.__earlyStop || error.message === 'EARLY_STOP_TOO_DISSIMILAR')) {
const response: CompareWorkerResponse = { const response: CompareWorkerResponse = {
+22 -10
View File
@@ -247,9 +247,9 @@ export class AuthService {
error.response?.data?.msg || error.response?.data?.msg ||
error.response?.data?.message || error.response?.data?.message ||
error.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); await this.saveTokenEverywhere(token);
} catch (error) { } catch (error) {
console.error('[Desktop AuthService] Failed to save token:', 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 // Save user info to store
@@ -320,37 +320,49 @@ export class AuthService {
// Authentication errors // Authentication errors
if (errMsg.includes('401') || errMsg.includes('unauthorized') || errMsg.includes('invalid credentials')) { if (errMsg.includes('401') || errMsg.includes('unauthorized') || errMsg.includes('invalid credentials')) {
this.setAuthStatus('unauthenticated', null); 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 // Server not found or unreachable
else if (errMsg.includes('connection refused') || errMsg.includes('econnrefused')) { else if (errMsg.includes('connection refused') || errMsg.includes('econnrefused')) {
this.setAuthStatus('unauthenticated', null); 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 // Timeout
else if (errMsg.includes('timeout') || errMsg.includes('timed out')) { else if (errMsg.includes('timeout') || errMsg.includes('timed out')) {
this.setAuthStatus('unauthenticated', null); 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 // DNS failure
else if (errMsg.includes('getaddrinfo') || errMsg.includes('dns') || errMsg.includes('not found') || errMsg.includes('enotfound')) { else if (errMsg.includes('getaddrinfo') || errMsg.includes('dns') || errMsg.includes('not found') || errMsg.includes('enotfound')) {
this.setAuthStatus('unauthenticated', null); 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 // SSL/TLS errors
else if (errMsg.includes('ssl') || errMsg.includes('tls') || errMsg.includes('certificate') || errMsg.includes('cert')) { else if (errMsg.includes('ssl') || errMsg.includes('tls') || errMsg.includes('certificate') || errMsg.includes('cert')) {
this.setAuthStatus('unauthenticated', null); 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 // 404 - endpoint not found
else if (errMsg.includes('404') || errMsg.includes('not found')) { else if (errMsg.includes('404') || errMsg.includes('not found')) {
this.setAuthStatus('unauthenticated', null); 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 // 403 - security disabled
else if (errMsg.includes('403') || errMsg.includes('forbidden')) { else if (errMsg.includes('403') || errMsg.includes('forbidden')) {
this.setAuthStatus('unauthenticated', null); 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,
});
} }
} }