auth-runtime/dist/auth.js

106 lines
3.6 KiB
JavaScript
Raw Normal View History

2026-03-11 23:33:43 +00:00
import { requestApi } from './http.js';
import { getCacheFile, readCachedToken, writeCache, deleteCache } from './cache.js';
const SESSION_RETRYABLE_STATUS = new Set([401, 403]);
const SESSION_RETRYABLE_BODY_MARKERS = [
'session not found or expired',
'invalid or expired token',
'unauthorized',
'client key expired',
'client key revoked',
];
/**
* Create environment configuration from process.env
*/
export function createEnvConfig() {
return {
authBase: (process.env.AUTH_BASE || 'https://api-gw-test.yuanwei-lnc.com').replace(/\/$/, ''),
clientKey: process.env.CLIENT_KEY || '',
authCacheDir: process.env.AUTH_CACHE_DIR || '/tmp/skill-auth-cache',
authMinTtlSec: parseInt(process.env.AUTH_MIN_TTL_SEC || '60', 10),
};
}
/**
* Fetch session JSON from auth endpoint
*/
export async function fetchSessionJson(dryRun, config) {
if (dryRun) {
return {
accessToken: '<dry-run-token>',
hookUrl: '<dry-run-hook-url>',
hookToken: '<dry-run-hook-token>',
expiresIn: 900,
};
}
if (!config.clientKey) {
throw new Error('CLIENT_KEY is required');
}
const payload = JSON.stringify({ clientKey: config.clientKey });
const result = await requestApi('POST', `${config.authBase}/auth/skill-credit/session`, undefined, payload);
if (result.status < 200 || result.status >= 300) {
throw new Error(`Auth session request failed: HTTP ${result.status} - ${result.body}`);
}
const session = JSON.parse(result.body);
if (!session.accessToken) {
throw new Error(`Missing accessToken in session response: ${result.body}`);
}
return session;
}
/**
* Get access token with caching
*/
export async function getAccessToken(dryRun, config) {
if (dryRun) {
return '<dry-run-token>';
}
if (!config.clientKey) {
throw new Error('CLIENT_KEY is required');
}
const cacheFile = getCacheFile(config.authBase, config.clientKey, config.authCacheDir);
const cachedToken = readCachedToken(cacheFile, config.authMinTtlSec);
if (cachedToken) {
return cachedToken;
}
const session = await fetchSessionJson(dryRun, config);
writeCache(cacheFile, session);
return session.accessToken;
}
/**
* Refresh access token (bypass cache)
*/
export async function refreshAccessToken(dryRun, config) {
if (dryRun) {
return '<dry-run-token>';
}
if (!config.clientKey) {
throw new Error('CLIENT_KEY is required');
}
const cacheFile = getCacheFile(config.authBase, config.clientKey, config.authCacheDir);
deleteCache(cacheFile);
return getAccessToken(dryRun, config);
}
/**
* Check whether response likely indicates expired/invalid runtime session.
*/
export function isRetryableSessionError(response) {
if (!SESSION_RETRYABLE_STATUS.has(response.status)) {
return false;
}
const body = (response.body || '').toLowerCase();
if (!body) {
return true;
}
return SESSION_RETRYABLE_BODY_MARKERS.some((marker) => body.includes(marker));
}
/**
* Make API request with automatic runtime token refresh and one retry.
*/
export async function requestApiWithAutoRefresh(method, url, dryRun, config, body, accessToken) {
const token = accessToken || await getAccessToken(dryRun, config);
const first = await requestApi(method, url, token, body);
if (!isRetryableSessionError(first)) {
return first;
}
const freshToken = await refreshAccessToken(dryRun, config);
return requestApi(method, url, freshToken, body);
}
//# sourceMappingURL=auth.js.map