From ec69b8f11bfd4b20991aef74a72a47182ca79a9d Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Sat, 11 Jul 2026 23:40:13 +0800 Subject: [PATCH] =?UTF-8?q?fix(pipeline):=20=E9=87=8D=E6=9E=84=E8=BF=90?= =?UTF-8?q?=E8=A1=8C=E6=97=B6=E4=BE=9D=E8=B5=96=E5=8A=A0=E8=BD=BD=E9=80=BB?= =?UTF-8?q?=E8=BE=91=EF=BC=8C=E4=BF=AE=E5=A4=8D=E7=81=AB=E5=B1=B1=E5=BC=95?= =?UTF-8?q?=E6=93=8EDNS=E8=A7=A3=E6=9E=90=E6=8A=A5runtimeDepsService?= =?UTF-8?q?=E6=9C=AA=E5=88=9D=E5=A7=8B=E5=8C=96=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core/pipeline/src/access/api.ts | 3 - .../core/pipeline/src/access/decorator.ts | 2 +- .../core/pipeline/src/notification/api.ts | 3 - packages/core/pipeline/src/plugin/api.ts | 3 - .../src/user/access/service/access-getter.ts | 19 ++---- .../src/user/access/service/access-service.ts | 18 ++++-- .../libs/lib-server/src/user/addon/api/api.ts | 3 - .../plugin-lib/src/cert/dns-provider/base.ts | 3 - .../controller/user/mine/mine-controller.ts | 6 ++ .../user/pipeline/handle-controller.ts | 8 +-- .../src/modules/auto/auto-load-plugins.ts | 7 +++ .../service/getter/task-service-getter.ts | 3 +- .../modules/plugin/service/plugin-service.ts | 2 + .../runtime-deps/runtime-deps-service.ts | 58 ++++++++++++++++++- .../plugins/plugin-volcengine/cdn-client.ts | 3 +- .../plugins/plugin-volcengine/dns-client.ts | 3 +- .../plugins/plugin-volcengine/ve-client.ts | 8 ++- .../volcengine-dns-provider.ts | 1 + 18 files changed, 105 insertions(+), 48 deletions(-) diff --git a/packages/core/pipeline/src/access/api.ts b/packages/core/pipeline/src/access/api.ts index 8298b1306..d72c71cc5 100644 --- a/packages/core/pipeline/src/access/api.ts +++ b/packages/core/pipeline/src/access/api.ts @@ -62,9 +62,6 @@ export abstract class BaseAccess implements IAccess { if (!this.runtimeDepsService && this.ctx.serviceGetter) { this.runtimeDepsService = await this.ctx.serviceGetter.get("runtimeDepsService"); } - if (this.runtimeDepsService && this.ctx.define?.name) { - await this.runtimeDepsService.ensureRuntimeDependencies({ pluginKeys: `access:${this.ctx.define.name}`, logger: this.ctx.logger }); - } } async onRequest(req: AccessRequestHandleReq) { diff --git a/packages/core/pipeline/src/access/decorator.ts b/packages/core/pipeline/src/access/decorator.ts index 70779561b..549d9999d 100644 --- a/packages/core/pipeline/src/access/decorator.ts +++ b/packages/core/pipeline/src/access/decorator.ts @@ -47,7 +47,7 @@ export function AccessInput(input?: AccessInputDefine): PropertyDecorator { }; } -export async function newAccess(type: string, input: any, accessService: IAccessService, ctx?: AccessContext) { +export async function newAccess(type: string, input: any, accessService: IAccessService, ctx: AccessContext) { const register = accessRegistry.get(type); if (register == null) { throw new Error(`access ${type} not found`); diff --git a/packages/core/pipeline/src/notification/api.ts b/packages/core/pipeline/src/notification/api.ts index 130d12833..c083fe42c 100644 --- a/packages/core/pipeline/src/notification/api.ts +++ b/packages/core/pipeline/src/notification/api.ts @@ -112,9 +112,6 @@ export abstract class BaseNotification implements INotification { if (!this.runtimeDepsService && this.ctx.serviceGetter) { this.runtimeDepsService = await this.ctx.serviceGetter.get("runtimeDepsService"); } - if (this.runtimeDepsService && this.ctx.define?.name) { - await this.runtimeDepsService.ensureRuntimeDependencies({ pluginKeys: `notification:${this.ctx.define.name}`, logger: this.logger }); - } } setDefine = (define: NotificationDefine) => { this.define = define; diff --git a/packages/core/pipeline/src/plugin/api.ts b/packages/core/pipeline/src/plugin/api.ts index b04d457a6..c01ae3795 100644 --- a/packages/core/pipeline/src/plugin/api.ts +++ b/packages/core/pipeline/src/plugin/api.ts @@ -181,9 +181,6 @@ export abstract class AbstractTaskPlugin implements ITaskPlugin { if (!this.runtimeDepsService && this.ctx.serviceGetter) { this.runtimeDepsService = await this.ctx.serviceGetter.get("runtimeDepsService"); } - if (this.runtimeDepsService && this.ctx.define?.name) { - await this.runtimeDepsService.ensureRuntimeDependencies({ pluginKeys: `plugin:${this.ctx.define.name}`, logger: this.logger }); - } // 将证书加入secret // @ts-ignore if (this.cert && this.cert.crt && this.cert.key) { diff --git a/packages/libs/lib-server/src/user/access/service/access-getter.ts b/packages/libs/lib-server/src/user/access/service/access-getter.ts index d84686406..d89765c9a 100644 --- a/packages/libs/lib-server/src/user/access/service/access-getter.ts +++ b/packages/libs/lib-server/src/user/access/service/access-getter.ts @@ -1,29 +1,20 @@ -import { IAccessService, IRuntimeDepsService } from "@certd/pipeline"; - -export type AccessRuntimeDepsService = IRuntimeDepsService; +import { IAccessService } from "@certd/pipeline"; export class AccessGetter implements IAccessService { userId: number; projectId?: number; - runtimeDepsService?: AccessRuntimeDepsService; - getter: (id: any, userId?: number, projectId?: number, ignorePermission?: boolean, runtimeDepsService?: AccessRuntimeDepsService) => Promise; - constructor( - userId: number, - projectId: number, - getter: (id: any, userId: number, projectId?: number, ignorePermission?: boolean, runtimeDepsService?: AccessRuntimeDepsService) => Promise, - runtimeDepsService?: AccessRuntimeDepsService - ) { + getter: (id: any, userId?: number, projectId?: number, ignorePermission?: boolean) => Promise; + constructor(userId: number, projectId: number, getter: (id: any, userId: number, projectId?: number, ignorePermission?: boolean) => Promise) { this.userId = userId; this.projectId = projectId; this.getter = getter; - this.runtimeDepsService = runtimeDepsService; } async getById(id: any) { - return await this.getter(id, this.userId, this.projectId, false, this.runtimeDepsService); + return await this.getter(id, this.userId, this.projectId, false); } async getCommonById(id: any) { - return await this.getter(id, 0, null, false, this.runtimeDepsService); + return await this.getter(id, 0, null, false); } } diff --git a/packages/libs/lib-server/src/user/access/service/access-service.ts b/packages/libs/lib-server/src/user/access/service/access-service.ts index 44be1c588..9292ef965 100644 --- a/packages/libs/lib-server/src/user/access/service/access-service.ts +++ b/packages/libs/lib-server/src/user/access/service/access-service.ts @@ -1,8 +1,8 @@ -import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { ApplicationContext, Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import type { IMidwayContainer } from "@midwayjs/core"; import { InjectEntityModel } from "@midwayjs/typeorm"; import { In, Repository } from "typeorm"; import { AccessGetter, BaseService, PageReq, PermissionException, ValidateException } from "../../../index.js"; -import type { AccessRuntimeDepsService } from "./access-getter.js"; import { AccessEntity } from "../entity/access.js"; import { AccessDefine, accessRegistry, newAccess } from "@certd/pipeline"; import { EncryptService } from "./encrypt-service.js"; @@ -20,6 +20,9 @@ export class AccessService extends BaseService { @Inject() encryptService: EncryptService; + @ApplicationContext() + applicationContext: IMidwayContainer; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment //@ts-ignore getRepository() { @@ -161,7 +164,7 @@ export class AccessService extends BaseService { }; } - async getAccessById(id: any, checkUserId: boolean, userId?: number, projectId?: number, runtimeDepsService?: AccessRuntimeDepsService): Promise { + async getAccessById(id: any, checkUserId: boolean, userId?: number, projectId?: number): Promise { const entity = await this.info(id); if (entity == null) { throw new Error(`该授权配置不存在,请确认是否已被删除:id=${id}`); @@ -184,20 +187,23 @@ export class AccessService extends BaseService { id: entity.id, ...setting, }; + const taskServiceBuilder: any = await this.applicationContext.getAsync("taskServiceBuilder"); + const serviceGetter = taskServiceBuilder.create({ userId: userId || 0, projectId }); const getAccessById = this.getById.bind(this); - const accessGetter = new AccessGetter(userId, projectId, getAccessById, runtimeDepsService); + const accessGetter = new AccessGetter(userId, projectId, getAccessById); const accessContext = { logger, http, utils, accessService: accessGetter, + serviceGetter, } as any; const access = await newAccess(entity.type, input, accessGetter, accessContext); return access; } - async getById(id: any, userId: number, projectId?: number, _ignorePermission?: boolean, runtimeDepsService?: AccessRuntimeDepsService): Promise { - return await this.getAccessById(id, true, userId, projectId, runtimeDepsService); + async getById(id: any, userId: number, projectId?: number, _ignorePermission?: boolean): Promise { + return await this.getAccessById(id, true, userId, projectId); } decryptAccessEntity(entity: AccessEntity): any { diff --git a/packages/libs/lib-server/src/user/addon/api/api.ts b/packages/libs/lib-server/src/user/addon/api/api.ts index 9d56e3578..b5ccf937f 100644 --- a/packages/libs/lib-server/src/user/addon/api/api.ts +++ b/packages/libs/lib-server/src/user/addon/api/api.ts @@ -121,9 +121,6 @@ export abstract class BaseAddon implements IAddon { if (!this.runtimeDepsService && this.ctx.serviceGetter) { this.runtimeDepsService = await this.ctx.serviceGetter.get("runtimeDepsService"); } - if (this.runtimeDepsService && this.define?.addonType && this.define?.name) { - await this.runtimeDepsService.ensureRuntimeDependencies({ pluginKeys: `addon:${this.define.addonType}:${this.define.name}`, logger: this.logger }); - } } setDefine = (define:AddonDefine) => { this.define = define; diff --git a/packages/plugins/plugin-lib/src/cert/dns-provider/base.ts b/packages/plugins/plugin-lib/src/cert/dns-provider/base.ts index b74df800b..45e1c2933 100644 --- a/packages/plugins/plugin-lib/src/cert/dns-provider/base.ts +++ b/packages/plugins/plugin-lib/src/cert/dns-provider/base.ts @@ -45,9 +45,6 @@ export abstract class AbstractDnsProvider implements IDnsProvider { if (!this.runtimeDepsService && this.ctx.serviceGetter) { this.runtimeDepsService = await this.ctx.serviceGetter.get("runtimeDepsService"); } - if (this.runtimeDepsService && this.ctx.define?.name) { - await this.runtimeDepsService.ensureRuntimeDependencies({ pluginKeys: `dnsProvider:${this.ctx.define.name}`, logger: this.logger }); - } } async parseDomain(fullDomain: string) { diff --git a/packages/ui/certd-server/src/controller/user/mine/mine-controller.ts b/packages/ui/certd-server/src/controller/user/mine/mine-controller.ts index 1faefb321..c36837067 100644 --- a/packages/ui/certd-server/src/controller/user/mine/mine-controller.ts +++ b/packages/ui/certd-server/src/controller/user/mine/mine-controller.ts @@ -9,6 +9,7 @@ import { http, logger, utils } from "@certd/basic"; import { ApiTags } from "@midwayjs/swagger"; import { CodeService } from "../../../modules/basic/service/code-service.js"; import { EmailService } from "../../../modules/basic/service/email-service.js"; +import { TaskServiceBuilder } from "../../../modules/pipeline/service/getter/task-service-getter.js"; /** */ @@ -40,6 +41,9 @@ export class MineController extends BaseController { @Inject() emailService: EmailService; + @Inject() + taskServiceBuilder: TaskServiceBuilder; + @Post("/info", { description: Constants.per.authOnly, summary: "查询用户信息" }) public async info() { const userId = this.getUserId(); @@ -176,11 +180,13 @@ export class MineController extends BaseController { const getAccessById = this.accessService.getById.bind(this.accessService); const accessGetter = new AccessGetter(userId, undefined, getAccessById); + const serviceGetter = this.taskServiceBuilder.create({ userId }); const accessContext = { http, logger, utils, accessService: accessGetter, + serviceGetter, define: undefined, } as any; const access = await newAccess("acmeAccount", { caType: "letsencrypt", email: userEmail }, accessGetter, accessContext); diff --git a/packages/ui/certd-server/src/controller/user/pipeline/handle-controller.ts b/packages/ui/certd-server/src/controller/user/pipeline/handle-controller.ts index 021e310c1..9751a0544 100644 --- a/packages/ui/certd-server/src/controller/user/pipeline/handle-controller.ts +++ b/packages/ui/certd-server/src/controller/user/pipeline/handle-controller.ts @@ -8,7 +8,6 @@ import { TaskServiceBuilder } from "../../../modules/pipeline/service/getter/tas import { cloneDeep } from "lodash-es"; import { ApiTags } from "@midwayjs/swagger"; import { AuthService } from "../../../modules/sys/authority/service/auth-service.js"; -import { RuntimeDepsService } from "../../../modules/runtime-deps/runtime-deps-service.js"; @Provide() @Controller("/api/pi/handle") @@ -29,9 +28,6 @@ export class HandleController extends BaseController { @Inject() notificationService: NotificationService; - @Inject() - runtimeDepsService: RuntimeDepsService; - @Post("/access", { description: Constants.per.authOnly, summary: "处理授权请求" }) async accessRequest(@Body(ALL) body: AccessRequestHandleReq) { let { projectId, userId } = await this.getProjectUserIdRead(); @@ -64,12 +60,14 @@ export class HandleController extends BaseController { } } const getAccessById = this.accessService.getById.bind(this.accessService); - const accessGetter = new AccessGetter(userId, projectId, getAccessById, this.runtimeDepsService); + const accessGetter = new AccessGetter(userId, projectId, getAccessById); + const serviceGetter = this.taskServiceBuilder.create({ userId, projectId }); const accessContext = { http, logger, utils, accessService: accessGetter, + serviceGetter, define: undefined, } as any; const access = await newAccess(body.typeName, inputAccess, accessGetter, accessContext); diff --git a/packages/ui/certd-server/src/modules/auto/auto-load-plugins.ts b/packages/ui/certd-server/src/modules/auto/auto-load-plugins.ts index 7ea7b0bb1..3b9ed1b84 100644 --- a/packages/ui/certd-server/src/modules/auto/auto-load-plugins.ts +++ b/packages/ui/certd-server/src/modules/auto/auto-load-plugins.ts @@ -2,6 +2,7 @@ import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; import { logger } from "@certd/basic"; import { PluginService } from "../plugin/service/plugin-service.js"; import { registerPaymentProviders } from "../suite/payments/index.js"; +import { RuntimeDepsService } from "../runtime-deps/runtime-deps-service.js"; @Provide() @Scope(ScopeEnum.Request, { allowDowngrade: true }) @@ -9,6 +10,9 @@ export class AutoLoadPlugins { @Inject() pluginService: PluginService; + @Inject() + runtimeDepsService: RuntimeDepsService; + async init() { logger.info(`加载插件开始,加载模式:${process.env.certd_plugin_loadmode}`); if (process.env.certd_plugin_loadmode === "metadata") { @@ -30,5 +34,8 @@ export class AutoLoadPlugins { await registerPaymentProviders(); logger.info(`加载插件完成,加载模式:${process.env.certd_plugin_loadmode}`); + + // 收集插件 dependPackages 并安装 + await this.runtimeDepsService.refreshPluginDeps(); } } diff --git a/packages/ui/certd-server/src/modules/pipeline/service/getter/task-service-getter.ts b/packages/ui/certd-server/src/modules/pipeline/service/getter/task-service-getter.ts index 4c68bf1cb..2f60acb82 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/getter/task-service-getter.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/getter/task-service-getter.ts @@ -66,9 +66,8 @@ export class TaskServiceGetter implements IServiceGetter { async getAccessService(): Promise { const accessService: AccessService = await this.appCtx.getAsync("accessService"); - const runtimeDepsService = await this.getRuntimeDepsService(); const getAccessById = accessService.getById.bind(accessService); - return new AccessGetter(this.userId, this.projectId, getAccessById, runtimeDepsService); + return new AccessGetter(this.userId, this.projectId, getAccessById); } async getCnameProxyService(): Promise { diff --git a/packages/ui/certd-server/src/modules/plugin/service/plugin-service.ts b/packages/ui/certd-server/src/modules/plugin/service/plugin-service.ts index 7b578639b..b7a2f4676 100644 --- a/packages/ui/certd-server/src/modules/plugin/service/plugin-service.ts +++ b/packages/ui/certd-server/src/modules/plugin/service/plugin-service.ts @@ -270,6 +270,7 @@ export class PluginService extends BaseService { return; } await this.registerPlugin(item); + await this.runtimeDepsService.refreshPluginDeps(); } async unRegisterById(id: any) { @@ -297,6 +298,7 @@ export class PluginService extends BaseService { } else { logger.warn(`不支持的插件类型:${item.pluginType}`); } + await this.runtimeDepsService.refreshPluginDeps(); } async update(param: any) { diff --git a/packages/ui/certd-server/src/modules/runtime-deps/runtime-deps-service.ts b/packages/ui/certd-server/src/modules/runtime-deps/runtime-deps-service.ts index af13cb9c0..d6c7ef39b 100644 --- a/packages/ui/certd-server/src/modules/runtime-deps/runtime-deps-service.ts +++ b/packages/ui/certd-server/src/modules/runtime-deps/runtime-deps-service.ts @@ -150,6 +150,11 @@ export class RuntimeDepsService { @Config("runtimeDeps.lazyDependencies") lazyDependencies: Record = {}; + /** + * 从插件 registry 收集到的懒加载依赖,键为包名,值为版本范围 + */ + pluginLazyDependencies: Record = {}; + @Inject() registryResolver!: NpmRegistryResolver; @@ -339,7 +344,8 @@ export class RuntimeDepsService { private async resolveMissingRuntimeSpecifier(specifier: string, runtimeError: any, logger?: ILogger) { const packageName = this.parsePackageName(specifier); - const lazyRange = this.lazyDependencies?.[packageName]; + const mergedDeps = this.getMergedLazyDependencies(); + const lazyRange = mergedDeps[packageName]; if (!lazyRange) { try { return this.resolveProjectSpecifier(specifier, runtimeError).resolved; @@ -565,6 +571,56 @@ export class RuntimeDepsService { }); } + /** + * 合并 package.json 的 lazyDependencies 和插件注册表收集到的 dependPackages + * 插件依赖优先(同名时使用插件声明的版本) + */ + getMergedLazyDependencies(): Record { + return { ...this.lazyDependencies, ...this.pluginLazyDependencies }; + } + + /** + * 从所有插件注册表中收集 dependPackages,合并到 pluginLazyDependencies + */ + collectPluginDeps() { + const registries: Array<{ registry: Registry; keyFormatter?: (name: string) => string }> = [ + { registry: pluginRegistry }, + { registry: accessRegistry }, + { registry: notificationRegistry }, + { registry: dnsProviderRegistry }, + { registry: addonRegistry }, + ]; + + const deps: Record = {}; + for (const { registry } of registries) { + const defineList = registry.getDefineList(); + for (const define of defineList) { + const dependPackages = (define as any).dependPackages as Record | undefined; + if (!dependPackages) { + continue; + } + for (const [pkgName, range] of Object.entries(dependPackages)) { + const existing = deps[pkgName]; + if (existing && !areRangesCompatible(existing, range)) { + logger.warn(`懒加载依赖版本冲突: ${pkgName} => ${existing} vs ${range},保留已有版本`); + continue; + } + deps[pkgName] = range; + } + } + } + + this.pluginLazyDependencies = deps; + logger.info(`从插件注册表收集到 ${Object.keys(deps).length} 个懒加载依赖`); + } + + /** + * 刷新插件懒加载依赖:收集所有插件的 dependPackages 到内存列表,实际安装延迟到 importRuntime 时触发 + */ + async refreshPluginDeps() { + this.collectPluginDeps(); + } + private readInstallState(statePath: string): any { if (!fs.existsSync(statePath)) { return null; diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/cdn-client.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/cdn-client.ts index 148f7185c..3678ede0e 100644 --- a/packages/ui/certd-server/src/plugins/plugin-volcengine/cdn-client.ts +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/cdn-client.ts @@ -14,7 +14,8 @@ export class VolcengineCdnClient { if (this.service) { return this.service; } - const { cdn } = await this.opts.access.importRuntime("@volcengine/openapi"); + const importRuntime = this.opts.importRuntime || this.opts.access.importRuntime.bind(this.opts.access); + const { cdn } = await importRuntime("@volcengine/openapi"); const service = new cdn.CdnService(); // 设置ak、sk service.setAccessKeyId(this.opts.access.accessKeyId); diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/dns-client.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/dns-client.ts index 7d604ad54..68cd49738 100644 --- a/packages/ui/certd-server/src/plugins/plugin-volcengine/dns-client.ts +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/dns-client.ts @@ -21,7 +21,8 @@ export class VolcengineDnsClient { } async doRequest(req: VolcengineReq) { - const { Signer } = await this.opts.access.importRuntime("@volcengine/openapi"); + const importRuntime = this.opts.importRuntime || this.opts.access.importRuntime.bind(this.opts.access); + const { Signer } = await importRuntime("@volcengine/openapi"); // http request data const openApiRequestData: any = { diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/ve-client.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/ve-client.ts index 82fd34623..2bd2725ff 100644 --- a/packages/ui/certd-server/src/plugins/plugin-volcengine/ve-client.ts +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/ve-client.ts @@ -1,10 +1,12 @@ import { VolcengineAccess } from "./access.js"; import { HttpClient, ILogger } from "@certd/basic"; +import { ImportRuntime } from "@certd/pipeline"; export type VolcengineOpts = { access: VolcengineAccess; logger: ILogger; http: HttpClient; + importRuntime?: ImportRuntime; }; export class VolcengineClient { @@ -140,7 +142,8 @@ export class VolcengineClient { } async getTOSService(opts: { region?: string }) { - const { TosClient } = await this.opts.access.importRuntime("@volcengine/tos-sdk"); + const importRuntime = this.opts.importRuntime || this.opts.access.importRuntime.bind(this.opts.access); + const { TosClient } = await importRuntime("@volcengine/tos-sdk"); const client = new TosClient({ accessKeyId: this.opts.access.accessKeyId, @@ -169,7 +172,8 @@ export class VolcengineClient { if (this.CommonService) { return this.CommonService; } - const { Service } = await this.opts.access.importRuntime("@volcengine/openapi"); + const importRuntime = this.opts.importRuntime || this.opts.access.importRuntime.bind(this.opts.access); + const { Service } = await importRuntime("@volcengine/openapi"); class CommonService extends Service { Generic: any; diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/volcengine-dns-provider.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/volcengine-dns-provider.ts index 3bf5b35ee..762a74ae8 100644 --- a/packages/ui/certd-server/src/plugins/plugin-volcengine/volcengine-dns-provider.ts +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/volcengine-dns-provider.ts @@ -22,6 +22,7 @@ export class VolcengineDnsProvider extends AbstractDnsProvider { access: this.access, logger: this.logger, http: this.http, + importRuntime: this.importRuntime.bind(this), }); }