Add service handler registration and DI support

Introduces dependency injection via Inversify and reflect-metadata, adds a service handler registry for packet handling, and updates core initialization to auto-register and bind service handlers. Also updates Vite configs and auto-include logic to support protocol service files.
This commit is contained in:
手瓜一十雪 2025-11-14 22:20:33 +08:00
parent a2a73ce2dd
commit f04ffa5dc6
8 changed files with 62 additions and 13 deletions

View File

@ -14,6 +14,8 @@
"devDependencies": { "devDependencies": {
"@rollup/plugin-node-resolve": "^16.0.3", "@rollup/plugin-node-resolve": "^16.0.3",
"@vitejs/plugin-react-swc": "^4.2.2", "@vitejs/plugin-react-swc": "^4.2.2",
"inversify": "^7.10.4",
"reflect-metadata": "^0.2.2",
"typescript": "^5.3.0", "typescript": "^5.3.0",
"vite": "^6.4.1", "vite": "^6.4.1",
"vite-plugin-cp": "^6.0.3" "vite-plugin-cp": "^6.0.3"

View File

@ -31,6 +31,7 @@ import { NodeIKernelMsgListener, NodeIKernelProfileListener } from '@/napcat-cor
import { proxiedListenerOf } from 'napcat-common/src/proxy-handler'; import { proxiedListenerOf } from 'napcat-common/src/proxy-handler';
import { NTQQPacketApi } from './apis/packet'; import { NTQQPacketApi } from './apis/packet';
import { NativePacketHandler } from './packet/handler/client'; import { NativePacketHandler } from './packet/handler/client';
import { container, ReceiverServiceRegistry } from './packet/handler/serviceRegister';
export * from './wrapper'; export * from './wrapper';
export * from './types/index'; export * from './types/index';
export * from './services/index'; export * from './services/index';
@ -118,6 +119,15 @@ export class NapCatCore {
UserApi: new NTQQUserApi(this.context, this), UserApi: new NTQQUserApi(this.context, this),
GroupApi: new NTQQGroupApi(this.context, this), GroupApi: new NTQQGroupApi(this.context, this),
}; };
container.bind(NapCatCore).toConstantValue(this);
ReceiverServiceRegistry.forEach((ServiceClass, serviceName) => {
container.bind(ServiceClass).toSelf();
console.log(`Registering service handler for: ${serviceName}`);
this.context.packetHandler.onCmd(serviceName, ({ seq, hex_data }) => {
const serviceInstance = container.get(ServiceClass);
return serviceInstance.handler(seq, hex_data);
});
});
} }
async initCore () { async initCore () {

View File

@ -0,0 +1,24 @@
import "reflect-metadata";
import { Container, injectable } from "inversify";
import { NapCatCore } from "../..";
export const container = new Container();
export const ReceiverServiceRegistry = new Map<string, new (...args: any[]) => ServiceBase>();
export abstract class ServiceBase {
get core(): NapCatCore {
return container.get(NapCatCore);
}
abstract handler(seq: number, hex_data: string): Promise<void> | void;
}
export function ReceiveService(serviceName: string) {
return function <T extends new (...args: any[]) => ServiceBase>(constructor: T) {
injectable()(constructor);
ReceiverServiceRegistry.set(serviceName, constructor);
return constructor;
};
}

View File

@ -0,0 +1,8 @@
import { ReceiveService, ServiceBase } from "../packet/handler/serviceRegister";
// @ReceiveService('trpc.msg.olpush.OlPushService.MsgPush')
// export class OlPushService extends ServiceBase {
// async handler(seq: number, hex_data: string) {
// console.log(`OlPushService handler called with seq: ${seq} and data: ${hex_data}`);
// }
// }

View File

@ -16,6 +16,7 @@ const nodeModules = [...builtinModules, builtinModules.map((m) => `node:${m}`)].
const FrameworkBaseConfigPlugin: PluginOption[] = [ const FrameworkBaseConfigPlugin: PluginOption[] = [
autoIncludeTSPlugin({ autoIncludeTSPlugin({
entries: [ entries: [
{ entry: 'napcat.ts', dir: path.resolve(__dirname, '../napcat-core/protocol') },
{ entry: 'napcat.ts', dir: path.resolve(__dirname, '../napcat-onebot/action/test') } { entry: 'napcat.ts', dir: path.resolve(__dirname, '../napcat-onebot/action/test') }
] ]
}), }),

View File

@ -19,6 +19,7 @@ const ShellBaseConfigPlugin: PluginOption[] = [
react({ tsDecorators: true }), react({ tsDecorators: true }),
autoIncludeTSPlugin({ autoIncludeTSPlugin({
entries: [ entries: [
{ entry: 'napcat.ts', dir: path.resolve(__dirname, '../napcat-core/protocol') },
{ entry: 'napcat.ts', dir: path.resolve(__dirname, '../napcat-onebot/action/test') } { entry: 'napcat.ts', dir: path.resolve(__dirname, '../napcat-onebot/action/test') }
] ]
}), }),

View File

@ -12,6 +12,9 @@ export function autoIncludeTSPlugin(options) {
async buildStart() { async buildStart() {
tsFilesMap = {}; tsFilesMap = {};
for (const { entry, dir } of entries) { for (const { entry, dir } of entries) {
if (!tsFilesMap[entry]) {
tsFilesMap[entry] = [];
}
const fullDir = path.resolve(dir); const fullDir = path.resolve(dir);
const allTsFiles = await findTSFiles(fullDir); const allTsFiles = await findTSFiles(fullDir);
@ -29,7 +32,7 @@ export function autoIncludeTSPlugin(options) {
} }
}); });
tsFilesMap[entry] = validFiles; tsFilesMap[entry].push(...validFiles);
} }
}, },