import { AuthManager } from "./auth.js";
const GRAPH_BASE_URL = "https://graph.microsoft.com/v1.0";
export interface GraphResponse<T = unknown> {
value?: T[];
[key: string]: unknown;
}
export class GraphClient {
private auth: AuthManager;
constructor(auth: AuthManager) {
this.auth = auth;
}
private async request<T>(
endpoint: string,
options: RequestInit = {}
): Promise<T> {
const token = await this.auth.getAccessToken();
const url = endpoint.startsWith("http")
? endpoint
: `${GRAPH_BASE_URL}${endpoint}`;
const response = await fetch(url, {
...options,
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
...options.headers,
},
});
if (!response.ok) {
const errorBody = await response.text();
throw new Error(
`Graph API error ${response.status}: ${response.statusText}\n${errorBody}`
);
}
// DELETE returns 204 No Content
if (response.status === 204) {
return {} as T;
}
return response.json() as Promise<T>;
}
async get<T>(endpoint: string, params?: Record<string, string>): Promise<T> {
let url = endpoint;
if (params) {
const searchParams = new URLSearchParams(params);
url += `?${searchParams.toString()}`;
}
return this.request<T>(url);
}
async post<T>(endpoint: string, body: unknown): Promise<T> {
return this.request<T>(endpoint, {
method: "POST",
body: JSON.stringify(body),
});
}
async patch<T>(endpoint: string, body: unknown): Promise<T> {
return this.request<T>(endpoint, {
method: "PATCH",
body: JSON.stringify(body),
});
}
async delete(endpoint: string): Promise<void> {
await this.request(endpoint, { method: "DELETE" });
}
}