fix: 修复QQBot内置插件运行态注入

This commit is contained in:
sunlei 2026-06-17 11:57:30 +08:00
parent 39aabc6264
commit f3255123b7
4 changed files with 83 additions and 3 deletions

View File

@ -1,4 +1,10 @@
import { Inject, Injectable, OnModuleInit, Optional } from '@nestjs/common'; import {
forwardRef,
Inject,
Injectable,
OnModuleInit,
Optional,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { Between, LessThanOrEqual, MoreThanOrEqual, Repository } from 'typeorm'; import { Between, LessThanOrEqual, MoreThanOrEqual, Repository } from 'typeorm';
import { throwVbenError } from '@/common'; import { throwVbenError } from '@/common';
@ -162,6 +168,7 @@ export class QqbotPluginPlatformService
@Optional() @Optional()
private readonly packageReader?: QqbotPluginPackageReaderService, private readonly packageReader?: QqbotPluginPackageReaderService,
@Optional() @Optional()
@Inject(forwardRef(() => QqbotBuiltinPluginPackageLoaderService))
private readonly builtinPluginLoader?: QqbotBuiltinPluginPackageLoaderService, private readonly builtinPluginLoader?: QqbotBuiltinPluginPackageLoaderService,
@Optional() @Optional()
private readonly taskSynchronizer?: QqbotPluginTaskManifestSynchronizer, private readonly taskSynchronizer?: QqbotPluginTaskManifestSynchronizer,

View File

@ -1,4 +1,10 @@
import { Injectable, OnModuleInit, Optional } from '@nestjs/common'; import {
forwardRef,
Inject,
Injectable,
OnModuleInit,
Optional,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm'; import { Repository } from 'typeorm';
import { formatKtDateTime, throwVbenError } from '@/common'; import { formatKtDateTime, throwVbenError } from '@/common';
@ -26,6 +32,7 @@ export class QqbotEventPluginRegistryService implements OnModuleInit {
constructor( constructor(
private readonly accountService: QqbotAccountService, private readonly accountService: QqbotAccountService,
@Inject(forwardRef(() => QqbotBuiltinPluginPackageLoaderService))
private readonly builtinPluginLoader: QqbotBuiltinPluginPackageLoaderService, private readonly builtinPluginLoader: QqbotBuiltinPluginPackageLoaderService,
@Optional() @Optional()
@InjectRepository(QqbotPlugin) @InjectRepository(QqbotPlugin)

View File

@ -1,4 +1,10 @@
import { Injectable, OnModuleInit, Optional } from '@nestjs/common'; import {
forwardRef,
Inject,
Injectable,
OnModuleInit,
Optional,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm'; import { Repository } from 'typeorm';
import { formatKtDateTime, throwVbenError } from '@/common'; import { formatKtDateTime, throwVbenError } from '@/common';
@ -24,6 +30,7 @@ export class QqbotPluginRegistryService implements OnModuleInit {
constructor( constructor(
@Optional() @Optional()
@Inject(forwardRef(() => QqbotBuiltinPluginPackageLoaderService))
private readonly builtinPluginLoader?: QqbotBuiltinPluginPackageLoaderService, private readonly builtinPluginLoader?: QqbotBuiltinPluginPackageLoaderService,
@Optional() @Optional()
@InjectRepository(QqbotPlugin) @InjectRepository(QqbotPlugin)

View File

@ -0,0 +1,59 @@
import 'reflect-metadata';
import { SELF_DECLARED_DEPS_METADATA } from '@nestjs/common/constants';
type DependencyMetadata = {
index: number;
param: unknown;
};
const unwrapForwardRef = (token: unknown) => {
if (
token &&
typeof token === 'object' &&
'forwardRef' in token &&
typeof token.forwardRef === 'function'
) {
return token.forwardRef();
}
return token;
};
const resolveConstructorToken = (target: unknown, index: number) => {
const explicitDependencies = (Reflect.getMetadata(
SELF_DECLARED_DEPS_METADATA,
target,
) || []) as DependencyMetadata[];
const explicitToken = explicitDependencies.find(
(dependency) => dependency.index === index,
)?.param;
if (explicitToken) return unwrapForwardRef(explicitToken);
const designTypes =
(Reflect.getMetadata('design:paramtypes', target) as unknown[]) || [];
return unwrapForwardRef(designTypes[index]);
};
describe('QQBot plugin platform DI tokens', () => {
beforeEach(() => {
jest.resetModules();
});
it('keeps the built-in plugin loader injection token stable across require order', async () => {
const { QqbotBuiltinPluginPackageLoaderService } = await import(
'../../../../src/modules/qqbot/plugin-platform/infrastructure/integration/package/builtin-plugin-package-loader.service'
);
const { QqbotPluginRegistryService } = await import(
'../../../../src/modules/qqbot/plugin-platform/application/registry/qqbot-plugin-registry.service'
);
const { QqbotPluginPlatformService } = await import(
'../../../../src/modules/qqbot/plugin-platform/application/plugin-platform.service'
);
expect(resolveConstructorToken(QqbotPluginRegistryService, 0)).toBe(
QqbotBuiltinPluginPackageLoaderService,
);
expect(resolveConstructorToken(QqbotPluginPlatformService, 14)).toBe(
QqbotBuiltinPluginPackageLoaderService,
);
});
});