Commit d2efb2e2 authored by nanahira's avatar nanahira

fix injection issue

parent 6c592e61
......@@ -14,7 +14,7 @@
"@types/ws": "^8.5.3",
"koa": "^2.13.4",
"koa-bodyparser": "^4.3.0",
"koishi-thirdeye": "^11.0.2",
"koishi-thirdeye": "^11.0.4",
"lodash": "^4.17.21",
"typed-reflector": "^1.0.11",
"ws": "^8.7.0"
......@@ -2844,9 +2844,9 @@
}
},
"node_modules/cordis-decorators": {
"version": "1.0.16",
"resolved": "https://registry.npmjs.org/cordis-decorators/-/cordis-decorators-1.0.16.tgz",
"integrity": "sha512-S5XULywHemcob+KqSItv3kAo1mNRjbDchmfrKJALYs3wqzp4q4PPZRQftbW5SVuLReSis14hgwTHbgoXNGJVEA==",
"version": "1.0.17",
"resolved": "https://registry.npmjs.org/cordis-decorators/-/cordis-decorators-1.0.17.tgz",
"integrity": "sha512-Y3FB4Aa1irDRQOGSLht3Dtwovza94KFjYCst6HrtPQE9nWzTKa3vUAZp0kIOBCaY/G/fNgAAd3O6TA27jgcouA==",
"dependencies": {
"lodash": "^4.17.21",
"mustache": "^4.2.0",
......@@ -5720,14 +5720,14 @@
}
},
"node_modules/koishi-thirdeye": {
"version": "11.0.2",
"resolved": "https://registry.npmjs.org/koishi-thirdeye/-/koishi-thirdeye-11.0.2.tgz",
"integrity": "sha512-0Mk1Nb3OwAaONgVE5YIFpHI4QHGQlQlfMC9r2Am8+FKKyxL0oqivg9eiJJj7eopTpZ8c8WBPdoFlJl9MEDs4PA==",
"version": "11.0.4",
"resolved": "https://registry.npmjs.org/koishi-thirdeye/-/koishi-thirdeye-11.0.4.tgz",
"integrity": "sha512-R/p+YePSjnBsZalaJy+U9gkvJae2wiOn7rZeg+mFU/gEtxQ38roh7dyIaB+IWXYnc7k4+6VqEa52DHqPZtxh0Q==",
"dependencies": {
"lodash": "^4.17.21",
"minato-decorators": "^2.0.8",
"rxjs": "^7.5.6",
"satori-decorators": "^1.0.8"
"satori-decorators": "^1.0.10"
},
"peerDependencies": {
"koishi": "^4.8.1",
......@@ -7048,13 +7048,13 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"node_modules/satori-decorators": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/satori-decorators/-/satori-decorators-1.0.8.tgz",
"integrity": "sha512-9AbhozP7pRc82mtDydOeiQSBfhnKBjM7bzk3sh8TKbI8EWh+58cykpXwYNMKUya8eRkvs3jlKtAdoArBzuOPFw==",
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/satori-decorators/-/satori-decorators-1.0.10.tgz",
"integrity": "sha512-kIHEFq8FGWEq7jn8zglEeD3qV6fSS8phpMJVuJ0qWVY1M+r9wKfBSQw8zvE2f6DECIFH0xDii0aIepaOgfLCUA==",
"dependencies": {
"@types/koa": "^2.13.5",
"@types/koa__router": "^8.0.11",
"cordis-decorators": "^1.0.16",
"cordis-decorators": "^1.0.17",
"lodash": "^4.17.21"
},
"peerDependencies": {
......@@ -10491,9 +10491,9 @@
}
},
"cordis-decorators": {
"version": "1.0.16",
"resolved": "https://registry.npmjs.org/cordis-decorators/-/cordis-decorators-1.0.16.tgz",
"integrity": "sha512-S5XULywHemcob+KqSItv3kAo1mNRjbDchmfrKJALYs3wqzp4q4PPZRQftbW5SVuLReSis14hgwTHbgoXNGJVEA==",
"version": "1.0.17",
"resolved": "https://registry.npmjs.org/cordis-decorators/-/cordis-decorators-1.0.17.tgz",
"integrity": "sha512-Y3FB4Aa1irDRQOGSLht3Dtwovza94KFjYCst6HrtPQE9nWzTKa3vUAZp0kIOBCaY/G/fNgAAd3O6TA27jgcouA==",
"requires": {
"lodash": "^4.17.21",
"mustache": "^4.2.0",
......@@ -12694,14 +12694,14 @@
}
},
"koishi-thirdeye": {
"version": "11.0.2",
"resolved": "https://registry.npmjs.org/koishi-thirdeye/-/koishi-thirdeye-11.0.2.tgz",
"integrity": "sha512-0Mk1Nb3OwAaONgVE5YIFpHI4QHGQlQlfMC9r2Am8+FKKyxL0oqivg9eiJJj7eopTpZ8c8WBPdoFlJl9MEDs4PA==",
"version": "11.0.4",
"resolved": "https://registry.npmjs.org/koishi-thirdeye/-/koishi-thirdeye-11.0.4.tgz",
"integrity": "sha512-R/p+YePSjnBsZalaJy+U9gkvJae2wiOn7rZeg+mFU/gEtxQ38roh7dyIaB+IWXYnc7k4+6VqEa52DHqPZtxh0Q==",
"requires": {
"lodash": "^4.17.21",
"minato-decorators": "^2.0.8",
"rxjs": "^7.5.6",
"satori-decorators": "^1.0.8"
"satori-decorators": "^1.0.10"
}
},
"leven": {
......@@ -13704,13 +13704,13 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"satori-decorators": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/satori-decorators/-/satori-decorators-1.0.8.tgz",
"integrity": "sha512-9AbhozP7pRc82mtDydOeiQSBfhnKBjM7bzk3sh8TKbI8EWh+58cykpXwYNMKUya8eRkvs3jlKtAdoArBzuOPFw==",
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/satori-decorators/-/satori-decorators-1.0.10.tgz",
"integrity": "sha512-kIHEFq8FGWEq7jn8zglEeD3qV6fSS8phpMJVuJ0qWVY1M+r9wKfBSQw8zvE2f6DECIFH0xDii0aIepaOgfLCUA==",
"requires": {
"@types/koa": "^2.13.5",
"@types/koa__router": "^8.0.11",
"cordis-decorators": "^1.0.16",
"cordis-decorators": "^1.0.17",
"lodash": "^4.17.21"
}
},
......
......@@ -52,7 +52,7 @@ const koishiContextProvider: Provider<Context> = {
KoishiInterceptorManagerService,
KoishiExceptionHandlerService,
],
exports: [KoishiService, koishiContextProvider],
exports: [koishiContextProvider],
})
export class KoishiModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
......
......@@ -4,6 +4,7 @@ import {
Injectable,
OnModuleDestroy,
OnModuleInit,
Scope,
} from '@nestjs/common';
import {
KoishiCommandInterceptorRegistration,
......@@ -21,7 +22,9 @@ import { KoishiNestRouter } from './utility/koa-router';
import './utility/koishi.workarounds';
import './utility/koishi.declares';
@Injectable()
@Injectable({
scope: Scope.DEFAULT,
})
export class KoishiService
extends Context
implements OnModuleInit, OnModuleDestroy
......@@ -74,15 +77,18 @@ export class KoishiService
}
async onModuleInit() {
if (this.forkedProvider) {
return;
}
await this.setHttpServer();
this.metascan.preRegisterContext(this.any());
this.metascan.preRegisterContext(this);
if (this.koishiModuleOptions.usePlugins) {
for (const pluginDef of this.koishiModuleOptions.usePlugins) {
this.plugin(pluginDef.plugin, pluginDef.options);
}
}
await this.metascan.registerContext(this.any());
return this.start();
await this.metascan.registerContext(this);
await this.start();
}
async onModuleDestroy() {
......@@ -95,4 +101,11 @@ export class KoishiService
) {
return this.metascan.addInterceptors(command, interceptorDefs);
}
override extend(meta = {}): this {
return super.extend({
...meta,
forkedProvider: true,
});
}
}
......@@ -24,7 +24,10 @@ export class KoishiInjectionService {
getInjectContext(inquerier: string | any) {
const token =
typeof inquerier === 'string' ? inquerier : inquerier.constructor;
typeof inquerier === 'string' ? inquerier : inquerier?.constructor;
if (!token) {
return this.koishi;
}
const interceptors = this.metaFetcher.getMetadataArray(
KoishiCommandInterceptorDef,
token,
......
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Inject, Injectable, NestMiddleware } from '@nestjs/common';
import { NextFunction } from 'express';
import { KoishiService } from '../koishi.service';
import { IncomingMessage, ServerResponse } from 'http';
......
import { KoishiCommandInterceptorRegistration } from './koishi.interfaces';
import { IntercepterManagerService } from './koishi.workarounds';
interface ContextInterceptorMeta {
interface ContextNestMeta {
forkedProvider?: boolean;
interceptors: KoishiCommandInterceptorRegistration[];
}
......@@ -9,11 +10,11 @@ declare module 'koishi' {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace Context {
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface Meta extends ContextInterceptorMeta {}
interface Meta extends ContextNestMeta {}
}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface Context extends ContextInterceptorMeta {
interface Context extends ContextNestMeta {
$interceptorManager: IntercepterManagerService;
withInterceptors(
interceptors: KoishiCommandInterceptorRegistration[],
......
import { Command, Commander, Context } from 'koishi';
import { KoishiService } from '../koishi.service';
import { KoishiCommandInterceptorRegistration } from './koishi.interfaces';
import { StarterPlugin } from 'koishi-thirdeye/dist/src/registrar';
import { Caller, DefinePlugin, Internal, Provide } from 'koishi-thirdeye';
// command interceptor supports
const oldCommand = Commander.prototype.command;
......@@ -14,22 +16,19 @@ Commander.prototype.command = function (this: Commander, ...args: any[]) {
return command;
};
export class IntercepterManagerService {
constructor(private ctx: Context) {}
protected get caller(): Context {
return this[Context.current] || this.ctx;
}
static methods = ['withInterceptors'];
@Provide('$interceptorManager', { internal: true })
@DefinePlugin()
export class IntercepterManagerService extends StarterPlugin() {
@Caller()
caller: Context;
@Internal()
withInterceptors(
interceptors: KoishiCommandInterceptorRegistration[],
): Context {
const ctx = this.caller;
return ctx['fork']({
return ctx.extend({
interceptors: [...(ctx.interceptors || []), ...interceptors],
});
}
}
Context.service('$interceptorManager', IntercepterManagerService);
......@@ -3,14 +3,13 @@ import { KoishiWsAdapter } from '../src/koishi.ws-adapter';
import http from 'http';
import request from 'supertest';
import { Context, Events, Session } from 'koishi';
import { testingModule } from './utility/testing-module';
import { KoishiTestService, testingModule } from './utility/testing-module';
import { NestExpressApplication } from '@nestjs/platform-express';
type EventName = keyof Events;
describe('Koishi in Nest.js', () => {
let app: NestExpressApplication;
let koishiApp: KoishiService;
let koishiApp: Context;
beforeEach(async () => {
const moduleFixture = await testingModule();
......@@ -89,6 +88,45 @@ describe('Koishi in Nest.js', () => {
expect(methodCtx.filter(wrongSession2)).toBe(false);
});
it('should inject correct context', () => {
const testService = app.get(KoishiTestService);
expect(testService.ctx1).toBeDefined();
expect(testService.ctx2).toBeDefined();
expect(testService.ctx1.filter({ platform: 'discord' } as Session)).toBe(
true,
);
expect(testService.ctx1.filter({ platform: 'telegram' } as Session)).toBe(
false,
);
expect(testService.ctx2.filter({ platform: 'telegram' } as Session)).toBe(
false,
);
expect(
testService.ctx1.filter({
platform: 'discord',
userId: '111111111',
} as Session),
).toBe(true);
expect(
testService.ctx2.filter({
platform: 'discord',
userId: '111111111',
} as Session),
).toBe(true);
expect(
testService.ctx1.filter({
platform: 'discord',
userId: '111111112',
} as Session),
).toBe(true);
expect(
testService.ctx2.filter({
platform: 'discord',
userId: '111111112',
} as Session),
).toBe(false);
});
it('should handle command error', () => {
const command = koishiApp.command('boo');
expect(command).toBeDefined();
......
import { Injectable, NotFoundException } from '@nestjs/common';
import { KoishiCommandInterceptor } from '../../src/utility/koishi.interfaces';
import { Argv } from 'koishi';
import { Argv, Context } from 'koishi';
import {
CommandUsage,
OnGuild,
......@@ -12,10 +12,12 @@ import {
} from 'koishi-thirdeye';
import {
CommandInterceptors,
InjectContextUser,
UsingService,
} from '../../src/utility/koishi.decorators';
import { Test } from '@nestjs/testing';
import { KoishiModule } from '../../src/koishi.module';
import { InjectContext } from '../../src/utility/koishi.decorators';
@Injectable()
class MooInterceptor implements KoishiCommandInterceptor {
......@@ -49,16 +51,21 @@ class PeeInterceptor implements KoishiCommandInterceptor {
@OnPlatform('discord')
@Injectable()
@CommandInterceptors(PooInterceptor)
class KoishiTestService {
export class KoishiTestService {
constructor(
@InjectContext() public ctx1: Context,
@InjectContextUser('111111111') public ctx2: Context,
) {}
@OnGuild('1111111111')
@UseCommand('echo', 'hi')
@CommandUsage('foo')
async onEcho(@PutOption('content', '-c <content:string>') content: string) {
async onEcho(@PutOption('content', '-c <content>') content: string) {
return `bot: ${content}`;
}
@UseCommand('boo')
async onBoo(@PutOption('content', '-c <content:string>') content: string) {
async onBoo(@PutOption('content', '-c <content>') content: string) {
throw new NotFoundException(`boo: ${content}`);
}
......@@ -107,5 +114,6 @@ export function testingModule() {
PooInterceptor,
PeeInterceptor,
],
exports: [KoishiTestService],
}).compile();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment