refactor(core): migrate to Bun and converge acquisition policies and Agent boundaries

This commit is contained in:
root committed 2026-10-13 14:37:03 +08:00
1 parent 3f1c6d02f6
commit 27c0f27434
268 files changed
+7468 -7852

No files matched your search

@@ -28,7 +28,7 @@ import { readBrowserUserAgent, resolveUserAgent, type UserAgentDefaults } from "
export interface RuntimeOverrides {
/** 站点与 RSS 请求使用的 fetch(测试指向 mock) */
fetch?: typeof globalThis.fetch;
fetch?: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
/** TMDB 客户端工厂;返回 null 表示未配置(只做本地召回) */
tmdb?: (() => TmdbClient | null) | undefined;
now?: () => Date;
@@ -39,7 +39,7 @@ export interface RuntimeOverrides {
/** false = 站点限流只用进程内令牌桶(缺省走 PG 跨进程令牌桶 rate_limit_bucket) */
sharedRateLimit?: boolean;
/** 豆瓣 / bgm.tv 请求用的 fetch;null = 不在线查(测试缺省不出外网) */
metaFetch?: typeof globalThis.fetch | null;
metaFetch?: ((input: RequestInfo | URL, init?: RequestInit) => Promise<Response>) | null;
}
interface CachedAdapter {
@@ -78,9 +78,9 @@ export class SourcesRuntime {
* 未配置时回退环境变量 TMDB_API_KEY / TMDB_ACCESS_TOKEN / TMDB_BASE_URL。设置变化(引用/地址)时重建。
*/
/** 豆瓣 / bgm.tv 请求:注入优先;测试进程(VITEST)缺省不出外网;否则按环境变量代理出外网 */
metaFetch(): typeof globalThis.fetch | null {
metaFetch(): ((input: RequestInfo | URL, init?: RequestInit) => Promise<Response>) | null {
if (this.overrides.metaFetch !== undefined) return this.overrides.metaFetch;
return Deno.env.get("VITEST") ? null : externalFetch;
return process.env.VITEST ? null : externalFetch;
}
async tmdb(): Promise<TmdbClient | null> {
@@ -110,7 +110,7 @@ export class SourcesRuntime {
if (!cfg) return null;
let n = 0;
const base = cfg.fetch ?? externalFetch;
const counted: typeof fetch = (input, init) => {
const counted: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response> = (input, init) => {
n++;
return base(input, init);
};
@@ -122,7 +122,7 @@ export class SourcesRuntime {
private async tmdbConfig(): Promise<{ sig: string; cfg: Parameters<typeof createTmdbClient>[0] | null }> {
const meta = await this.ctx.settings.get("metadata").catch(() => null);
const policy = await tmdbCachePolicy(this.ctx);
const env = (k: string) => Deno.env.get(k);
const env = (k: string) => process.env[k];
const ref = meta?.tmdbApiKeySecretRef ?? null;
const baseUrl = meta?.tmdbBaseUrl ?? env("TMDB_BASE_URL");
const sig = JSON.stringify([
@@ -189,7 +189,7 @@ export class SourcesRuntime {
site: Pick<SiteRow, "proxy"> & Partial<Pick<SiteRow, "id">>,
defaults: SitesSettings = this.siteDefaultsCache,
ua?: string | (() => Promise<string>),
): typeof globalThis.fetch {
): (input: RequestInfo | URL, init?: RequestInit) => Promise<Response> {
const base = this.transportFetch(site, defaults);
const egress = this.egressKeyOf(site, defaults);
const siteId = site.id;
@@ -214,7 +214,7 @@ export class SourcesRuntime {
return base(input, { ...init, headers: h, ...(signal ? { signal } : {}) });
},
);
}) as typeof globalThis.fetch;
}) as (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
}
/** 站点 HTTP 出口键(direct / proxy:<主机>),与浏览器会话的出口同一口径 */
@@ -223,7 +223,10 @@ export class SourcesRuntime {
}
/** 不加 UA 的底层 fetch(测试注入 / 按站点出口:代理或明确直连) */
private transportFetch(site: Pick<SiteRow, "proxy">, defaults: SitesSettings): typeof globalThis.fetch {
private transportFetch(
site: Pick<SiteRow, "proxy">,
defaults: SitesSettings,
): (input: RequestInfo | URL, init?: RequestInit) => Promise<Response> {
if (this.overrides.fetch) return this.overrides.fetch;
return siteFetchFor(siteEgress(site.proxy, defaults.proxyUrl));
}