diff --git a/src/modules/qqbot/plugin-platform/application/plugin-platform.service.ts b/src/modules/qqbot/plugin-platform/application/plugin-platform.service.ts index 15fe432..8d96797 100644 --- a/src/modules/qqbot/plugin-platform/application/plugin-platform.service.ts +++ b/src/modules/qqbot/plugin-platform/application/plugin-platform.service.ts @@ -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 { Between, LessThanOrEqual, MoreThanOrEqual, Repository } from 'typeorm'; import { throwVbenError } from '@/common'; @@ -162,6 +168,7 @@ export class QqbotPluginPlatformService @Optional() private readonly packageReader?: QqbotPluginPackageReaderService, @Optional() + @Inject(forwardRef(() => QqbotBuiltinPluginPackageLoaderService)) private readonly builtinPluginLoader?: QqbotBuiltinPluginPackageLoaderService, @Optional() private readonly taskSynchronizer?: QqbotPluginTaskManifestSynchronizer, diff --git a/src/modules/qqbot/plugin-platform/application/registry/qqbot-event-plugin-registry.service.ts b/src/modules/qqbot/plugin-platform/application/registry/qqbot-event-plugin-registry.service.ts index 87f4f4c..4c2e68e 100644 --- a/src/modules/qqbot/plugin-platform/application/registry/qqbot-event-plugin-registry.service.ts +++ b/src/modules/qqbot/plugin-platform/application/registry/qqbot-event-plugin-registry.service.ts @@ -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 { Repository } from 'typeorm'; import { formatKtDateTime, throwVbenError } from '@/common'; @@ -26,6 +32,7 @@ export class QqbotEventPluginRegistryService implements OnModuleInit { constructor( private readonly accountService: QqbotAccountService, + @Inject(forwardRef(() => QqbotBuiltinPluginPackageLoaderService)) private readonly builtinPluginLoader: QqbotBuiltinPluginPackageLoaderService, @Optional() @InjectRepository(QqbotPlugin) diff --git a/src/modules/qqbot/plugin-platform/application/registry/qqbot-plugin-registry.service.ts b/src/modules/qqbot/plugin-platform/application/registry/qqbot-plugin-registry.service.ts index b595382..9a7b4d2 100644 --- a/src/modules/qqbot/plugin-platform/application/registry/qqbot-plugin-registry.service.ts +++ b/src/modules/qqbot/plugin-platform/application/registry/qqbot-plugin-registry.service.ts @@ -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 { Repository } from 'typeorm'; import { formatKtDateTime, throwVbenError } from '@/common'; @@ -24,6 +30,7 @@ export class QqbotPluginRegistryService implements OnModuleInit { constructor( @Optional() + @Inject(forwardRef(() => QqbotBuiltinPluginPackageLoaderService)) private readonly builtinPluginLoader?: QqbotBuiltinPluginPackageLoaderService, @Optional() @InjectRepository(QqbotPlugin) diff --git a/test/modules/qqbot/plugin-platform/plugin-platform-di.spec.ts b/test/modules/qqbot/plugin-platform/plugin-platform-di.spec.ts new file mode 100644 index 0000000..828f94e --- /dev/null +++ b/test/modules/qqbot/plugin-platform/plugin-platform-di.spec.ts @@ -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, + ); + }); +});