Commit 4e1b5aa5 authored by nanahira's avatar nanahira

http route support

parent e16035a5
This diff is collapsed.
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
"jest": "^27.4.3", "jest": "^27.4.3",
"koishi": "^4.0.0-beta.5", "koishi": "^4.0.0-beta.5",
"prettier": "^2.4.1", "prettier": "^2.4.1",
"supertest": "^6.1.6",
"ts-jest": "^27.0.7", "ts-jest": "^27.0.7",
"typescript": "^4.5.2", "typescript": "^4.5.2",
"ws": "^8.2.3" "ws": "^8.2.3"
...@@ -50,6 +51,8 @@ ...@@ -50,6 +51,8 @@
"koishi": "^4.0.0-beta.5" "koishi": "^4.0.0-beta.5"
}, },
"dependencies": { "dependencies": {
"@types/koa": "^2.13.4",
"@types/koa__router": "^8.0.11",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"reflect-metadata": "^0.1.13", "reflect-metadata": "^0.1.13",
"schemastery": "^2.1.0", "schemastery": "^2.1.0",
......
...@@ -11,6 +11,7 @@ import { ...@@ -11,6 +11,7 @@ import {
KoishiDoRegister, KoishiDoRegister,
KoishiDoRegisterKeys, KoishiDoRegisterKeys,
KoishiOnContextScope, KoishiOnContextScope,
KoishiRouteDef,
KoishiServiceInjectSym, KoishiServiceInjectSym,
KoishiServiceInjectSymKeys, KoishiServiceInjectSymKeys,
KoishiServiceProvideSym, KoishiServiceProvideSym,
...@@ -33,11 +34,27 @@ export const DoRegister = (value: DoRegisterConfig): MethodDecorator => ...@@ -33,11 +34,27 @@ export const DoRegister = (value: DoRegisterConfig): MethodDecorator =>
export const UseMiddleware = (prepend?: boolean): MethodDecorator => export const UseMiddleware = (prepend?: boolean): MethodDecorator =>
DoRegister(GenerateMappingStruct('middleware', prepend)); DoRegister(GenerateMappingStruct('middleware', prepend));
export const UseEvent = (name: EventName, prepend?: boolean): MethodDecorator => export const UseEvent = (name: EventName, prepend?: boolean): MethodDecorator =>
DoRegister(GenerateMappingStruct('onevent', { name, prepend })); DoRegister(GenerateMappingStruct('onevent', { name, prepend }));
export const UsePlugin = (): MethodDecorator => export const UsePlugin = (): MethodDecorator =>
DoRegister(GenerateMappingStruct('plugin')); DoRegister(GenerateMappingStruct('plugin'));
export const UseHttpRoute = (routeDef: KoishiRouteDef): MethodDecorator =>
DoRegister(GenerateMappingStruct('route', routeDef));
export const Get = (path: string) => UseHttpRoute({ path, method: 'get' });
export const Post = (path: string) => UseHttpRoute({ path, method: 'post' });
export const Put = (path: string) => UseHttpRoute({ path, method: 'put' });
export const Delete = (path: string) =>
UseHttpRoute({ path, method: 'delete' });
export const Patch = (path: string) => UseHttpRoute({ path, method: 'patch' });
export const Options = (path: string) =>
UseHttpRoute({ path, method: 'options' });
export const Head = (path: string) => UseHttpRoute({ path, method: 'head' });
export const All = (path: string) => UseHttpRoute({ path, method: 'all' });
export function UseCommand<D extends string>( export function UseCommand<D extends string>(
def: D, def: D,
config?: Command.Config, config?: Command.Config,
......
...@@ -13,6 +13,8 @@ import { ...@@ -13,6 +13,8 @@ import {
User, User,
} from 'koishi'; } from 'koishi';
import { KoishiPluginRegistrationOptions, PluginClass } from '../register'; import { KoishiPluginRegistrationOptions, PluginClass } from '../register';
import type { DefaultContext, DefaultState, ParameterizedContext } from 'koa';
import type { RouterParamContext } from '@koa/router';
export interface Type<T = any> extends Function { export interface Type<T = any> extends Function {
new (...args: any[]): T; new (...args: any[]): T;
...@@ -87,11 +89,12 @@ export interface DoRegisterConfigDataMap { ...@@ -87,11 +89,12 @@ export interface DoRegisterConfigDataMap {
onevent: EventNameAndPrepend; onevent: EventNameAndPrepend;
plugin: never; plugin: never;
command: CommandRegisterConfig; command: CommandRegisterConfig;
route: KoishiRouteDef;
} }
export interface MappingStruct< export interface MappingStruct<
T extends Record<string | number | symbol, any>, T extends Record<string | number | symbol, any>,
K extends keyof T K extends keyof T,
> { > {
type: K; type: K;
data?: T[K]; data?: T[K];
...@@ -99,7 +102,7 @@ export interface MappingStruct< ...@@ -99,7 +102,7 @@ export interface MappingStruct<
export function GenerateMappingStruct< export function GenerateMappingStruct<
T extends Record<string | number | symbol, any>, T extends Record<string | number | symbol, any>,
K extends keyof T K extends keyof T,
>(type: K, data?: T[K]): MappingStruct<T, K> { >(type: K, data?: T[K]): MappingStruct<T, K> {
return { return {
type, type,
...@@ -108,7 +111,7 @@ export function GenerateMappingStruct< ...@@ -108,7 +111,7 @@ export function GenerateMappingStruct<
} }
export type DoRegisterConfig< export type DoRegisterConfig<
K extends keyof DoRegisterConfigDataMap = keyof DoRegisterConfigDataMap K extends keyof DoRegisterConfigDataMap = keyof DoRegisterConfigDataMap,
> = MappingStruct<DoRegisterConfigDataMap, K>; > = MappingStruct<DoRegisterConfigDataMap, K>;
// Command stuff // Command stuff
...@@ -138,7 +141,7 @@ export interface CommandPutConfigMap { ...@@ -138,7 +141,7 @@ export interface CommandPutConfigMap {
} }
export type CommandPutConfig< export type CommandPutConfig<
K extends keyof CommandPutConfigMap = keyof CommandPutConfigMap K extends keyof CommandPutConfigMap = keyof CommandPutConfigMap,
> = MappingStruct<CommandPutConfigMap, K>; > = MappingStruct<CommandPutConfigMap, K>;
export type CommandDefinitionFun = (cmd: Command) => Command; export type CommandDefinitionFun = (cmd: Command) => Command;
...@@ -155,3 +158,22 @@ export interface ProvideOptions { ...@@ -155,3 +158,22 @@ export interface ProvideOptions {
export interface ProvideDefinition extends ProvideOptions { export interface ProvideDefinition extends ProvideOptions {
serviceName: keyof Context.Services; serviceName: keyof Context.Services;
} }
export interface KoishiRouteDef {
path: string;
method:
| 'get'
| 'post'
| 'put'
| 'delete'
| 'patch'
| 'options'
| 'head'
| 'all';
}
export type KoaContext = ParameterizedContext<
DefaultState,
DefaultContext & RouterParamContext<DefaultState, DefaultContext>,
any
>;
...@@ -285,6 +285,15 @@ export function KoishiPlugin<T = any>( ...@@ -285,6 +285,15 @@ export function KoishiPlugin<T = any>(
}); });
} }
break; break;
case 'route':
const { data: routeData } = regData as DoRegisterConfig<'route'>;
const realPath = routeData.path.startsWith('/')
? routeData.path
: `/${routeData.path}`;
baseContext.router[routeData.method](realPath, (ctx, next) =>
this[methodKey](ctx, next),
);
break;
default: default:
throw new Error(`Unknown operation type ${regData.type}`); throw new Error(`Unknown operation type ${regData.type}`);
} }
......
import { App } from 'koishi';
import { KoishiPlugin } from '../src/register';
import { Get } from '../src/decorators';
import { KoaContext } from '../src/def';
import request from 'supertest';
@KoishiPlugin()
class MyPlugin {
@Get('ping')
async ping(ctx: KoaContext) {
ctx.status = 233;
ctx.body = 'pong';
}
}
describe('Http Routes', () => {
let app: App;
beforeEach(() => {
app = new App();
});
it('should be able to get a route', async () => {
app.plugin(MyPlugin);
await app.start();
return request(app._httpServer).get('/ping').expect(233).expect('pong');
});
});
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