feat: 实现依赖注入系统、插件架构和窗口管理

- 引入ExamAware的DI系统并适配SecScore项目
- 添加服务注册表和窗口管理器
- 实现基于Koishi的Disposable设计的插件系统
- 集成Winston日志服务
- 分离设置窗口为独立页面
- 将非核心功能改为内置插件
- 更新README文件
- 添加相关hooks和工具函数
This commit is contained in:
Yukino_fox
2026-04-26 19:39:56 +08:00
parent a39355d62a
commit 18eada8ff3
47 changed files with 5347 additions and 180 deletions
+184
View File
@@ -0,0 +1,184 @@
import type {
ConfigureHostDelegate,
HostBuilderContext,
HostExposure,
HostedService,
PluginHostApplicationContext,
PluginMiddleware,
ServiceToken,
} from "./types"
import { ServiceProvider } from "./serviceCollection"
// 插件Host应用类,管理应用的生命周期和托管服务
export class PluginHostApplication {
private hostedInstances: HostedService[] = [] // 已启动的托管服务实例
private hostDisposers: Array<() => void> = [] // 清理函数列表
private started = false // 是否已启动
constructor(
private readonly context: HostBuilderContext, // Host构建器上下文
private readonly provider: ServiceProvider, // 服务提供者
private readonly configureDelegates: ConfigureHostDelegate[], // 配置委托
private readonly middleware: PluginMiddleware[], // 中间件
private readonly hostedTokens: ServiceToken<HostedService>[] // 托管服务令牌
) {}
// 包装应用,添加服务暴露功能
withExposures(exposures: HostExposure[]): PluginHostApplicationWithExposures {
return new PluginHostApplicationWithExposures(this, exposures)
}
// 启动应用
async start(): Promise<void> {
if (this.started) return
const appCtx = this.createApplicationContext() // 创建应用上下文
// 执行所有配置委托
for (const configure of this.configureDelegates) {
await configure(this.context, appCtx)
}
// 通过中间件管道执行终端逻辑(启动托管服务)
await this.dispatch(0, appCtx, async () => {
await this.bootstrapHostedServices()
})
this.started = true
await this.context.lifetime.notifyStarted() // 通知生命周期已启动
}
// 停止应用
async stop(): Promise<void> {
if (!this.started) return
await this.context.lifetime.notifyStopping() // 通知正在停止
await this.disposeHostedServices() // 停止托管服务
await this.context.lifetime.notifyStopped() // 通知已停止
this.started = false
}
// 释放资源
async dispose(): Promise<void> {
await this.stop()
await this.provider.dispose() // 释放服务提供者
}
// 获取服务提供者
get services(): ServiceProvider {
return this.provider
}
// 获取Host上下文
get hostContext(): HostBuilderContext {
return this.context
}
// 创建应用上下文
private createApplicationContext(): PluginHostApplicationContext {
return {
ctx: this.context.ctx,
services: this.provider,
host: this.context,
}
}
// 启动所有托管服务
private async bootstrapHostedServices() {
for (const token of this.hostedTokens) {
const service = this.provider.get(token) // 从提供者获取服务实例
this.hostedInstances.push(service)
if (typeof service.start === "function") {
await service.start() // 调用启动方法
}
}
}
// 停止所有托管服务
private async disposeHostedServices() {
while (this.hostedInstances.length) {
const service = this.hostedInstances.pop()
if (!service) continue
if (typeof service.stop === "function") {
await service.stop() // 调用停止方法
}
}
}
// 执行中间件管道
private async dispatch(
index: number,
appCtx: PluginHostApplicationContext,
terminal: () => Promise<void>
) {
const middleware = this.middleware[index]
if (!middleware) {
await terminal() // 执行终端逻辑
return
}
// 调用中间件,传入下一个中间件的执行函数
await middleware(appCtx, () => this.dispatch(index + 1, appCtx, terminal))
}
}
// 带服务暴露的Host应用类
export class PluginHostApplicationWithExposures {
private readonly exposureDisposers: Array<() => void> = [] // 暴露服务的清理函数
constructor(
private readonly app: PluginHostApplication,
private readonly exposures: HostExposure[]
) {}
// 启动应用,包括注册暴露服务
async start(): Promise<void> {
try {
await this.registerExposures() // 先注册暴露服务
await this.app.start() // 再启动应用
} catch (error) {
await this.disposeExposures() // 出错时清理暴露服务
throw error
}
}
// 停止应用,包括清理暴露服务
async stop(): Promise<void> {
await this.app.stop()
await this.disposeExposures()
}
// 释放资源
async dispose(): Promise<void> {
await this.app.dispose()
await this.disposeExposures()
}
// 获取服务提供者
get services() {
return this.app.services
}
// 获取Host上下文
get hostContext() {
return this.app.hostContext
}
// 注册暴露的服务到插件上下文
private async registerExposures() {
const ctx = this.app.hostContext.ctx
if (!ctx.services) return
for (const exposure of this.exposures) {
const value = exposure.resolver(this.app.services) // 解析服务值
const disposer = ctx.services.provide(exposure.name, value) // 注册到服务API
this.exposureDisposers.push(disposer)
}
}
// 清理暴露的服务
private async disposeExposures() {
while (this.exposureDisposers.length) {
const dispose = this.exposureDisposers.pop()
if (!dispose) continue
await dispose() // 调用清理函数
}
}
}
+167
View File
@@ -0,0 +1,167 @@
import { ServiceCollection, ServiceProvider } from "./serviceCollection"
import { PluginHostApplication, PluginHostApplicationWithExposures } from "./hostApplication"
import {
type ConfigureHostDelegate,
type ConfigureServicesDelegate,
type HostBuilderContext,
type HostBuilderSettings,
type HostExposure,
type HostExposureResolver,
type HostedService,
type PluginMiddleware,
type PluginRuntimeContext,
type ServiceToken,
} from "./types"
// ExamAware Host构建器,类似.NET的HostBuilder,用于配置插件的服务和生命周期
export class ExamAwareHostBuilder {
private readonly serviceCollection: ServiceCollection // 服务集合,管理所有注册的服务
private readonly configureServicesDelegates: ConfigureServicesDelegate[] = [] // 配置服务的委托列表
private readonly configureDelegates: ConfigureHostDelegate[] = [] // 配置应用的委托列表
private readonly middleware: PluginMiddleware[] = [] // 中间件列表
private readonly hostedServices: ServiceToken<HostedService>[] = [] // 托管服务的令牌列表
private readonly exposures: HostExposure[] = [] // 要暴露的服务列表
private readonly builderContext: HostBuilderContext // 构建器上下文
constructor(
private readonly runtimeCtx: PluginRuntimeContext,
settings: HostBuilderSettings = {}
) {
this.serviceCollection = new ServiceCollection(runtimeCtx)
this.builderContext = {
ctx: runtimeCtx,
environmentName: settings.environment ?? process.env.EXAMAWARE_ENV ?? "Production",
properties: new Map(Object.entries(settings.properties ?? {})),
lifetime: this.serviceCollection.getLifetime(), // 获取应用生命周期管理器
}
}
// 获取构建器上下文
get context(): HostBuilderContext {
return this.builderContext
}
// 添加服务配置委托
configureServices(callback: ConfigureServicesDelegate): this {
this.configureServicesDelegates.push(callback)
return this
}
// 添加应用配置委托
configure(callback: ConfigureHostDelegate): this {
this.configureDelegates.push(callback)
return this
}
// 添加中间件
use(middleware: PluginMiddleware): this {
this.middleware.push(middleware)
return this
}
// 添加托管服务
addHostedService(token: ServiceToken<HostedService>): this {
this.hostedServices.push(token)
return this
}
// 暴露服务到插件上下文
exposeHostService(name: string, resolver: HostExposureResolver): this {
const normalized = this.normalizeResolver(resolver)
if (normalized) {
this.exposures.push({ name, resolver: normalized })
}
return this
}
// 构建Host应用
async build(): Promise<PluginHost> {
// 执行所有服务配置委托
for (const configure of this.configureServicesDelegates) {
await configure(this.builderContext, this.serviceCollection)
}
const provider = this.serviceCollection.buildServiceProvider() // 构建服务提供者
const application = new PluginHostApplication(
this.builderContext,
provider,
this.configureDelegates,
this.middleware,
this.hostedServices
)
return new PluginHost(application.withExposures(this.exposures)) // 返回包装了暴露服务的Host
}
// 标准化暴露解析器
private normalizeResolver(
resolver: HostExposureResolver
): ((provider: ServiceProvider) => unknown) | null {
if (resolver.token) {
return (provider) => provider.get(resolver.token as ServiceToken) // 通过令牌获取服务
}
if (resolver.factory) {
return resolver.factory // 使用工厂函数
}
return null
}
}
// 插件Host类,管理应用的启动和停止
export class PluginHost {
constructor(private readonly app: PluginHostApplicationWithExposures) {}
// 获取服务提供者
get services() {
return this.app.services
}
// 获取Host上下文
get hostContext() {
return this.app.hostContext
}
// 启动应用
async start() {
await this.app.start()
}
// 停止应用
async stop() {
await this.app.stop()
}
// 释放资源
async dispose() {
await this.app.dispose()
}
// 运行应用,返回停止函数
async run() {
await this.start()
return async () => {
await this.dispose()
}
}
}
// 创建Host构建器的工厂函数
export function createPluginHostBuilder(ctx: PluginRuntimeContext, settings?: HostBuilderSettings) {
return new ExamAwareHostBuilder(ctx, settings)
}
// Host工具类,提供创建构建器的静态方法
export const Host = {
createApplicationBuilder: createPluginHostBuilder,
}
// 定义插件的辅助函数,使用Host构建器配置插件
export function defineExamAwarePlugin(
setup: (builder: ExamAwareHostBuilder) => Promise<void> | void
) {
return async function examAwarePlugin(ctx: PluginRuntimeContext) {
const builder = Host.createApplicationBuilder(ctx)
await setup(builder)
const host = await builder.build()
return host.run() // 返回运行函数,插件加载时调用
}
}
+30
View File
@@ -0,0 +1,30 @@
export {
ExamAwareHostBuilder,
PluginHost,
createPluginHostBuilder,
Host,
defineExamAwarePlugin,
} from "./hostBuilder"
export { ServiceCollection, ServiceProvider } from "./serviceCollection"
export {
PluginContextToken,
PluginLoggerToken,
PluginSettingsToken,
DesktopApiToken,
HostApplicationLifetimeToken,
} from "./tokens"
export type {
PluginRuntimeContext,
PluginLogger,
PluginSettingsAPI,
ServiceAPI,
HostedService,
PluginMiddleware,
HostBuilderSettings,
HostBuilderContext,
PluginHostApplicationLifetime,
ConfigureServicesDelegate,
ConfigureHostDelegate,
PluginHostApplicationContext,
ServiceToken,
} from "./types"
+61
View File
@@ -0,0 +1,61 @@
import type { Awaitable, Disposer, PluginHostApplicationLifetime } from "./types"
type LoggerLike = { error: (...args: any[]) => void }
// 默认的应用生命周期实现,管理启动/停止事件
export class DefaultHostApplicationLifetime implements PluginHostApplicationLifetime {
constructor(private readonly logger: LoggerLike = console) {}
private readonly started = new Set<() => Awaitable<void>>() // 启动事件处理器
private readonly stopping = new Set<() => Awaitable<void>>() // 停止事件处理器
private readonly stopped = new Set<() => Awaitable<void>>() // 已停止事件处理器
// 注册启动事件处理器
onStarted(handler: () => Awaitable<void>): Disposer {
this.started.add(handler)
return () => {
this.started.delete(handler)
} // 返回清理函数
}
// 注册停止事件处理器
onStopping(handler: () => Awaitable<void>): Disposer {
this.stopping.add(handler)
return () => {
this.stopping.delete(handler)
}
}
// 注册已停止事件处理器
onStopped(handler: () => Awaitable<void>): Disposer {
this.stopped.add(handler)
return () => {
this.stopped.delete(handler)
}
}
// 通知所有启动事件处理器
async notifyStarted() {
await this.dispatch(this.started)
}
// 通知所有停止事件处理器
async notifyStopping() {
await this.dispatch(this.stopping)
}
// 通知所有已停止事件处理器
async notifyStopped() {
await this.dispatch(this.stopped)
}
// 执行事件处理器列表
private async dispatch(targets: Set<() => Awaitable<void>>) {
for (const handler of Array.from(targets)) {
try {
await handler()
} catch (error) {
this.logger.error("[PluginHostLifetime] handler failed", error as Error) // 记录错误但不中断
}
}
}
}
+237
View File
@@ -0,0 +1,237 @@
import {
DesktopApiToken,
HostApplicationLifetimeToken,
PluginContextToken,
PluginLoggerToken,
PluginSettingsToken,
} from "./tokens"
import { DefaultHostApplicationLifetime } from "./lifetime"
import type {
Disposer,
InjectableClass,
PluginRuntimeContext,
ServiceDescriptor,
ServiceFactory,
ServiceFactoryOrValue,
ServiceLifetime,
ServiceToken,
} from "./types"
// 检查值是否为构造函数
function isConstructor<T>(value: ServiceFactoryOrValue<T>): value is InjectableClass<T> {
return (
typeof value === "function" &&
!!(value as any).prototype &&
(value as any).prototype.constructor === value
)
}
// 服务集合类,管理所有注册的服务描述符
export class ServiceCollection {
private readonly descriptors = new Map<ServiceToken, ServiceDescriptor>() // 服务描述符映射
private readonly hostLifetime: DefaultHostApplicationLifetime // 应用生命周期管理器
constructor(private readonly ctx: PluginRuntimeContext) {
this.hostLifetime = new DefaultHostApplicationLifetime((ctx as any).logger ?? console)
// 预注册常用服务
this.addSingleton(PluginContextToken, () => ctx)
this.addSingleton(PluginLoggerToken, () => ctx.logger)
this.addSingleton(PluginSettingsToken, () => ctx.settings)
this.addSingleton(DesktopApiToken, () => ctx.desktopApi)
this.addSingleton(HostApplicationLifetimeToken, () => this.hostLifetime)
}
// 获取生命周期管理器
getLifetime() {
return this.hostLifetime
}
// 添加单例服务
addSingleton<T>(token: ServiceToken<T>, impl: ServiceFactoryOrValue<T>): this {
return this.register(token, "singleton", impl)
}
// 添加作用域服务
addScoped<T>(token: ServiceToken<T>, impl: ServiceFactoryOrValue<T>): this {
return this.register(token, "scoped", impl)
}
// 添加瞬时服务
addTransient<T>(token: ServiceToken<T>, impl: ServiceFactoryOrValue<T>): this {
return this.register(token, "transient", impl)
}
// 尝试添加单例服务(如果不存在)
tryAddSingleton<T>(token: ServiceToken<T>, impl: ServiceFactoryOrValue<T>): this {
if (!this.descriptors.has(token)) {
this.addSingleton(token, impl)
}
return this
}
// 检查服务是否已注册
has(token: ServiceToken): boolean {
return this.descriptors.has(token)
}
// 清空所有服务
clear(): void {
this.descriptors.clear()
}
// 构建服务提供者
buildServiceProvider(): ServiceProvider {
return new ServiceProvider(this.ctx, new Map(this.descriptors))
}
// 注册服务
private register<T>(
token: ServiceToken<T>,
lifetime: ServiceLifetime,
impl: ServiceFactoryOrValue<T>
): this {
const descriptor: ServiceDescriptor = {
token,
lifetime,
factory: this.normalizeFactory(impl), // 标准化工厂函数
}
this.descriptors.set(token, descriptor)
return this
}
// 标准化工厂函数
private normalizeFactory<T>(impl: ServiceFactoryOrValue<T>): ServiceFactory<T> {
if (isConstructor(impl)) {
return (provider) => this.instantiateClass(impl, provider) // 构造函数,实例化类
}
if (typeof impl === "function") {
return impl as ServiceFactory<T> // 已经是工厂函数
}
return () => impl // 直接值,返回常量
}
// 实例化类,注入依赖
private instantiateClass<T>(Ctor: InjectableClass<T>, provider: ServiceProvider): T {
const deps = [...(Ctor.inject ?? [])].map((token) => provider.get(token)) // 获取依赖
return new Ctor(...deps) // 构造实例
}
}
// 服务提供者类,负责解析和提供服务实例
export class ServiceProvider {
private readonly singletonCache: Map<ServiceToken, unknown> // 单例缓存
private readonly scopedCache = new Map<ServiceToken, unknown>() // 作用域缓存
private readonly singletonCleanup: Disposer[] // 单例清理函数
private readonly scopedCleanup: Disposer[] = [] // 作用域清理函数
private readonly root: ServiceProvider | null // 根提供者
constructor(
private readonly ctx: PluginRuntimeContext,
private readonly descriptors: Map<ServiceToken, ServiceDescriptor>,
root: ServiceProvider | null = null,
private readonly isScope = false // 是否为作用域提供者
) {
this.root = root
this.singletonCache = root ? root.singletonCache : new Map() // 共享单例缓存
this.singletonCleanup = root ? root.singletonCleanup : []
}
// 获取服务实例
get<T>(token: ServiceToken<T>): T {
const descriptor = this.descriptors.get(token) as ServiceDescriptor<T> | undefined
if (!descriptor) {
const hostValue = this.resolveFromHost<T>(token) // 尝试从宿主获取
if (hostValue !== undefined) return hostValue
throw new Error(`Service not registered for token: ${token.toString?.() ?? String(token)}`)
}
switch (descriptor.lifetime) {
case "singleton":
return this.resolveSingleton(descriptor)
case "scoped":
return this.resolveScoped(descriptor)
case "transient":
default:
return this.instantiate(descriptor) // 每次都新实例
}
}
// 创建作用域提供者
createScope(): ServiceProvider {
return new ServiceProvider(this.ctx, this.descriptors, this.root ?? this, true)
}
// 释放资源
async dispose(): Promise<void> {
await this.flushCleanup(this.scopedCleanup) // 先清理作用域
if (!this.isScope) {
await this.flushCleanup(this.singletonCleanup) // 再清理单例
this.singletonCache.clear()
}
this.scopedCache.clear()
}
// 解析单例服务
private resolveSingleton<T>(descriptor: ServiceDescriptor<T>): T {
const cacheOwner = this.root ?? this
if (cacheOwner.singletonCache.has(descriptor.token)) {
return cacheOwner.singletonCache.get(descriptor.token) as T
}
const instance = this.instantiate(descriptor)
cacheOwner.singletonCache.set(descriptor.token, instance)
const disposer = this.extractDisposer(instance) // 提取清理函数
if (disposer) cacheOwner.singletonCleanup.push(disposer)
return instance
}
// 解析作用域服务
private resolveScoped<T>(descriptor: ServiceDescriptor<T>): T {
if (this.scopedCache.has(descriptor.token)) {
return this.scopedCache.get(descriptor.token) as T
}
const instance = this.instantiate(descriptor)
this.scopedCache.set(descriptor.token, instance)
const disposer = this.extractDisposer(instance)
if (disposer) this.scopedCleanup.push(disposer)
return instance
}
// 实例化服务
private instantiate<T>(descriptor: ServiceDescriptor<T>): T {
return descriptor.factory(this)
}
// 从宿主服务API解析
private resolveFromHost<T>(token: ServiceToken<T>): T | undefined {
if (typeof token === "string" && this.ctx.services?.has?.(token)) {
return this.ctx.services.inject<T>(token)
}
return undefined
}
// 提取实例的清理函数
private extractDisposer(instance: unknown): Disposer | null {
if (!instance) return null
if (typeof (instance as any).dispose === "function") {
return () => (instance as any).dispose()
}
if (typeof (instance as any).destroy === "function") {
return () => (instance as any).destroy()
}
if (typeof (instance as any).stop === "function") {
return () => (instance as any).stop()
}
return null
}
// 执行清理函数列表
private async flushCleanup(cleanup: Disposer[]) {
while (cleanup.length) {
const disposer = cleanup.pop()
if (!disposer) continue
await disposer()
}
}
}
+17
View File
@@ -0,0 +1,17 @@
// 服务令牌定义,用于依赖注入
// 使用Symbol确保唯一性,避免字符串冲突
// 插件运行时上下文令牌
export const PluginContextToken = Symbol.for("examaware.hosting.ctx")
// 插件日志器令牌
export const PluginLoggerToken = Symbol.for("examaware.hosting.logger")
// 插件设置API令牌
export const PluginSettingsToken = Symbol.for("examaware.hosting.settings")
// Desktop API令牌
export const DesktopApiToken = Symbol.for("examaware.hosting.desktopApi")
// 应用生命周期管理器令牌
export const HostApplicationLifetimeToken = Symbol.for("examaware.hosting.lifetime")
+150
View File
@@ -0,0 +1,150 @@
import type { ServiceProvideOptions, ServiceWatcherMeta } from "../../shared/services/registry"
import type { ServiceCollection, ServiceProvider } from "./serviceCollection"
// 基础类型定义
export type Awaitable<T> = T | Promise<T> // 可以是同步值或Promise
export type Disposer = () => Awaitable<void> // 清理函数,返回void或Promise<void>
// 服务令牌,可以是字符串、符号或构造函数
export type ServiceToken<T = unknown> = string | symbol | (new (...args: any[]) => T)
// 可注入的类,带可选的inject属性声明依赖
export interface InjectableClass<T = unknown> {
new (...args: any[]): T
inject?: readonly ServiceToken[] // 依赖的令牌列表
}
// 服务工厂函数,从provider获取实例
export type ServiceFactory<T> = (provider: ServiceProvider) => T
// 服务实现,可以是工厂函数、构造函数或直接值
export type ServiceFactoryOrValue<T> = ServiceFactory<T> | InjectableClass<T> | T
// 服务生命周期:单例、作用域内单例、每次都新实例
export type ServiceLifetime = "singleton" | "scoped" | "transient"
// 服务描述符,定义如何创建服务
export interface ServiceDescriptor<T = unknown> {
token: ServiceToken<T>
lifetime: ServiceLifetime
factory: ServiceFactory<T> // 创建实例的工厂函数
}
// 托管服务接口,有启动和停止方法
export interface HostedService {
start(): Awaitable<void>
stop(): Awaitable<void>
}
// Host构建器设置
export interface HostBuilderSettings {
environment?: string // 环境名,如'development'
properties?: Record<string, unknown> // 额外属性
}
// Host构建器上下文,包含运行时上下文和配置
export interface HostBuilderContext {
ctx: PluginRuntimeContext // 插件运行时上下文
environmentName: string // 当前环境
properties: Map<string | symbol, unknown> // 属性映射
lifetime: PluginHostApplicationLifetime // 应用生命周期管理
}
// 插件应用上下文,包含服务提供者和上下文
export interface PluginHostApplicationContext {
ctx: PluginRuntimeContext
services: ServiceProvider
host: HostBuilderContext
}
// 配置服务委托,在构建时注册服务
export type ConfigureServicesDelegate = (
context: HostBuilderContext,
services: ServiceCollection
) => Awaitable<void>
// 配置Host委托,在应用启动时执行
export type ConfigureHostDelegate = (
context: HostBuilderContext,
app: PluginHostApplicationContext
) => Awaitable<void>
// 中间件函数,包装应用逻辑
export type PluginMiddleware = (
app: PluginHostApplicationContext,
next: () => Promise<void>
) => Awaitable<void>
// 暴露服务解析器,可以通过令牌或工厂函数
export interface HostExposureResolver<T = unknown> {
token?: ServiceToken<T> // 通过令牌暴露
factory?: (provider: ServiceProvider) => T // 通过工厂函数暴露
}
// 服务API接口,插件用来注册和获取服务
export interface ServiceAPI {
provide: (name: string, value: unknown, options?: ServiceProvideOptions) => Disposer
inject: <T = unknown>(name: string, owner?: string) => T
injectAsync?: <T = unknown>(name: string, owner?: string) => Promise<T>
when?: <T = unknown>(
name: string,
cb: (svc: T, owner: string, meta: ServiceWatcherMeta) => void | (() => void)
) => Disposer
has: (name: string, owner?: string) => boolean
}
// 插件日志接口
export interface PluginLogger {
info: (...args: any[]) => void
warn: (...args: any[]) => void
error: (...args: any[]) => void
debug?: (...args: any[]) => void
}
// 插件设置API,读写配置
export interface PluginSettingsAPI {
all(): Record<string, any> // 获取所有配置
get<T = unknown>(key?: string, def?: T): T // 获取单个配置项
set<T = unknown>(key: string, value: T): Promise<void> // 设置配置项
patch(partial: Record<string, any>): Promise<void> // 批量更新配置
reset(): Promise<void> // 重置配置
onChange(listener: (config: Record<string, any>) => void): Disposer // 监听配置变化
}
// 插件运行时上下文,插件的核心接口
export interface PluginRuntimeContext {
app: "main" | "renderer" // 运行在主进程还是渲染进程
logger: PluginLogger // 日志器
config: Record<string, any> // 插件配置
settings: PluginSettingsAPI // 设置API
effect: (fn: () => void | Disposer | Promise<void | Disposer>) => void // 注册副作用清理
services: ServiceAPI // 服务API
windows?: {
// 窗口操作(主进程)
broadcast: (channel: string, payload?: any) => void
}
ipc?: {
// IPC通信(主进程)
registerChannel: (channel: string, handler: (event: unknown, ...args: any[]) => any) => Disposer
invokeRenderer?: (channel: string, payload?: any) => void
}
desktopApi?: unknown // Desktop API(渲染进程)
}
// 插件应用生命周期接口,管理启动/停止事件
export interface PluginHostApplicationLifetime {
onStarted(handler: () => Awaitable<void>): Disposer // 监听启动事件
onStopping(handler: () => Awaitable<void>): Disposer // 监听停止事件
onStopped(handler: () => Awaitable<void>): Disposer // 监听已停止事件
notifyStarted(): Promise<void> // 触发启动通知
notifyStopping(): Promise<void> // 触发停止通知
notifyStopped(): Promise<void> // 触发已停止通知
}
// 暴露的服务定义
export type HostExposure = {
name: string // 服务名
resolver: (provider: ServiceProvider) => unknown // 解析函数
}
// 重新导出类型,便于使用
export type { ServiceCollection, ServiceProvider }