Commit a9dd493e authored by nanahira's avatar nanahira

bump koishi

parent 99b28e90
This diff is collapsed.
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
"peerDependencies": { "peerDependencies": {
"@nestjs/common": "^8.2.6", "@nestjs/common": "^8.2.6",
"@nestjs/core": "^8.2.6", "@nestjs/core": "^8.2.6",
"koishi": "^4.6.0", "koishi": "^4.7.1",
"reflect-metadata": "^0.1.13", "reflect-metadata": "^0.1.13",
"rxjs": "^7.5.4" "rxjs": "^7.5.4"
}, },
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
"eslint-plugin-prettier": "^3.4.1", "eslint-plugin-prettier": "^3.4.1",
"express": "^4.17.1", "express": "^4.17.1",
"jest": "^27.4.4", "jest": "^27.4.4",
"koishi": "4.6.0", "koishi": "4.7.1",
"prettier": "^2.4.1", "prettier": "^2.4.1",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"supertest": "^6.1.6", "supertest": "^6.1.6",
...@@ -64,13 +64,13 @@ ...@@ -64,13 +64,13 @@
"dependencies": { "dependencies": {
"@nestjs/platform-ws": "^8.1.2", "@nestjs/platform-ws": "^8.1.2",
"@nestjs/websockets": "^8.1.2", "@nestjs/websockets": "^8.1.2",
"@types/ws": "^8.2.0", "@types/ws": "^8.5.3",
"koa": "^2.13.3", "koa": "^2.13.4",
"koa-bodyparser": "^4.3.0", "koa-bodyparser": "^4.3.0",
"koishi-decorators": "^2.0.0", "koishi-decorators": "^2.1.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"typed-reflector": "^1.0.10", "typed-reflector": "^1.0.10",
"ws": "^8.2.3" "ws": "^8.6.0"
}, },
"jest": { "jest": {
"moduleFileExtensions": [ "moduleFileExtensions": [
......
...@@ -9,7 +9,9 @@ describe('KoishiExceptionHandlerService', () => { ...@@ -9,7 +9,9 @@ describe('KoishiExceptionHandlerService', () => {
providers: [KoishiExceptionHandlerService], providers: [KoishiExceptionHandlerService],
}).compile(); }).compile();
service = module.get<KoishiExceptionHandlerService>(KoishiExceptionHandlerService); service = module.get<KoishiExceptionHandlerService>(
KoishiExceptionHandlerService,
);
}); });
it('should be defined', () => { it('should be defined', () => {
......
import { App, Argv, Command, Context, Router } from 'koishi'; import { App, Command, Context, Plugin } from 'koishi';
import { import {
Inject, Inject,
Injectable, Injectable,
OnApplicationBootstrap,
OnModuleDestroy, OnModuleDestroy,
OnModuleInit, OnModuleInit,
} from '@nestjs/common'; } from '@nestjs/common';
...@@ -20,16 +19,15 @@ import { KoishiHttpDiscoveryService } from './koishi-http-discovery/koishi-http- ...@@ -20,16 +19,15 @@ import { KoishiHttpDiscoveryService } from './koishi-http-discovery/koishi-http-
import { Filter, ReplacedContext } from './utility/replaced-context'; import { Filter, ReplacedContext } from './utility/replaced-context';
import { applySelector } from 'koishi-decorators'; import { applySelector } from 'koishi-decorators';
import WebSocket from 'ws'; import WebSocket from 'ws';
import { KoishiNestRouter } from './utility/koa-router';
// eslint-disable-next-line @typescript-eslint/no-empty-function import './utility/commander-with-interceptor';
Router.prepare = () => {};
@Injectable() @Injectable()
export class KoishiService export class KoishiService
extends App extends App
implements OnModuleInit, OnModuleDestroy implements OnModuleInit, OnModuleDestroy
{ {
private readonly globalInterceptors: KoishiCommandInterceptorRegistration[]; private readonly _interceptors: KoishiCommandInterceptorRegistration[];
constructor( constructor(
@Inject(KOISHI_MODULE_OPTIONS) @Inject(KOISHI_MODULE_OPTIONS)
private readonly koishiModuleOptions: KoishiModuleOptions, private readonly koishiModuleOptions: KoishiModuleOptions,
...@@ -42,8 +40,8 @@ export class KoishiService ...@@ -42,8 +40,8 @@ export class KoishiService
port: 0, port: 0,
}); });
this.baseDir ??= process.cwd(); this.baseDir ??= process.cwd();
this.globalInterceptors = this.koishiModuleOptions.globalInterceptors || []; this._interceptors = this.koishiModuleOptions.globalInterceptors || [];
this.router = new Router(); this.router = new KoishiNestRouter();
this._nestKoaTmpInstance.use((ctx, next) => { this._nestKoaTmpInstance.use((ctx, next) => {
ctx.request.ip = ctx.req[KoishiIpSym]; ctx.request.ip = ctx.req[KoishiIpSym];
return next(); return next();
...@@ -103,58 +101,20 @@ export class KoishiService ...@@ -103,58 +101,20 @@ export class KoishiService
private cloneContext( private cloneContext(
filter: Filter, filter: Filter,
interceptors: KoishiCommandInterceptorRegistration[] = [], plugin: Plugin,
interceptors: KoishiCommandInterceptorRegistration[],
): Context { ): Context {
return new ReplacedContext(filter, this, null, [ return new ReplacedContext(filter, this, plugin, interceptors);
...this.globalInterceptors,
...interceptors,
]);
} }
withInterceptors(interceptors: KoishiCommandInterceptorRegistration[]) { withInterceptors(interceptors: KoishiCommandInterceptorRegistration[]) {
return this.cloneContext(() => true, interceptors); return this.cloneContext(this.filter, this.plugin, [
} ...this._interceptors,
...interceptors,
override any() { ]);
return this.cloneContext(() => true);
}
override never() {
return this.cloneContext(() => false);
}
override union(arg: Filter | Context) {
const filter = typeof arg === 'function' ? arg : arg.filter;
return this.cloneContext((s) => this.filter(s) || filter(s));
}
override intersect(arg: Filter | Context) {
const filter = typeof arg === 'function' ? arg : arg.filter;
return this.cloneContext((s) => this.filter(s) && filter(s));
}
override except(arg: Filter | Context) {
const filter = typeof arg === 'function' ? arg : arg.filter;
return this.cloneContext((s) => this.filter(s) && !filter(s));
} }
override command<D extends string>( override fork(filter: Filter, _plugin: Plugin) {
def: D, return this.cloneContext(filter, _plugin, this._interceptors);
config?: Command.Config,
): Command<never, never, Argv.ArgumentType<D>>;
override command<D extends string>(
def: D,
desc: string,
config?: Command.Config,
): Command<never, never, Argv.ArgumentType<D>>;
override command(
def: string,
...args: [Command.Config?] | [string, Command.Config?]
) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const cmd = super.command(def, ...args);
this.addInterceptors(cmd, this.globalInterceptors);
return cmd;
} }
} }
...@@ -80,7 +80,7 @@ export class KoishiMetascanService { ...@@ -80,7 +80,7 @@ export class KoishiMetascanService {
ctx: Context, ctx: Context,
instance: any, instance: any,
property: string, property: string,
name: keyof Context.Services, name: keyof Context,
) { ) {
Object.defineProperty(instance, property, { Object.defineProperty(instance, property, {
enumerable: true, enumerable: true,
...@@ -89,6 +89,8 @@ export class KoishiMetascanService { ...@@ -89,6 +89,8 @@ export class KoishiMetascanService {
return ctx[name]; return ctx[name];
}, },
set(val: any) { set(val: any) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
ctx[name] = val; ctx[name] = val;
}, },
}); });
...@@ -114,7 +116,7 @@ export class KoishiMetascanService { ...@@ -114,7 +116,7 @@ export class KoishiMetascanService {
return; return;
} }
for (const property of properties) { for (const property of properties) {
const serviceName: keyof Context.Services = Reflect.getMetadata( const serviceName: keyof Context = Reflect.getMetadata(
KoishiServiceWireProperty, KoishiServiceWireProperty,
instanceClass, instanceClass,
property, property,
......
import { Command, Commander } from 'koishi';
import { ReplacedContext } from './replaced-context';
import { KoishiService } from '../koishi.service';
const oldCommand = Commander.prototype.command;
Commander.prototype.command = function (this: Commander, ...args: any[]) {
const command: Command = oldCommand.call(this, ...args);
const ctx = this.caller;
const interceptors = (ctx as ReplacedContext)._interceptors;
if (interceptors?.length) {
(ctx.app as KoishiService).addInterceptors(command, interceptors);
}
return command;
};
import KoaRouter from '@koa/router';
import { Context, MaybeArray, remove, WebSocketLayer } from 'koishi';
import { IncomingMessage } from 'http';
import WebSocket from 'ws';
export class KoishiNestRouter extends KoaRouter {
wsStack: WebSocketLayer[] = [];
/**
* hack into router methods to make sure that koa middlewares are disposable
*/
override register(...args: Parameters<KoaRouter['register']>) {
const layer = super.register(...args);
const context: Context = this[Context.current];
context?.state.disposables.push(() => {
remove(this.stack, layer);
});
return layer;
}
ws(
path: MaybeArray<string | RegExp>,
callback?: (socket: WebSocket, request: IncomingMessage) => void,
) {
const layer = new WebSocketLayer(this, path, callback);
this.wsStack.push(layer);
const context: Context = this[Context.current];
context?.state.disposables.push(() => layer.close());
return layer;
}
}
...@@ -15,7 +15,7 @@ export const KoishiServiceProvideSym = 'KoishiServiceProvideSym'; ...@@ -15,7 +15,7 @@ export const KoishiServiceProvideSym = 'KoishiServiceProvideSym';
// metadata map // metadata map
export interface MetadataArrayMap { export interface MetadataArrayMap {
KoishiServiceProvideSym: keyof Context.Services; KoishiServiceProvideSym: keyof Context;
KoishiCommandInterceptorDef: KoishiCommandInterceptorRegistration; KoishiCommandInterceptorDef: KoishiCommandInterceptorRegistration;
} }
......
...@@ -98,9 +98,7 @@ export { PluginDef } from 'koishi-decorators'; ...@@ -98,9 +98,7 @@ export { PluginDef } from 'koishi-decorators';
// Service // Service
export function WireContextService( export function WireContextService(name?: keyof Context): PropertyDecorator {
name?: keyof Context.Services,
): PropertyDecorator {
return (obj, key) => { return (obj, key) => {
const objClass = obj.constructor; const objClass = obj.constructor;
const properties: string[] = const properties: string[] =
...@@ -116,9 +114,7 @@ export function WireContextService( ...@@ -116,9 +114,7 @@ export function WireContextService(
}; };
} }
export function ProvideContextService( export function ProvideContextService(name: keyof Context): ClassDecorator {
name: keyof Context.Services,
): ClassDecorator {
Context.service(name); Context.service(name);
return AppendMetadata(KoishiServiceProvideSym, name); return AppendMetadata(KoishiServiceProvideSym, name);
} }
......
...@@ -2,6 +2,7 @@ import { ModuleMetadata, Provider, Type } from '@nestjs/common'; ...@@ -2,6 +2,7 @@ import { ModuleMetadata, Provider, Type } from '@nestjs/common';
import { App, Channel, Command, User } from 'koishi'; import { App, Channel, Command, User } from 'koishi';
import { MetadataArrayMap, MetadataMap } from './koishi.constants'; import { MetadataArrayMap, MetadataMap } from './koishi.constants';
import { ContextSelector, PluginDefinition } from 'koishi-decorators'; import { ContextSelector, PluginDefinition } from 'koishi-decorators';
export * from 'koishi-decorators/dist/src/def/interfaces'; export * from 'koishi-decorators/dist/src/def/interfaces';
export interface KoishiModuleSelection extends ContextSelector { export interface KoishiModuleSelection extends ContextSelector {
......
import { Argv, Command, Context, Plugin, Session } from 'koishi'; import { Context, Plugin, Session } from 'koishi';
import { KoishiService } from '../koishi.service'; import { KoishiService } from '../koishi.service';
import { KoishiCommandInterceptorRegistration } from './koishi.interfaces'; import { KoishiCommandInterceptorRegistration } from './koishi.interfaces';
...@@ -16,58 +16,20 @@ export class ReplacedContext extends Context { ...@@ -16,58 +16,20 @@ export class ReplacedContext extends Context {
private cloneContext( private cloneContext(
filter: Filter, filter: Filter,
interceptors: KoishiCommandInterceptorRegistration[] = [], plugin: Plugin,
interceptors: KoishiCommandInterceptorRegistration[],
): Context { ): Context {
return new ReplacedContext(filter, this._app, this.__plugin, [ return new ReplacedContext(filter, this._app, plugin, interceptors);
...this._interceptors,
...interceptors,
]);
} }
withInterceptors(interceptors: KoishiCommandInterceptorRegistration[]) { withInterceptors(interceptors: KoishiCommandInterceptorRegistration[]) {
return this.cloneContext(this.filter, interceptors); return this.cloneContext(this.filter, this.plugin, [
} ...this._interceptors,
...interceptors,
override any() { ]);
return this.cloneContext(() => true);
}
override never() {
return this.cloneContext(() => false);
}
override union(arg: Filter | Context) {
const filter = typeof arg === 'function' ? arg : arg.filter;
return this.cloneContext((s) => this.filter(s) || filter(s));
}
override intersect(arg: Filter | Context) {
const filter = typeof arg === 'function' ? arg : arg.filter;
return this.cloneContext((s) => this.filter(s) && filter(s));
}
override except(arg: Filter | Context) {
const filter = typeof arg === 'function' ? arg : arg.filter;
return this.cloneContext((s) => this.filter(s) && !filter(s));
} }
override command<D extends string>( override fork(filter: Filter, _plugin: Plugin) {
def: D, return this.cloneContext(filter, _plugin, this._interceptors);
config?: Command.Config,
): Command<never, never, Argv.ArgumentType<D>>;
override command<D extends string>(
def: D,
desc: string,
config?: Command.Config,
): Command<never, never, Argv.ArgumentType<D>>;
override command(
def: string,
...args: [Command.Config?] | [string, Command.Config?]
) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const cmd = super.command(def, ...args);
this._app.addInterceptors(cmd, this._interceptors);
return cmd;
} }
} }
...@@ -6,7 +6,6 @@ import { KoishiService } from '../src/koishi.service'; ...@@ -6,7 +6,6 @@ import { KoishiService } from '../src/koishi.service';
import { testingModule } from './utility/testing-module'; import { testingModule } from './utility/testing-module';
import { KoishiWsAdapter } from '../src/koishi.ws-adapter'; import { KoishiWsAdapter } from '../src/koishi.ws-adapter';
import http from 'http'; import http from 'http';
import request from 'supertest';
describe('Koishi module in Fastify adapter', () => { describe('Koishi module in Fastify adapter', () => {
let app: NestFastifyApplication; let app: NestFastifyApplication;
......
...@@ -79,7 +79,7 @@ describe('Koishi in Nest.js', () => { ...@@ -79,7 +79,7 @@ describe('Koishi in Nest.js', () => {
platform: 'telegram', platform: 'telegram',
} as Session; } as Session;
const methodCtx = command.context; const methodCtx = command.ctx;
expect(methodCtx.filter(correctSession)).toBe(true); expect(methodCtx.filter(correctSession)).toBe(true);
expect(methodCtx.filter(wrongSession1)).toBe(false); expect(methodCtx.filter(wrongSession1)).toBe(false);
expect(methodCtx.filter(wrongSession2)).toBe(false); expect(methodCtx.filter(wrongSession2)).toBe(false);
......
import { Injectable, NotFoundException } from '@nestjs/common'; import { Injectable, NotFoundException } from '@nestjs/common';
import { KoishiCommandInterceptor } from '../../src/utility/koishi.interfaces'; import { KoishiCommandInterceptor } from '../../src/utility/koishi.interfaces';
import { Argv, Context } from 'koishi'; import { Argv } from 'koishi';
import { import {
CommandUsage, CommandUsage,
OnGuild, OnGuild,
OnPlatform, OnPlatform,
PluginDef,
PutOption, PutOption,
UseCommand, UseCommand,
} from 'koishi-decorators'; } from 'koishi-decorators';
......
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