refactor: dedupe ACLED OAuth token request flow (#1569)

This commit is contained in:
Elie Habib
2026-03-14 13:59:39 +04:00
committed by GitHub
parent 24b502d0b1
commit 68f8e69f3e

View File

@@ -39,6 +39,12 @@ interface TokenState {
expiresAt: number;
}
interface AcledOAuthTokenResponse {
access_token?: string;
refresh_token?: string;
expires_in?: number;
}
/**
* In-memory fast-path cache.
* Acts as L1 cache; Redis is L2 and survives Vercel Edge cold starts.
@@ -46,6 +52,30 @@ interface TokenState {
let memCached: TokenState | null = null;
let refreshPromise: Promise<string | null> | null = null;
async function requestAcledToken(
body: URLSearchParams,
action: 'exchange' | 'refresh',
): Promise<AcledOAuthTokenResponse> {
const resp = await fetch(ACLED_TOKEN_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent': CHROME_UA,
},
body,
signal: AbortSignal.timeout(15_000),
});
if (!resp.ok) {
const text = await resp.text().catch(() => '');
throw new Error(
`ACLED OAuth token ${action} failed (${resp.status}): ${text.slice(0, 200)}`,
);
}
return (await resp.json()) as AcledOAuthTokenResponse;
}
/**
* Exchange ACLED credentials for an OAuth token pair.
*/
@@ -59,29 +89,7 @@ async function exchangeCredentials(
grant_type: 'password',
client_id: ACLED_CLIENT_ID,
});
const resp = await fetch(ACLED_TOKEN_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent': CHROME_UA,
},
body,
signal: AbortSignal.timeout(15_000),
});
if (!resp.ok) {
const text = await resp.text().catch(() => '');
throw new Error(
`ACLED OAuth token exchange failed (${resp.status}): ${text.slice(0, 200)}`,
);
}
const data = (await resp.json()) as {
access_token?: string;
refresh_token?: string;
expires_in?: number;
};
const data = await requestAcledToken(body, 'exchange');
if (!data.access_token || !data.refresh_token) {
throw new Error('ACLED OAuth response missing access_token or refresh_token');
@@ -103,29 +111,7 @@ async function refreshAccessToken(refreshToken: string): Promise<TokenState> {
grant_type: 'refresh_token',
client_id: ACLED_CLIENT_ID,
});
const resp = await fetch(ACLED_TOKEN_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent': CHROME_UA,
},
body,
signal: AbortSignal.timeout(15_000),
});
if (!resp.ok) {
const text = await resp.text().catch(() => '');
throw new Error(
`ACLED OAuth token refresh failed (${resp.status}): ${text.slice(0, 200)}`,
);
}
const data = (await resp.json()) as {
access_token?: string;
refresh_token?: string;
expires_in?: number;
};
const data = await requestAcledToken(body, 'refresh');
if (!data.access_token) {
throw new Error('ACLED OAuth refresh response missing access_token');