style: drop redundant comments and apply formatting
Frontend now uses double quotes and semicolons. No behaviour change.
This commit is contained in:
+48
-33
@@ -1,54 +1,69 @@
|
||||
export type User = { id: number; username: string }
|
||||
export type Genre = { id: number; name: string }
|
||||
export type ReadingStatus = 'not_started' | 'reading' | 'finished'
|
||||
export type User = { id: number; username: string };
|
||||
export type Genre = { id: number; name: string };
|
||||
export type ReadingStatus = "not_started" | "reading" | "finished";
|
||||
export type Book = {
|
||||
id: number
|
||||
title: string
|
||||
author: string
|
||||
genre: Genre
|
||||
total_pages: number
|
||||
current_page: number
|
||||
status: ReadingStatus
|
||||
created_at: string
|
||||
updated_at: string
|
||||
}
|
||||
export type Note = { id: number; book_id: number; body: string; created_at: string; updated_at: string }
|
||||
id: number;
|
||||
title: string;
|
||||
author: string;
|
||||
genre: Genre;
|
||||
total_pages: number;
|
||||
current_page: number;
|
||||
status: ReadingStatus;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
};
|
||||
export type Note = {
|
||||
id: number;
|
||||
book_id: number;
|
||||
body: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
};
|
||||
|
||||
export class ApiError extends Error {
|
||||
readonly status: number
|
||||
readonly field?: string
|
||||
readonly status: number;
|
||||
readonly field?: string;
|
||||
|
||||
constructor(status: number, message: string, field?: string) {
|
||||
super(message)
|
||||
this.status = status
|
||||
this.field = field
|
||||
super(message);
|
||||
this.status = status;
|
||||
this.field = field;
|
||||
}
|
||||
}
|
||||
|
||||
let handleUnauthorized: () => void = () => {}
|
||||
let handleUnauthorized: () => void = () => {};
|
||||
|
||||
export function setUnauthorizedHandler(handler: () => void) {
|
||||
handleUnauthorized = handler
|
||||
handleUnauthorized = handler;
|
||||
}
|
||||
|
||||
export async function api<T>(method: 'GET' | 'POST' | 'PATCH' | 'DELETE', path: string, body?: unknown): Promise<T> {
|
||||
export async function api<T>(
|
||||
method: "GET" | "POST" | "PATCH" | "DELETE",
|
||||
path: string,
|
||||
body?: unknown,
|
||||
): Promise<T> {
|
||||
const response = await fetch(`/api${path}`, {
|
||||
method,
|
||||
credentials: 'same-origin',
|
||||
// Always JSON: the server rejects mutations without it (CSRF defense, ADR-0002).
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
credentials: "same-origin",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: body === undefined ? undefined : JSON.stringify(body),
|
||||
})
|
||||
if (response.status === 204) return undefined as T
|
||||
const data = await response.json().catch(() => null)
|
||||
});
|
||||
if (response.status === 204) return undefined as T;
|
||||
const data = await response.json().catch(() => null);
|
||||
if (!response.ok) {
|
||||
// 401s from /auth/* are expected answers (bad login, not signed in yet), not an expired session.
|
||||
if (response.status === 401 && !path.startsWith('/auth/')) handleUnauthorized()
|
||||
throw new ApiError(response.status, data?.error ?? `Request failed with status ${response.status}`, data?.field)
|
||||
if (response.status === 401 && !path.startsWith("/auth/"))
|
||||
handleUnauthorized();
|
||||
throw new ApiError(
|
||||
response.status,
|
||||
data?.error ?? `Request failed with status ${response.status}`,
|
||||
data?.field,
|
||||
);
|
||||
}
|
||||
return data as T
|
||||
return data as T;
|
||||
}
|
||||
|
||||
export function errorMessage(error: unknown): string {
|
||||
return error instanceof ApiError ? error.message : 'Could not reach the server; check your connection and try again'
|
||||
return error instanceof ApiError
|
||||
? error.message
|
||||
: "Could not reach the server; check your connection and try again";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user