upgrade to tamagui v2 and guest pwa overhaul
This commit is contained in:
95
resources/js/guest-v2/services/apiClient.ts
Normal file
95
resources/js/guest-v2/services/apiClient.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
export type ApiErrorPayload = {
|
||||
error?: {
|
||||
code?: string;
|
||||
title?: string;
|
||||
message?: string;
|
||||
meta?: Record<string, unknown>;
|
||||
};
|
||||
code?: string;
|
||||
message?: string;
|
||||
};
|
||||
|
||||
export type ApiError = Error & {
|
||||
status?: number;
|
||||
code?: string;
|
||||
meta?: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export type FetchJsonResult<T> = {
|
||||
data: T | null;
|
||||
etag: string | null;
|
||||
notModified: boolean;
|
||||
status: number;
|
||||
};
|
||||
|
||||
type FetchJsonOptions = {
|
||||
method?: string;
|
||||
headers?: HeadersInit;
|
||||
body?: BodyInit | null;
|
||||
signal?: AbortSignal;
|
||||
etag?: string | null;
|
||||
noStore?: boolean;
|
||||
};
|
||||
|
||||
export async function fetchJson<T>(url: string, options: FetchJsonOptions = {}): Promise<FetchJsonResult<T>> {
|
||||
const headers: Record<string, string> = {
|
||||
Accept: 'application/json',
|
||||
};
|
||||
|
||||
if (options.noStore) {
|
||||
headers['Cache-Control'] = 'no-store';
|
||||
}
|
||||
|
||||
if (options.etag) {
|
||||
headers['If-None-Match'] = options.etag;
|
||||
}
|
||||
|
||||
if (options.headers) {
|
||||
Object.assign(headers, options.headers as Record<string, string>);
|
||||
}
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: options.method ?? 'GET',
|
||||
headers,
|
||||
body: options.body ?? null,
|
||||
signal: options.signal,
|
||||
credentials: 'include',
|
||||
});
|
||||
|
||||
if (response.status === 304) {
|
||||
return {
|
||||
data: null,
|
||||
etag: response.headers.get('ETag') ?? options.etag ?? null,
|
||||
notModified: true,
|
||||
status: response.status,
|
||||
};
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
const errorPayload = await safeParseError(response);
|
||||
const error: ApiError = new Error(errorPayload?.error?.message ?? errorPayload?.message ?? `Request failed (${response.status})`);
|
||||
error.status = response.status;
|
||||
error.code = errorPayload?.error?.code ?? errorPayload?.code;
|
||||
if (errorPayload?.error?.meta) {
|
||||
error.meta = errorPayload.error.meta;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
|
||||
const data = (await response.json()) as T;
|
||||
return {
|
||||
data,
|
||||
etag: response.headers.get('ETag'),
|
||||
notModified: false,
|
||||
status: response.status,
|
||||
};
|
||||
}
|
||||
|
||||
async function safeParseError(response: Response): Promise<ApiErrorPayload | null> {
|
||||
try {
|
||||
const payload = (await response.clone().json()) as ApiErrorPayload;
|
||||
return payload;
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user