From be94f1d2b79c4f388520312e520ae090d6a5284d Mon Sep 17 00:00:00 2001 From: IRHM Date: Sun, 26 Jul 2026 20:11:14 +0100 Subject: [PATCH] Replace axios with native Fetch API & some maintenance --- .npmrc | 2 + CHANGELOG.md | 14 + package-lock.json | 234 ++++--------- package.json | 41 ++- src/lib/JobWatcherModal.svelte | 49 +-- src/lib/RegionDropDown.svelte | 6 +- src/lib/content/FollowedThoughts.svelte | 10 +- src/lib/logout/ProxyUserLogoutModal.svelte | 6 +- src/lib/request/ArrRequestButton.svelte | 32 +- src/lib/request/RequestMovie.svelte | 18 +- src/lib/request/RequestShow.svelte | 18 +- src/lib/season/SeasonsList.svelte | 17 +- src/lib/season/api.ts | 35 +- src/lib/tag/CreateTagModal.svelte | 16 +- src/lib/tag/DeleteTagModal.svelte | 35 +- src/lib/tag/api.ts | 10 +- src/lib/util/api.ts | 95 +++-- src/lib/util/fetch.ts | 330 ++++++++++++++++++ src/lib/util/paginatedLoader.svelte.ts | 15 +- src/lib/util/plex.ts | 27 +- src/routes/(app)/+layout.svelte | 58 +-- src/routes/(app)/+layout.ts | 44 --- src/routes/(app)/+page.svelte | 8 +- src/routes/(app)/arr_requests/+page.svelte | 20 +- src/routes/(app)/discover/+page.svelte | 7 +- src/routes/(app)/game/[id]/+page.svelte | 6 +- src/routes/(app)/import/process/+page.svelte | 16 +- src/routes/(app)/import/trakt/+page.svelte | 10 +- .../(app)/lists/[id]/[username]/+page.svelte | 25 +- src/routes/(app)/manage_users/+page.svelte | 4 +- .../manage_users/modals/EditUserModal.svelte | 22 +- src/routes/(app)/movie/[id]/+page.svelte | 20 +- src/routes/(app)/person/[id]/+page.svelte | 13 +- src/routes/(app)/profile/+page.svelte | 28 +- .../profile/modals/ExportListModal.svelte | 10 +- .../(app)/profile/modals/SyncModal.svelte | 48 +-- src/routes/(app)/request_admin/+page.svelte | 11 +- src/routes/(app)/search/+page.svelte | 21 +- src/routes/(app)/server/+page.svelte | 13 +- .../(app)/server/modals/RadarrModal.svelte | 55 ++- .../(app)/server/modals/SonarrModal.svelte | 55 ++- .../server/modals/TaskScheduleModal.svelte | 10 +- .../modals/TrustedHeaderAuthModal.svelte | 8 +- .../(app)/server/modals/TwitchModal.svelte | 22 +- src/routes/(app)/tag/[id]/+page.svelte | 17 +- src/routes/(app)/tv/[id]/+page.svelte | 16 +- src/routes/(plain)/login/+page.svelte | 102 +++--- src/routes/(plain)/setup/+page.svelte | 30 +- src/store.svelte.ts | 2 +- 49 files changed, 894 insertions(+), 817 deletions(-) create mode 100644 src/lib/util/fetch.ts diff --git a/.npmrc b/.npmrc index b6f27f13..1b091a4d 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +1,3 @@ engine-strict=true +ignore-scripts=true +min-release-age=14 diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bab49d9..0ac01ad5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,20 @@ These changes are awaiting release: +## Changed + +- HTTP Requests: Replace `axios` with `Fetch`. + +## Fixed + +- Login: Display error when request to get available auth providers fails. +- Removed some legacy code that still thought there was a `store.watchedList`. + +## Maintenance + +- Package.json: Use exact version for all packages. +- .npmrc: Enable `ignore-scripts` (still on npm 11) and set `min-release-age=14`. + # [4.1.1] - 2026-07-26T02:00:00Z ## Fixed diff --git a/package-lock.json b/package-lock.json index fa59b7ed..11e9f024 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,29 +9,28 @@ "version": "4.1.1", "license": "GPL-3.0-only", "dependencies": { - "axios": "^1.9.0", - "blurhash": "^2.0.5", - "papaparse": "^5.4.1" + "blurhash": "2.0.5", + "papaparse": "5.4.1" }, "devDependencies": { - "@sveltejs/adapter-node": "^5.2.12", - "@sveltejs/kit": "^2.21.0", - "@types/papaparse": "^5.3.15", - "@typescript-eslint/eslint-plugin": "^8.32.1", - "@typescript-eslint/parser": "^8.32.1", - "@vite-pwa/sveltekit": "^0.6.6", - "eslint": "^8.57.0", - "eslint-config-prettier": "^10.1.2", - "eslint-plugin-svelte": "^2.45.1", - "prettier": "^3.4.2", - "prettier-plugin-svelte": "^3.4.0", - "sass": "^1.97.3", - "svelte": "^5.17.3", - "svelte-check": "^4.1.3", - "svelte-eslint-parser": "^0.42.0", - "svelte-preprocess": "^6.0.3", - "typescript": "^5.8.3", - "vite": "^6.3.5" + "@sveltejs/adapter-node": "5.2.12", + "@sveltejs/kit": "2.21.0", + "@types/papaparse": "5.3.15", + "@typescript-eslint/eslint-plugin": "8.32.1", + "@typescript-eslint/parser": "8.32.1", + "@vite-pwa/sveltekit": "0.6.6", + "eslint": "8.57.0", + "eslint-config-prettier": "10.1.2", + "eslint-plugin-svelte": "2.45.1", + "prettier": "3.4.2", + "prettier-plugin-svelte": "3.4.0", + "sass": "1.97.3", + "svelte": "5.17.3", + "svelte-check": "4.1.3", + "svelte-eslint-parser": "0.42.0", + "svelte-preprocess": "6.0.3", + "typescript": "5.8.3", + "vite": "6.3.5" } }, "node_modules/@ampproject/remapping": { @@ -2112,22 +2111,24 @@ } }, "node_modules/@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "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, + "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "deprecated": "Use @eslint/config-array instead", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", + "@humanwhocodes/object-schema": "^2.0.2", "debug": "^4.3.1", "minimatch": "^3.0.5" }, @@ -2136,20 +2137,22 @@ } }, "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.16.tgz", + "integrity": "sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -2175,7 +2178,8 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "deprecated": "Use @eslint/object-schema instead", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.8", @@ -3332,10 +3336,11 @@ "dev": true }, "node_modules/@vite-pwa/sveltekit": { - "version": "0.6.7", - "resolved": "https://registry.npmjs.org/@vite-pwa/sveltekit/-/sveltekit-0.6.7.tgz", - "integrity": "sha512-geeRgOiFr4RdW4JHIshOTsa8OqX4P+aJtudnKjuxzpmHy44bo4o18OWM1iXc4qXBJCxCw+3yTttyJsdmHXG/sA==", + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/@vite-pwa/sveltekit/-/sveltekit-0.6.6.tgz", + "integrity": "sha512-f08xlcfZyaXgytl05hUtCLih7Vr8zOk/E4eE/UK71M+sEGk+y+vUyTuR8td8KQalpf1Begb8XkxAkV7iUj2a0g==", "dev": true, + "license": "MIT", "dependencies": { "kolorist": "^1.8.0", "tinyglobby": "^0.2.9" @@ -3349,7 +3354,7 @@ "peerDependencies": { "@sveltejs/kit": "^1.3.1 || ^2.0.1", "@vite-pwa/assets-generator": "^0.2.6", - "vite-plugin-pwa": ">=0.21.1 <1" + "vite-plugin-pwa": ">=0.20.5 <1" }, "peerDependenciesMeta": { "@vite-pwa/assets-generator": { @@ -3489,11 +3494,6 @@ "dev": true, "peer": true }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, "node_modules/at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", @@ -3520,17 +3520,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/axios": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz", - "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, "node_modules/axobject-query": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", @@ -3802,17 +3791,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -4030,14 +4008,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", @@ -4304,17 +4274,18 @@ } }, "node_modules/eslint": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", - "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -4388,22 +4359,23 @@ } }, "node_modules/eslint-plugin-svelte": { - "version": "2.46.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-2.46.1.tgz", - "integrity": "sha512-7xYr2o4NID/f9OEYMqxsEQsCsj4KaMy4q5sANaKkAb6/QeCjYFxRmDm2S3YC3A3pl1kyPZ/syOx/i7LcWYSbIw==", + "version": "2.45.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-2.45.1.tgz", + "integrity": "sha512-mYAKNDRji0YWl7o00KQi0enREcrtzcN7xwK/8lwk5uLRoKLjzPXc+WjngsYpPV35I3AF7UlXc1+JfyNMJS+njA==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@jridgewell/sourcemap-codec": "^1.4.15", "eslint-compat-utils": "^0.5.1", "esutils": "^2.0.3", - "known-css-properties": "^0.35.0", + "known-css-properties": "^0.34.0", "postcss": "^8.4.38", "postcss-load-config": "^3.1.4", "postcss-safe-parser": "^6.0.0", "postcss-selector-parser": "^6.1.0", "semver": "^7.6.2", - "svelte-eslint-parser": "^0.43.0" + "svelte-eslint-parser": "^0.42.0" }, "engines": { "node": "^14.17.0 || >=16.0.0" @@ -4413,34 +4385,7 @@ }, "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0-0 || ^9.0.0-0", - "svelte": "^3.37.0 || ^4.0.0 || ^5.0.0" - }, - "peerDependenciesMeta": { - "svelte": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-svelte/node_modules/svelte-eslint-parser": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-0.43.0.tgz", - "integrity": "sha512-GpU52uPKKcVnh8tKN5P4UZpJ/fUDndmq7wfsvoVXsyP+aY0anol7Yqo01fyrlaWGMFfm4av5DyrjlaXdLRJvGA==", - "dev": true, - "dependencies": { - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "postcss": "^8.4.39", - "postcss-scss": "^4.0.9" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ota-meshi" - }, - "peerDependencies": { - "svelte": "^3.37.0 || ^4.0.0 || ^5.0.0" + "svelte": "^3.37.0 || ^4.0.0 || ^5.0.0-next.191" }, "peerDependenciesMeta": { "svelte": { @@ -4738,25 +4683,6 @@ "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", "dev": true }, - "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -4767,19 +4693,6 @@ "is-callable": "^1.1.3" } }, - "node_modules/form-data": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", - "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/fs-extra": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", @@ -5809,10 +5722,11 @@ } }, "node_modules/known-css-properties": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.35.0.tgz", - "integrity": "sha512-a/RAk2BfKk+WFGhhOCAYqSiFLc34k8Mt/6NWRI4joER0EYUzXIcFivjjnoD3+XU1DggLn/tZc3DOAgke7l8a4A==", - "dev": true + "version": "0.34.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.34.0.tgz", + "integrity": "sha512-tBECoUqNFbyAY4RrbqsBQqDFpGXAEbdD5QKr8kACx3+rnArmuuR22nKQWKazvp07N9yjTyDZaw/20UIH8tL9DQ==", + "dev": true, + "license": "MIT" }, "node_modules/kolorist": { "version": "1.8.0", @@ -5963,25 +5877,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -6425,11 +6320,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", diff --git a/package.json b/package.json index f0d25c61..2a3dea15 100644 --- a/package.json +++ b/package.json @@ -14,29 +14,28 @@ "format": "prettier --write ." }, "devDependencies": { - "@sveltejs/adapter-node": "^5.2.12", - "@sveltejs/kit": "^2.21.0", - "@types/papaparse": "^5.3.15", - "@typescript-eslint/eslint-plugin": "^8.32.1", - "@typescript-eslint/parser": "^8.32.1", - "@vite-pwa/sveltekit": "^0.6.6", - "eslint": "^8.57.0", - "eslint-config-prettier": "^10.1.2", - "eslint-plugin-svelte": "^2.45.1", - "prettier": "^3.4.2", - "prettier-plugin-svelte": "^3.4.0", - "sass": "^1.97.3", - "svelte": "^5.17.3", - "svelte-check": "^4.1.3", - "svelte-eslint-parser": "^0.42.0", - "svelte-preprocess": "^6.0.3", - "typescript": "^5.8.3", - "vite": "^6.3.5" + "@sveltejs/adapter-node": "5.2.12", + "@sveltejs/kit": "2.21.0", + "@types/papaparse": "5.3.15", + "@typescript-eslint/eslint-plugin": "8.32.1", + "@typescript-eslint/parser": "8.32.1", + "@vite-pwa/sveltekit": "0.6.6", + "eslint": "8.57.0", + "eslint-config-prettier": "10.1.2", + "eslint-plugin-svelte": "2.45.1", + "prettier": "3.4.2", + "prettier-plugin-svelte": "3.4.0", + "sass": "1.97.3", + "svelte": "5.17.3", + "svelte-check": "4.1.3", + "svelte-eslint-parser": "0.42.0", + "svelte-preprocess": "6.0.3", + "typescript": "5.8.3", + "vite": "6.3.5" }, "type": "module", "dependencies": { - "axios": "^1.9.0", - "blurhash": "^2.0.5", - "papaparse": "^5.4.1" + "blurhash": "2.0.5", + "papaparse": "5.4.1" } } diff --git a/src/lib/JobWatcherModal.svelte b/src/lib/JobWatcherModal.svelte index b9d42fa9..43e54627 100644 --- a/src/lib/JobWatcherModal.svelte +++ b/src/lib/JobWatcherModal.svelte @@ -3,14 +3,10 @@ import Modal from "@/lib/Modal.svelte"; import Spinner from "@/lib/Spinner.svelte"; import { notify } from "@/lib/util/notify"; - import { - JobStatus, - type GetJobResponse, - type JobCreatedResponse, - } from "@/types"; - import axios from "axios"; + import { JobStatus, type GetJobResponse } from "@/types"; import { onDestroy, onMount } from "svelte"; - import { store } from "@/store.svelte"; + import { req } from "./util/api"; + import { ReqerError } from "./util/fetch"; interface Props { modalTitle: string; @@ -46,7 +42,7 @@ } catch (err: any) { console.error("startSync failed!", err); step = "errored"; - jobFailError = err?.response ? err?.response?.data?.error : String(err); + jobFailError = ReqerError.getMsg(err, "Starting sync failed"); } } @@ -63,13 +59,13 @@ let seqfailedJobReqs = 0; while (step === "job-running") { try { - const r = await axios.get(`/job/${jobId}`); - console.log("jobWatcher: Got job data:", r.data); - latestJobStatus = r.data; - currentTask = r.data?.currentTask; - if (r.data?.status === JobStatus.DONE) { + const r = await req.get(`/job/${jobId}`); + console.log("jobWatcher: Got job data:", r); + latestJobStatus = r; + currentTask = r?.currentTask; + if (r?.status === JobStatus.DONE) { step = "done"; - } else if (r.data?.status === JobStatus.CANCELLED) { + } else if (r?.status === JobStatus.CANCELLED) { step = "errored"; } // If we get here without erroring, we can reset it to 0. @@ -94,31 +90,6 @@ } await new Promise((r) => setTimeout(r, 1000)); } - if (step !== "modal-closing") { - // Update our watched list - const nid = notify({ - text: "Fetching updated watched list.", - type: "loading", - }); - try { - const w = await axios.get("/watched"); - if (w?.data?.length > 0) { - store.watchedList = w.data; - } - notify({ - id: nid, - text: "Fetched updated watched list.", - type: "success", - }); - } catch (err) { - console.error("jobWatcher: Getting updated watched list failed!", err); - notify({ - id: nid, - text: "Getting updated watched list failed!", - type: "error", - }); - } - } } function modalClose() { diff --git a/src/lib/RegionDropDown.svelte b/src/lib/RegionDropDown.svelte index d790130c..4b04dca1 100644 --- a/src/lib/RegionDropDown.svelte +++ b/src/lib/RegionDropDown.svelte @@ -1,8 +1,8 @@ diff --git a/src/lib/logout/ProxyUserLogoutModal.svelte b/src/lib/logout/ProxyUserLogoutModal.svelte index 027567a1..9a08a12b 100644 --- a/src/lib/logout/ProxyUserLogoutModal.svelte +++ b/src/lib/logout/ProxyUserLogoutModal.svelte @@ -1,11 +1,11 @@ diff --git a/src/routes/(app)/lists/[id]/[username]/+page.svelte b/src/routes/(app)/lists/[id]/[username]/+page.svelte index 3bf84505..ec38464d 100644 --- a/src/routes/(app)/lists/[id]/[username]/+page.svelte +++ b/src/routes/(app)/lists/[id]/[username]/+page.svelte @@ -3,11 +3,10 @@ import Spinner from "@/lib/Spinner.svelte"; import tooltip from "@/lib/actions/tooltip.js"; import UserAvatar from "@/lib/img/UserAvatar.svelte"; - import { followUser, unfollowUser } from "@/lib/util/api.js"; + import { followUser, req, unfollowUser } from "@/lib/util/api.js"; import { clearActiveFilters, store } from "@/store.svelte.js"; - import type { Media, PublicUser } from "@/types.js"; - import axios, { type GenericAbortSignal } from "axios"; - import { onDestroy, onMount, untrack } from "svelte"; + import type { Media, PaginationResponse, PublicUser } from "@/types.js"; + import { onDestroy, untrack } from "svelte"; import paginatedLoader, { PaginatedLoaderRunFnAction, } from "@/lib/util/paginatedLoader.svelte.js"; @@ -43,7 +42,7 @@ ...store.sortAndFiltersForQueryParams, }); - async function load(signal: GenericAbortSignal) { + async function load(signal: AbortSignal) { console.debug("load: loadParams:", nextLoadParams); if (nextLoadParams.page === dataLoader.state.page) { console.warn("load: Already on this page, not loading it again!"); @@ -53,10 +52,13 @@ console.warn("load: Missing id or username!"); return; } - const r = await axios.get(`/watched/${meta.id}/${meta.username}`, { - params: nextLoadParams, - signal, - }); + const r = await req.get>( + `/watched/${meta.id}/${meta.username}`, + { + params: nextLoadParams, + signal, + }, + ); scroll.dataLoaded(); return r; } @@ -87,8 +89,9 @@ }); async function getPublicUser() { - return (await axios.get(`/user/public/${meta.id}/${meta.username}`)) - .data as PublicUser; + return await req.get( + `/user/public/${meta.id}/${meta.username}`, + ); } async function follow() { diff --git a/src/routes/(app)/manage_users/+page.svelte b/src/routes/(app)/manage_users/+page.svelte index e9d5b06c..c8488819 100644 --- a/src/routes/(app)/manage_users/+page.svelte +++ b/src/routes/(app)/manage_users/+page.svelte @@ -7,7 +7,7 @@ userHasPermission, } from "@/lib/util/helpers"; import { UserPermission, type ManagedUser } from "@/types"; - import axios from "axios"; + import { req } from "@/lib/util/api"; import EditUserModal from "./modals/EditUserModal.svelte"; import UserTypeIcon from "@/lib/user/UserTypeIcon.svelte"; import Error from "@/lib/Error.svelte"; @@ -18,7 +18,7 @@ let editingUser: ManagedUser | undefined; async function getUsers() { - allUsers = (await axios.get(`/server/users`)).data as ManagedUser[]; + allUsers = await req.get(`/server/users`); } diff --git a/src/routes/(app)/manage_users/modals/EditUserModal.svelte b/src/routes/(app)/manage_users/modals/EditUserModal.svelte index afa705a1..adac53ca 100644 --- a/src/routes/(app)/manage_users/modals/EditUserModal.svelte +++ b/src/routes/(app)/manage_users/modals/EditUserModal.svelte @@ -4,10 +4,11 @@ import Modal from "@/lib/Modal.svelte"; import Setting from "@/lib/settings/Setting.svelte"; import SettingsList from "@/lib/settings/SettingsList.svelte"; + import { req } from "@/lib/util/api"; + import { ReqerError } from "@/lib/util/fetch"; import { userHasPermission } from "@/lib/util/helpers"; import { notify } from "@/lib/util/notify"; import { UserPermission, UserType, type ManagedUser } from "@/types"; - import axios from "axios"; interface UpdateUserRequest { permissions?: number; @@ -44,20 +45,15 @@ if (changedType) { toUpdate["type"] = user.type; } - const res = await axios.post(`/server/users/${user.id}`, toUpdate); - if (res.status === 200) { - notify({ - type: "success", - text: "Changes saved!", - }); - onClose(); - } + await req.post(`/server/users/${user.id}`, toUpdate); + notify({ + type: "success", + text: "Changes saved!", + }); + onClose(); } catch (err: any) { console.error("Failed to save user!", err); - error = `Failed to save`; - if (err?.response?.data?.error) { - error = err.response.data.error; - } + error = ReqerError.getMsg(err, "Failed to save"); } } } diff --git a/src/routes/(app)/movie/[id]/+page.svelte b/src/routes/(app)/movie/[id]/+page.svelte index cdbc001a..10e349e4 100644 --- a/src/routes/(app)/movie/[id]/+page.svelte +++ b/src/routes/(app)/movie/[id]/+page.svelte @@ -2,11 +2,7 @@ import PersonPoster from "@/lib/poster/PersonPoster.svelte"; import Spinner from "@/lib/Spinner.svelte"; import HorizontalList from "@/lib/HorizontalList.svelte"; - import { - contentExistsOnJellyfin, - removeWatched, - updateWatched, - } from "@/lib/util/api"; + import { contentExistsOnJellyfin, req, updateWatched } from "@/lib/util/api"; import { store } from "@/store.svelte"; import type { Media, @@ -14,7 +10,6 @@ TMDBContentCreditsCrew, WatchedStatus, } from "@/types"; - import axios from "axios"; import { getTopCrew } from "@/lib/util/helpers.js"; import Activity from "@/lib/Activity.svelte"; import Title from "@/lib/content/Title.svelte"; @@ -52,11 +47,9 @@ if (!data.movieId) { return; } - const resp = ( - await axios.get(`/content/movie/${data.movieId}`, { - params: { region: store.userSettings?.country }, - }) - ).data as Media; + const resp = await req.get(`/content/movie/${data.movieId}`, { + params: { region: store.userSettings?.country }, + }); if (resp) { if (resp.name && resp.ids.tmdb) { contentExistsOnJellyfin("movie", resp.name, resp.ids.tmdb).then( @@ -79,8 +72,9 @@ }); async function getMovieCredits() { - const credits = (await axios.get(`/content/movie/${data.movieId}/credits`)) - .data as TMDBContentCredits & { topCrew: TMDBContentCreditsCrew[] }; + const credits = await req.get< + TMDBContentCredits & { topCrew: TMDBContentCreditsCrew[] } + >(`/content/movie/${data.movieId}/credits`); if (credits.crew?.length > 0) { credits.topCrew = getTopCrew(credits.crew); } diff --git a/src/routes/(app)/person/[id]/+page.svelte b/src/routes/(app)/person/[id]/+page.svelte index 45f91dcb..57619769 100644 --- a/src/routes/(app)/person/[id]/+page.svelte +++ b/src/routes/(app)/person/[id]/+page.svelte @@ -9,7 +9,7 @@ PersonCreditsResponse, PersonDetailsResponse, } from "@/types"; - import axios from "axios"; + import { req } from "@/lib/util/api.js"; import Checkbox from "@/lib/Checkbox.svelte"; import Icon from "@/lib/Icon.svelte"; import PageBackdrop from "@/lib/generic/PageBackdrop.svelte"; @@ -53,16 +53,13 @@ } async function getPerson(id: number) { - return (await axios.get(`/content/person/${id}`)) - .data; + return await req.get(`/content/person/${id}`); } async function updatePersonCredits() { - credits = ( - await axios.get( - `/content/person/${data.personId}/credits`, - ) - ).data; + credits = await req.get( + `/content/person/${data.personId}/credits`, + ); credits.credits = credits.credits?.filter( (v, i, a) => a.findIndex((t) => t.ids.tmdb === v.ids.tmdb) === i, ); // remove duplicate entries. If an actor has multiple roles in a single movie, it would otherwise show up multiple times diff --git a/src/routes/(app)/profile/+page.svelte b/src/routes/(app)/profile/+page.svelte index cb2b9b7a..b0da374b 100644 --- a/src/routes/(app)/profile/+page.svelte +++ b/src/routes/(app)/profile/+page.svelte @@ -6,11 +6,10 @@ import Setting from "@/lib/settings/Setting.svelte"; import Stat from "@/lib/stats/Stat.svelte"; import Stats from "@/lib/stats/Stats.svelte"; - import { updateUserSetting } from "@/lib/util/api"; + import { req, updateUserSetting } from "@/lib/util/api"; import { getOrdinalSuffix, monthsShort } from "@/lib/util/helpers"; import { store } from "@/store.svelte"; import { UserType, type Image, type Profile } from "@/types"; - import axios from "axios"; import { notify } from "@/lib/util/notify"; import UserAvatar from "@/lib/img/UserAvatar.svelte"; import PwChangeModal from "@/routes/(app)/profile/modals/PwChangeModal.svelte"; @@ -19,6 +18,7 @@ import RatingSetting from "@/lib/rating/RatingSetting.svelte"; import { toggleTheme } from "@/lib/util/theme"; import ExportListModal from "./modals/ExportListModal.svelte"; + import { ReqerError } from "@/lib/util/fetch"; let user = $derived(store.userInfo); let settings = $derived(store.userSettings); @@ -37,7 +37,7 @@ let plexSyncModalOpen = $state(false); async function getProfile() { - return (await axios.get(`/profile`)).data as Profile; + return await req.get(`/profile`); } function formatDate(d: Date) { @@ -55,7 +55,7 @@ return; } const nid = notify({ text: "Updating Bio", type: "loading" }); - axios + req .post("/user/bio", { newBio: newBio }) .then(() => { if (user) { @@ -66,7 +66,7 @@ .catch((err) => { notify({ id: nid, - text: err?.response?.data?.error ?? "Failed to update bio", + text: ReqerError.getMsg(err, "Failed to update bio"), type: "error", }); }); @@ -79,19 +79,13 @@ return; } const nid = notify({ text: "Uploading avatar", type: "loading" }); - axios - .postForm( - "/user/avatar", - { avatar: files[0] }, - { - headers: { - "Content-Type": "multipart/form-data", - }, - }, - ) + const fd = new FormData(); + fd.append("avatar", files[0]); + req + .post("/user/avatar", fd) .then((r) => { if (user) { - user.avatar = r.data as Image; + user.avatar = r; notify({ id: nid, text: "Avatar Uploaded", type: "success" }); } }) @@ -99,7 +93,7 @@ console.error("uploading avatar failed", err); notify({ id: nid, - text: err?.response?.data?.error ?? "Failed to upload avatar", + text: ReqerError.getMsg(err, "Failed to upload avatar"), type: "error", }); }); diff --git a/src/routes/(app)/profile/modals/ExportListModal.svelte b/src/routes/(app)/profile/modals/ExportListModal.svelte index ca339782..9297f1f3 100644 --- a/src/routes/(app)/profile/modals/ExportListModal.svelte +++ b/src/routes/(app)/profile/modals/ExportListModal.svelte @@ -1,7 +1,7 @@ diff --git a/src/routes/(app)/server/modals/RadarrModal.svelte b/src/routes/(app)/server/modals/RadarrModal.svelte index 836af541..519deb2d 100644 --- a/src/routes/(app)/server/modals/RadarrModal.svelte +++ b/src/routes/(app)/server/modals/RadarrModal.svelte @@ -12,7 +12,8 @@ RadarrSettings, RadarrTestResponse, } from "@/types"; - import axios from "axios"; + import { req } from "@/lib/util/api"; + import { ReqerError } from "@/lib/util/fetch"; interface Props { servarr: RadarrSettings; @@ -22,7 +23,7 @@ let { servarr = $bindable(), isEditing, onClose }: Props = $props(); - let error: string = $state(); + let error: string | undefined = $state(); let formDisabled = $state(false); let qualityProfiles: DropDownItem[] = $state([]); @@ -42,14 +43,14 @@ async function getSettingsData() { try { formDisabled = true; - const res = await axios.post("/arr/rad/test", { + const res = await req.post("/arr/rad/test", { host: servarr.host, key: servarr.key, }); - qualityProfiles = res.data.qualityProfiles.map((d) => { + qualityProfiles = res.qualityProfiles.map((d) => { return { id: d.id, value: d.name }; }); - rootFolders = res.data.rootFolders.map((d) => { + rootFolders = res.rootFolders.map((d) => { return { id: d.id, value: d.path }; }); formDisabled = false; @@ -91,43 +92,33 @@ if (!error) { console.log(servarr); try { - const res = await axios.post( - `/arr/rad/${isEditing ? "edit" : "add"}`, - servarr, - ); - if (res.status === 200) { - notify({ - type: "success", - text: isEditing ? "Changes saved!" : "Server added successfully!", - }); - onClose(); - } + await req.post(`/arr/rad/${isEditing ? "edit" : "add"}`, servarr); + notify({ + type: "success", + text: isEditing ? "Changes saved!" : "Server added successfully!", + }); + onClose(); } catch (err: any) { console.error("Failed to save server!", err); - error = `Failed to ${isEditing ? "edit" : "add"}`; - if (err?.response?.data?.error) { - error = err.response.data.error; - } + error = ReqerError.getMsg( + err, + `Failed to ${isEditing ? "edit" : "add"}`, + ); } } } async function remove() { try { - const res = await axios.post(`/arr/rad/rm/${servarr.name}`); - if (res.status === 200) { - notify({ - type: "success", - text: "Removed server", - }); - onClose(); - } + await req.post(`/arr/rad/rm/${servarr.name}`); + notify({ + type: "success", + text: "Removed server", + }); + onClose(); } catch (err: any) { console.error("Failed to remove server!", err); - error = `Failed to remove`; - if (err?.response?.data?.error) { - error = err.response.data.error; - } + error = ReqerError.getMsg(err, "Failed to remove"); } } run(() => { diff --git a/src/routes/(app)/server/modals/SonarrModal.svelte b/src/routes/(app)/server/modals/SonarrModal.svelte index 72c09b1e..4d099b38 100644 --- a/src/routes/(app)/server/modals/SonarrModal.svelte +++ b/src/routes/(app)/server/modals/SonarrModal.svelte @@ -12,7 +12,8 @@ SonarrSettings, SonarrTestResponse, } from "@/types"; - import axios from "axios"; + import { req } from "@/lib/util/api"; + import { ReqerError } from "@/lib/util/fetch"; interface Props { servarr: SonarrSettings; @@ -44,17 +45,17 @@ async function getSettingsData() { try { formDisabled = true; - const res = await axios.post("/arr/son/test", { + const res = await req.post("/arr/son/test", { host: servarr.host, key: servarr.key, }); - qualityProfiles = res.data.qualityProfiles.map((d) => { + qualityProfiles = res.qualityProfiles.map((d) => { return { id: d.id, value: d.name }; }); - languageProfiles = res.data.languageProfiles.map((d) => { + languageProfiles = res.languageProfiles.map((d) => { return { id: d.id, value: d.name }; }); - rootFolders = res.data.rootFolders.map((d) => { + rootFolders = res.rootFolders.map((d) => { return { id: d.id, value: d.path }; }); formDisabled = false; @@ -99,43 +100,33 @@ if (!error) { console.log(servarr); try { - const res = await axios.post( - `/arr/son/${isEditing ? "edit" : "add"}`, - servarr, - ); - if (res.status === 200) { - notify({ - type: "success", - text: isEditing ? "Changes saved!" : "Server added successfully!", - }); - onClose(); - } + await req.post(`/arr/son/${isEditing ? "edit" : "add"}`, servarr); + notify({ + type: "success", + text: isEditing ? "Changes saved!" : "Server added successfully!", + }); + onClose(); } catch (err: any) { console.error("Failed to save server!", err); - error = `Failed to ${isEditing ? "edit" : "add"}`; - if (err?.response?.data?.error) { - error = err.response.data.error; - } + error = ReqerError.getMsg( + err, + `Failed to ${isEditing ? "edit" : "add"}`, + ); } } } async function remove() { try { - const res = await axios.post(`/arr/son/rm/${servarr.name}`); - if (res.status === 200) { - notify({ - type: "success", - text: "Removed server", - }); - onClose(); - } + await req.post(`/arr/son/rm/${servarr.name}`); + notify({ + type: "success", + text: "Removed server", + }); + onClose(); } catch (err: any) { console.error("Failed to remove server!", err); - error = `Failed to remove`; - if (err?.response?.data?.error) { - error = err.response.data.error; - } + error = ReqerError.getMsg(err, "Failed to remove"); } } run(() => { diff --git a/src/routes/(app)/server/modals/TaskScheduleModal.svelte b/src/routes/(app)/server/modals/TaskScheduleModal.svelte index 2f447a77..9c3715e0 100644 --- a/src/routes/(app)/server/modals/TaskScheduleModal.svelte +++ b/src/routes/(app)/server/modals/TaskScheduleModal.svelte @@ -1,6 +1,4 @@