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: '', hookUrl: '', hookToken: '', 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 ''; } 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 ''; } if (!config.clientKey) { throw new Error('CLIENT_KEY is required'); } const cacheFile = getCacheFile(config.authBase, config.clientKey, config.authCacheDir); // Remove cache file if exists 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