mirror of
https://github.com/certd/certd.git
synced 2026-07-09 06:07:37 +08:00
feat: 通过插件配置懒加载依赖,动态加载第三方依赖包,精简安装镜像大小
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
import { Config, Provide, Scope, ScopeEnum } from "@midwayjs/core";
|
||||
|
||||
export type NpmRegistryResolverConfig = {
|
||||
mode: "auto" | "fixed" | "system";
|
||||
fixedUrl: string;
|
||||
candidates: string[];
|
||||
probeTimeoutMs: number;
|
||||
cacheTtlMs: number;
|
||||
};
|
||||
|
||||
export type RegistryProbeResult = {
|
||||
registryUrl: string;
|
||||
ok: boolean;
|
||||
elapsedMs: number;
|
||||
};
|
||||
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class NpmRegistryResolver {
|
||||
@Config("runtimeDeps.registry")
|
||||
config!: NpmRegistryResolverConfig;
|
||||
|
||||
private cache?: { registryUrl: string; expiresAt: number };
|
||||
|
||||
async resolve(): Promise<string> {
|
||||
const config = this.config;
|
||||
if (config?.mode === "fixed" && config.fixedUrl) {
|
||||
return config.fixedUrl;
|
||||
}
|
||||
if (config?.mode === "system") {
|
||||
return "";
|
||||
}
|
||||
|
||||
const cached = this.cache;
|
||||
if (cached && cached.expiresAt > Date.now()) {
|
||||
return cached.registryUrl;
|
||||
}
|
||||
|
||||
const candidates = (config?.candidates || []).filter(Boolean);
|
||||
const probes = await Promise.allSettled(candidates.map(registryUrl => this.probe(registryUrl)));
|
||||
const okList = probes
|
||||
.map(item => (item.status === "fulfilled" ? item.value : null))
|
||||
.filter((item): item is RegistryProbeResult => !!item && item.ok);
|
||||
|
||||
if (okList.length > 0) {
|
||||
okList.sort((a, b) => a.elapsedMs - b.elapsedMs);
|
||||
const best = okList[0].registryUrl;
|
||||
this.cache = {
|
||||
registryUrl: best,
|
||||
expiresAt: Date.now() + (config?.cacheTtlMs || 0),
|
||||
};
|
||||
return best;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
async probe(registryUrl: string): Promise<RegistryProbeResult> {
|
||||
const timeoutMs = this.config?.probeTimeoutMs || 3000;
|
||||
const started = Date.now();
|
||||
try {
|
||||
const controller = new AbortController();
|
||||
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
||||
try {
|
||||
const res = await fetch(`${registryUrl.replace(/\/$/, "")}/-/ping`, { signal: controller.signal });
|
||||
return {
|
||||
registryUrl,
|
||||
ok: res.ok,
|
||||
elapsedMs: Date.now() - started,
|
||||
};
|
||||
} finally {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
} catch {
|
||||
return {
|
||||
registryUrl,
|
||||
ok: false,
|
||||
elapsedMs: Date.now() - started,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user