1
0
mirror of https://github.com/Sonarr/Sonarr.git synced 2026-04-26 22:56:23 -04:00

Convert Add New Series to TypeScript

This commit is contained in:
Mark McDowall
2025-01-11 21:39:48 -08:00
parent ee46e6378a
commit 87c840974b
22 changed files with 818 additions and 1107 deletions
+56 -34
View File
@@ -1,54 +1,76 @@
import { useQuery } from '@tanstack/react-query';
import { UndefinedInitialDataOptions, useQuery } from '@tanstack/react-query';
import { useMemo } from 'react';
interface QueryOptions {
url: string;
headers?: HeadersInit;
interface ApiErrorResponse {
message: string;
details: string;
}
export class ApiError extends Error {
public statusCode: number;
public statusText: string;
public statusBody?: ApiErrorResponse;
public constructor(
path: string,
statusCode: number,
statusText: string,
statusBody?: ApiErrorResponse
) {
super(`Request Error: (${statusCode}) ${path}`);
this.statusCode = statusCode;
this.statusText = statusText;
this.statusBody = statusBody;
Object.setPrototypeOf(this, new.target.prototype);
}
}
interface QueryOptions<T> {
path: string;
headers?: HeadersInit;
queryOptions?:
| Omit<UndefinedInitialDataOptions<T, ApiError>, 'queryKey' | 'queryFn'>
| undefined;
}
const absUrlRegex = /^(https?:)?\/\//i;
const apiRoot = window.Sonarr.apiRoot;
function isAbsolute(url: string) {
return absUrlRegex.test(url);
}
function getUrl(url: string) {
return apiRoot + url;
}
function useApiQuery<T>(options: QueryOptions) {
const { url, headers } = options;
const final = useMemo(() => {
if (isAbsolute(url)) {
return {
url,
headers,
};
}
function useApiQuery<T>(options: QueryOptions<T>) {
const { path, headers } = useMemo(() => {
return {
url: getUrl(url),
path: apiRoot + options.path,
headers: {
...headers,
...options.headers,
'X-Api-Key': window.Sonarr.apiKey,
},
};
}, [url, headers]);
}, [options]);
return useQuery({
queryKey: [final.url],
queryFn: async () => {
const result = await fetch(final.url, {
headers: final.headers,
...options.queryOptions,
queryKey: [path, headers],
queryFn: async ({ signal }) => {
const response = await fetch(path, {
headers,
signal,
});
if (!result.ok) {
throw new Error('Failed to fetch');
if (!response.ok) {
// eslint-disable-next-line init-declarations
let body;
try {
body = (await response.json()) as ApiErrorResponse;
} catch {
throw new ApiError(path, response.status, response.statusText);
}
throw new ApiError(path, response.status, response.statusText, body);
}
return result.json() as T;
return response.json() as T;
},
});
}