Files
rudder-js-sdk/test/e2e-prod/_setup/adminClient.ts
T

78 lines
2.5 KiB
TypeScript
Raw Normal View History

2026-08-12 14:02:25 +03:00
// Minimal fetch wrapper for the LiveOps platform/admin HTTP API used by the seed
// and by tests' admin-side assertions. Retries network errors and 5xx with backoff;
// fails fast on 4xx.
const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
export class ApiError extends Error {
constructor(
public readonly status: number,
public readonly path: string,
public readonly body: string,
) {
super(`HTTP ${status} on ${path}: ${body.slice(0, 400)}`);
this.name = 'ApiError';
}
}
export interface AdminClient {
setToken(token: string): void;
readonly token: string | undefined;
get<T>(path: string, opts?: { auth?: boolean }): Promise<T>;
post<T>(path: string, body?: unknown, opts?: { auth?: boolean }): Promise<T>;
put<T>(path: string, body?: unknown, opts?: { auth?: boolean }): Promise<T>;
del<T>(path: string, opts?: { auth?: boolean }): Promise<T>;
}
export function createAdminClient(baseUrl: string): AdminClient {
let token: string | undefined;
async function request<T>(
method: string,
path: string,
body?: unknown,
opts?: { auth?: boolean },
): Promise<T> {
const url = `${baseUrl}${path}`;
const headers: Record<string, string> = { 'Content-Type': 'application/json' };
if (opts?.auth !== false && token) headers['Authorization'] = `Bearer ${token}`;
let lastErr: unknown;
for (let attempt = 0; attempt < 4; attempt++) {
try {
const res = await fetch(url, {
method,
headers,
body: body === undefined ? undefined : JSON.stringify(body),
});
const text = await res.text();
if (res.status >= 500) {
lastErr = new ApiError(res.status, path, text);
await sleep(300 * (attempt + 1));
continue;
}
if (!res.ok) throw new ApiError(res.status, path, text);
return (text ? JSON.parse(text) : undefined) as T;
} catch (err) {
if (err instanceof ApiError) throw err; // 4xx — don't retry
lastErr = err; // network error — retry
await sleep(300 * (attempt + 1));
}
}
throw lastErr;
}
return {
setToken(t: string) {
token = t;
},
get token() {
return token;
},
get: (path, opts) => request('GET', path, undefined, opts),
post: (path, body, opts) => request('POST', path, body, opts),
put: (path, body, opts) => request('PUT', path, body, opts),
del: (path, opts) => request('DELETE', path, undefined, opts),
};
}