diff --git a/package.json b/package.json index 936814ef..190246ae 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,6 @@ "@mui/x-date-pickers": "^6.19.2", "@vitejs/plugin-react-swc": "^3.5.0", "apollo-upload-client": "^17.0.0", - "axios": "^1.6.7", "dayjs": "^1.11.10", "file-selector": "^0.6.0", "graphql-tag": "^2.12.6", diff --git a/src/components/util/SpinnerImage.tsx b/src/components/util/SpinnerImage.tsx index a36269b3..eb17e207 100644 --- a/src/components/util/SpinnerImage.tsx +++ b/src/components/util/SpinnerImage.tsx @@ -14,7 +14,6 @@ import { Theme, SxProps, Stack, Button } from '@mui/material'; import BrokenImageIcon from '@mui/icons-material/BrokenImage'; import RefreshIcon from '@mui/icons-material/Refresh'; import { useTranslation } from 'react-i18next'; -import { CanceledError } from 'axios'; import { requestManager } from '@/lib/requests/RequestManager.ts'; import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts'; @@ -72,7 +71,7 @@ export const SpinnerImage = forwardRef((props: IProps, imgRef: ForwardedRef): void { + public updateClient(config: RequestInit): void { this.restClient.updateConfig(config); this.graphQLClient.updateConfig(); } public getBaseUrl(): string { - return this.restClient.getClient().defaults.baseURL!; + return this.restClient.getBaseUrl(); } public getValidUrlFor(endpoint: string, apiVersion: string = RequestManager.API_VERSION): string { @@ -764,8 +763,13 @@ export class RequestManager { const response = this.restClient .fetcher(url, { checkResponseIsJson: false, - config: { signal, responseType: 'blob' }, + config: { + signal, + // @ts-ignore - typing has not been updated yet + priority: 'low', + }, }) + .then((data) => data.blob()) .then((data) => URL.createObjectURL(data)); return { response, abortRequest }; diff --git a/src/lib/requests/client/RestClient.ts b/src/lib/requests/client/RestClient.ts index a21adef1..b70da094 100644 --- a/src/lib/requests/client/RestClient.ts +++ b/src/lib/requests/client/RestClient.ts @@ -6,33 +6,30 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'; import { BaseClient } from '@/lib/requests/client/BaseClient.ts'; export enum HttpMethod { - GET = 'get', - POST = 'post', - PATCH = 'patch', - DELETE = 'delete', + GET = 'GET', + POST = 'POST', + PATCH = 'PATCH', + DELETE = 'DELETE', } -type SimpleRestResponse = { - data: Data; -}; - export interface IRestClient { - get>(url: string): Promise; - delete>(url: string): Promise; - post>(url: string, data?: any): Promise; - put>(url: string, data?: any): Promise; - patch>(url: string, data?: any): Promise; + get(url: string): Promise; + delete(url: string): Promise; + post(url: string, data?: any): Promise; + put(url: string, data?: any): Promise; + patch(url: string, data?: any): Promise; } export class RestClient - extends BaseClient(url: string, data: any) => Promise> + extends BaseClient Promise> implements IRestClient { - public readonly fetcher = async ( + private config: RequestInit = {}; + + public readonly fetcher = async ( url: string, { data, @@ -42,20 +39,27 @@ export class RestClient }: { data?: any; httpMethod?: HttpMethod; - config?: AxiosRequestConfig; + config?: RequestInit; checkResponseIsJson?: boolean; } = {}, - ): Promise => { - let result: AxiosResponse; + ): Promise => { + const updatedUrl = url.startsWith('http') ? url : `${this.getBaseUrl()}${url}`; + + let result: Response; switch (httpMethod) { case HttpMethod.GET: - result = await this.client[httpMethod](url, config); + result = await this.client(updatedUrl, { ...this.config, ...config, method: httpMethod }); break; case HttpMethod.POST: case HttpMethod.PATCH: case HttpMethod.DELETE: - result = await this.client[httpMethod](url, data, config); + result = await this.client(updatedUrl, { + ...this.config, + ...config, + method: httpMethod, + body: JSON.stringify(data), + }); break; default: throw new Error(`Unexpected HttpMethod "${httpMethod}"`); @@ -65,54 +69,42 @@ export class RestClient throw new Error(result.statusText); } - if (checkResponseIsJson && result.headers['content-type'] !== 'application/json') { + if (checkResponseIsJson && result.headers.get('content-type') !== 'application/json') { throw new Error('Response is not json'); } - return result.data; + return result; }; protected override createClient(): void { - const baseURL = this.getBaseUrl(); - - this.client = axios.create({ - // baseURL must not have trailing slash - baseURL, - }); - - this.client.interceptors.request.use((config) => { - if (config.data instanceof FormData) { - Object.assign(config.headers, { 'Content-Type': 'multipart/form-data' }); - } - return config; - }); + this.client = fetch.bind(window); } - public updateConfig(config: Partial): void { - this.client.defaults = { ...this.client.defaults, ...config }; + public updateConfig(config: RequestInit): void { + this.config = { ...this.config, ...config }; } - public getClient(): AxiosInstance { + public getClient(): typeof fetch { return this.client; } get get() { - return this.client.get; + return (url: string) => this.fetcher(url); } get post() { - return this.client.post; + return (url: string, data?: any) => this.fetcher(url, { data, httpMethod: HttpMethod.POST }); } get put() { - return this.client.put; + return (url: string, data?: any) => this.fetcher(url, { data, httpMethod: HttpMethod.POST }); } get patch() { - return this.client.patch; + return (url: string, data?: any) => this.fetcher(url, { data, httpMethod: HttpMethod.PATCH }); } get delete() { - return this.client.delete; + return (url: string) => this.fetcher(url, { httpMethod: HttpMethod.DELETE }); } } diff --git a/src/screens/settings/ServerSettings.tsx b/src/screens/settings/ServerSettings.tsx index 0b9cddff..dd0a4e21 100644 --- a/src/screens/settings/ServerSettings.tsx +++ b/src/screens/settings/ServerSettings.tsx @@ -88,7 +88,6 @@ export const ServerSettings = () => { const handleServerAddressChange = (address: string) => { const serverBaseUrl = address.replaceAll(/(\/)+$/g, ''); setServerAddress(serverBaseUrl); - requestManager.updateClient({ baseURL: serverBaseUrl }); }; const updateSetting = ( diff --git a/yarn.lock b/yarn.lock index 11147c1d..f3020d8f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2249,11 +2249,6 @@ asynciterator.prototype@^1.0.0: dependencies: has-symbols "^1.0.3" -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== - auto-bind@~4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/auto-bind/-/auto-bind-4.0.0.tgz#e3589fc6c2da8f7ca43ba9f84fa52a744fc997fb" @@ -2269,15 +2264,6 @@ axe-core@=4.7.0: resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.7.0.tgz#34ba5a48a8b564f67e103f0aa5768d76e15bbbbf" integrity sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ== -axios@^1.6.7: - version "1.6.7" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.7.tgz#7b48c2e27c96f9c68a2f8f31e2ab19f59b06b0a7" - integrity sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA== - dependencies: - follow-redirects "^1.15.4" - form-data "^4.0.0" - proxy-from-env "^1.1.0" - axobject-query@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.2.1.tgz#39c378a6e3b06ca679f29138151e45b2b32da62a" @@ -2610,13 +2596,6 @@ colorette@^2.0.16: resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== -combined-stream@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -2786,11 +2765,6 @@ define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1: has-property-descriptors "^1.0.0" object-keys "^1.1.1" -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== - dependency-graph@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.11.0.tgz#ac0ce7ed68a54da22165a85e97a01d53f5eb2e27" @@ -3412,11 +3386,6 @@ flatted@^3.2.9: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf" integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ== -follow-redirects@^1.15.4: - version "1.15.5" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.5.tgz#54d4d6d062c0fa7d9d17feb008461550e3ba8020" - integrity sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw== - for-each@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" @@ -3424,15 +3393,6 @@ for-each@^0.3.3: dependencies: is-callable "^1.1.3" -form-data@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" - integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -4314,18 +4274,6 @@ micromatch@^4.0.4, micromatch@^4.0.5: braces "^3.0.2" picomatch "^2.3.1" -mime-db@1.52.0: - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - -mime-types@^2.1.12: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -4724,11 +4672,6 @@ prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: object-assign "^4.1.1" react-is "^16.13.1" -proxy-from-env@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" - integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== - punycode@^1.3.2: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"