Files
openclaw/extensions/qa-matrix/src/substrate/request.ts
Gustavo Madeira Santana d5166718bc test(matrix): cover destructive E2EE backup recovery flows (#71311)
Merged via squash.

Prepared head SHA: fd5fc06007
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-04-25 17:48:18 -04:00

56 lines
1.7 KiB
TypeScript

export type MatrixQaFetchLike = typeof fetch;
type MatrixQaRequestResult<T> = {
status: number;
body: T;
};
export async function requestMatrixJson<T>(params: {
accessToken?: string;
baseUrl: string;
body?: unknown;
endpoint: string;
fetchImpl: MatrixQaFetchLike;
method: "DELETE" | "GET" | "POST" | "PUT";
okStatuses?: number[];
query?: Record<string, string | number | undefined>;
timeoutMs?: number;
}): Promise<MatrixQaRequestResult<T>> {
const url = new URL(params.endpoint, params.baseUrl);
for (const [key, value] of Object.entries(params.query ?? {})) {
if (value !== undefined) {
url.searchParams.set(key, String(value));
}
}
const response = await params.fetchImpl(url, {
method: params.method,
headers: {
accept: "application/json",
...(params.body !== undefined ? { "content-type": "application/json" } : {}),
...(params.accessToken ? { authorization: `Bearer ${params.accessToken}` } : {}),
},
...(params.body !== undefined ? { body: JSON.stringify(params.body) } : {}),
signal: AbortSignal.timeout(params.timeoutMs ?? 20_000),
});
let body: unknown = {};
try {
body = (await response.json()) as unknown;
} catch {
body = {};
}
const okStatuses = params.okStatuses ?? [200];
if (!okStatuses.includes(response.status)) {
const details =
typeof body === "object" &&
body !== null &&
typeof (body as { error?: unknown }).error === "string"
? (body as { error: string }).error
: `${params.method} ${params.endpoint} failed with status ${response.status}`;
throw new Error(details);
}
return {
status: response.status,
body: body as T,
};
}