63 lines
1.5 KiB
TypeScript
63 lines
1.5 KiB
TypeScript
|
|
// Generic API client with authentication
|
||
|
|
|
||
|
|
import type { User } from 'oidc-client-ts';
|
||
|
|
import { ApiError } from '@/types';
|
||
|
|
|
||
|
|
export interface RequestOptions {
|
||
|
|
method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
|
||
|
|
params?: Record<string, string | number | boolean | Date | undefined>;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Build query string from parameters object
|
||
|
|
*/
|
||
|
|
function buildQueryString(params: Record<string, string | number | boolean | Date | undefined>): string {
|
||
|
|
const queryString = new URLSearchParams();
|
||
|
|
|
||
|
|
for (const [key, value] of Object.entries(params)) {
|
||
|
|
if (value !== undefined && value !== null && value !== '') {
|
||
|
|
if (value instanceof Date) {
|
||
|
|
queryString.append(key, value.toISOString());
|
||
|
|
} else {
|
||
|
|
queryString.append(key, String(value));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return queryString.toString();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Generic authenticated API request
|
||
|
|
*/
|
||
|
|
export async function apiRequest<T>(
|
||
|
|
user: User,
|
||
|
|
endpoint: string,
|
||
|
|
options: RequestOptions = {}
|
||
|
|
): Promise<T> {
|
||
|
|
const { method = 'GET', params } = options;
|
||
|
|
const accessToken = user.access_token;
|
||
|
|
|
||
|
|
let url = endpoint;
|
||
|
|
if (params) {
|
||
|
|
const queryString = buildQueryString(params);
|
||
|
|
if (queryString) {
|
||
|
|
url = `${endpoint}?${queryString}`;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
const response = await fetch(url, {
|
||
|
|
method,
|
||
|
|
headers: {
|
||
|
|
Authorization: `Bearer ${accessToken}`,
|
||
|
|
'Content-Type': 'application/json',
|
||
|
|
},
|
||
|
|
});
|
||
|
|
|
||
|
|
if (!response.ok) {
|
||
|
|
throw new ApiError(`Error: ${response.status}`, response.status);
|
||
|
|
}
|
||
|
|
|
||
|
|
return response.json() as Promise<T>;
|
||
|
|
}
|