Commit 4e1b5aa5 authored by nanahira's avatar nanahira

http route support

parent e16035a5
This diff is collapsed.
......@@ -42,6 +42,7 @@
"jest": "^27.4.3",
"koishi": "^4.0.0-beta.5",
"prettier": "^2.4.1",
"supertest": "^6.1.6",
"ts-jest": "^27.0.7",
"typescript": "^4.5.2",
"ws": "^8.2.3"
......@@ -50,6 +51,8 @@
"koishi": "^4.0.0-beta.5"
},
"dependencies": {
"@types/koa": "^2.13.4",
"@types/koa__router": "^8.0.11",
"lodash": "^4.17.21",
"reflect-metadata": "^0.1.13",
"schemastery": "^2.1.0",
......
......@@ -11,6 +11,7 @@ import {
KoishiDoRegister,
KoishiDoRegisterKeys,
KoishiOnContextScope,
KoishiRouteDef,
KoishiServiceInjectSym,
KoishiServiceInjectSymKeys,
KoishiServiceProvideSym,
......@@ -33,11 +34,27 @@ export const DoRegister = (value: DoRegisterConfig): MethodDecorator =>
export const UseMiddleware = (prepend?: boolean): MethodDecorator =>
DoRegister(GenerateMappingStruct('middleware', prepend));
export const UseEvent = (name: EventName, prepend?: boolean): MethodDecorator =>
DoRegister(GenerateMappingStruct('onevent', { name, prepend }));
export const UsePlugin = (): MethodDecorator =>
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>(
def: D,
config?: Command.Config,
......
......@@ -13,6 +13,8 @@ import {
User,
} from 'koishi';
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 {
new (...args: any[]): T;
......@@ -87,11 +89,12 @@ export interface DoRegisterConfigDataMap {
onevent: EventNameAndPrepend;
plugin: never;
command: CommandRegisterConfig;
route: KoishiRouteDef;
}
export interface MappingStruct<
T extends Record<string | number | symbol, any>,
K extends keyof T
K extends keyof T,
> {
type: K;
data?: T[K];
......@@ -99,7 +102,7 @@ export interface MappingStruct<
export function GenerateMappingStruct<
T extends Record<string | number | symbol, any>,
K extends keyof T
K extends keyof T,
>(type: K, data?: T[K]): MappingStruct<T, K> {
return {
type,
......@@ -108,7 +111,7 @@ export function GenerateMappingStruct<
}
export type DoRegisterConfig<
K extends keyof DoRegisterConfigDataMap = keyof DoRegisterConfigDataMap
K extends keyof DoRegisterConfigDataMap = keyof DoRegisterConfigDataMap,
> = MappingStruct<DoRegisterConfigDataMap, K>;
// Command stuff
......@@ -138,7 +141,7 @@ export interface CommandPutConfigMap {
}
export type CommandPutConfig<
K extends keyof CommandPutConfigMap = keyof CommandPutConfigMap
K extends keyof CommandPutConfigMap = keyof CommandPutConfigMap,
> = MappingStruct<CommandPutConfigMap, K>;
export type CommandDefinitionFun = (cmd: Command) => Command;
......@@ -155,3 +158,22 @@ export interface ProvideOptions {
export interface ProvideDefinition extends ProvideOptions {
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>(
});
}
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:
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