From 153b05414e48b4412b866874e1eae4f99db0326c Mon Sep 17 00:00:00 2001 From: ywkj Date: Fri, 20 Mar 2026 06:19:16 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20remove=20all=20token=20caching=20?= =?UTF-8?q?=E2=80=94=20always=20fetch=20fresh=20session?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every call now hits /auth/skill-credit/session directly. Deletes cache.ts, removes CachedTokenData type, strips cacheDir/minTtlSec options. Co-Authored-By: Claude Opus 4.6 --- src/auth.ts | 37 ++--------------------- src/cache.ts | 83 --------------------------------------------------- src/client.ts | 32 ++------------------ src/index.ts | 1 - src/types.ts | 13 -------- 5 files changed, 5 insertions(+), 161 deletions(-) delete mode 100644 src/cache.ts diff --git a/src/auth.ts b/src/auth.ts index d54e338..bf82ff1 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -1,6 +1,5 @@ import type { ApiResponse, EnvConfig, HttpMethod, SessionResponse } from './types.js'; 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 = [ @@ -18,8 +17,6 @@ export function createEnvConfig(): EnvConfig { 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), }; } @@ -65,53 +62,23 @@ export async function fetchSessionJson( } /** - * Get access token with caching + * Get access token (always fetches fresh) */ export async function getAccessToken( dryRun: boolean, config: EnvConfig ): Promise { - 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) + * Refresh access token (same as getAccessToken — no cache to clear) */ export async function refreshAccessToken( dryRun: boolean, config: EnvConfig ): Promise { - 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); } diff --git a/src/cache.ts b/src/cache.ts deleted file mode 100644 index 5cf0fb6..0000000 --- a/src/cache.ts +++ /dev/null @@ -1,83 +0,0 @@ -import * as fs from 'fs'; -import * as path from 'path'; -import * as crypto from 'crypto'; -import type { CachedTokenData } from './types.js'; - -/** - * Generate SHA256 hash for cache key - */ -export function sha256(input: string): string { - return crypto.createHash('sha256').update(input).digest('hex'); -} - -/** - * Get cache file path for current AUTH_BASE and CLIENT_KEY - */ -export function getCacheFile(authBase: string, clientKey: string, cacheDir: string): string { - const key = sha256(`${authBase}|${clientKey}`); - - if (!fs.existsSync(cacheDir)) { - fs.mkdirSync(cacheDir, { recursive: true }); - } - - return path.join(cacheDir, `session_${key}.json`); -} - -/** - * Read cached token if valid - */ -export function readCachedToken( - cacheFile: string, - minTtlSec: number -): string | null { - if (!fs.existsSync(cacheFile)) { - return null; - } - - try { - const data = JSON.parse(fs.readFileSync(cacheFile, 'utf-8')) as CachedTokenData; - const now = Math.floor(Date.now() / 1000); - - if (!data.accessToken || data.expiresAtEpoch <= 0) { - return null; - } - - // Check if token is still valid (with min TTL buffer) - if (now + minTtlSec >= data.expiresAtEpoch) { - return null; - } - - return data.accessToken; - } catch (error) { - return null; - } -} - -/** - * Write token to cache - */ -export function writeCache( - cacheFile: string, - sessionJson: { accessToken: string; expiresIn: number } -): void { - const nowEpoch = Math.floor(Date.now() / 1000); - const expiresIn = sessionJson.expiresIn > 0 ? sessionJson.expiresIn : 900; - const expiresAtEpoch = nowEpoch + expiresIn; - - const cacheData: CachedTokenData = { - accessToken: sessionJson.accessToken, - expiresAtEpoch, - createdAtEpoch: nowEpoch, - }; - - fs.writeFileSync(cacheFile, JSON.stringify(cacheData, null, 2), 'utf-8'); -} - -/** - * Delete cache file if exists - */ -export function deleteCache(cacheFile: string): void { - if (fs.existsSync(cacheFile)) { - fs.unlinkSync(cacheFile); - } -} diff --git a/src/client.ts b/src/client.ts index daa5a2d..ace7f52 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1,6 +1,5 @@ import type { ApiResponse, ClientConfig, EnvConfig, HttpMethod, SessionResponse } from './types.js'; import { requestApi } from './http.js'; -import { getCacheFile, readCachedToken, writeCache, deleteCache } from './cache.js'; import { loadGlobalEnv } from './env.js'; const SESSION_RETRYABLE_STATUS = new Set([401, 403]); @@ -21,10 +20,6 @@ export interface SkillClientOptions { apiBase?: string; /** Dry run mode — no real HTTP calls */ dryRun?: boolean; - /** Cache directory (default: /tmp/skill-auth-cache) */ - cacheDir?: string; - /** Min TTL before token refresh, seconds (default: 60) */ - minTtlSec?: number; } function buildConfig(options: SkillClientOptions): EnvConfig { @@ -32,8 +27,6 @@ function buildConfig(options: SkillClientOptions): EnvConfig { return { authBase: (options.authBase || process.env.AUTH_BASE || 'https://api-gw-test.yuanwei-lnc.com').replace(/\/$/, ''), clientKey: options.clientKey || process.env.CLIENT_KEY || '', - authCacheDir: options.cacheDir || process.env.AUTH_CACHE_DIR || '/tmp/skill-auth-cache', - authMinTtlSec: options.minTtlSec ?? parseInt(process.env.AUTH_MIN_TTL_SEC || '60', 10), }; } @@ -118,37 +111,18 @@ export class SkillClient { const url = `${this.apiBase}${path}`; const bodyStr = body != null ? JSON.stringify(body) : undefined; - const token = await this.getToken(); + const token = (await this.fetchSession()).accessToken; const first = await requestApi(method, url, token, bodyStr); if (!isRetryable(first)) { return first; } - // Token expired — refresh and retry once - const freshToken = await this.refreshToken(); + // Token rejected — fetch fresh and retry once + const freshToken = (await this.fetchSession()).accessToken; return requestApi(method, url, freshToken, bodyStr); } - private async getToken(): Promise { - const cacheFile = getCacheFile(this.config.authBase, this.config.clientKey, this.config.authCacheDir); - const cached = readCachedToken(cacheFile, this.config.authMinTtlSec); - if (cached) return cached; - - const session = await this.fetchSession(); - writeCache(cacheFile, session); - return session.accessToken; - } - - private async refreshToken(): Promise { - const cacheFile = getCacheFile(this.config.authBase, this.config.clientKey, this.config.authCacheDir); - deleteCache(cacheFile); - - const session = await this.fetchSession(); - writeCache(cacheFile, session); - return session.accessToken; - } - private async fetchSession(): Promise { const result = await requestApi( 'POST', diff --git a/src/index.ts b/src/index.ts index ee2ac82..d131f6f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -19,7 +19,6 @@ export type { EnvConfig, SessionResponse, ClientConfig, - CachedTokenData, ApiResponse, HttpMethod, } from './types.js'; diff --git a/src/types.ts b/src/types.ts index 8e83271..4532b70 100644 --- a/src/types.ts +++ b/src/types.ts @@ -6,10 +6,6 @@ export interface EnvConfig { authBase: string; /** Client key for authentication */ clientKey: string; - /** Directory for storing auth cache files */ - authCacheDir: string; - /** Minimum TTL for cached tokens in seconds */ - authMinTtlSec: number; } /** @@ -33,15 +29,6 @@ export interface ClientConfig { metadata: Record; } -/** - * Cached token data stored on disk - */ -export interface CachedTokenData { - accessToken: string; - expiresAtEpoch: number; - createdAtEpoch: number; -} - /** * HTTP method used by requestApi */