framework: use @cordisjs/core instead

This commit is contained in:
undefined committed 2025-03-04 03:04:01 +08:00
1 parent 221283e8e8
commit 2c8c03153e
10 files changed
+86 -179

No files matched your search

+3 -2
View File
@@ -1,3 +1,4 @@
import { Context } from '@cordisjs/core';
import { ValidationError } from './error';
import type { Handler } from './server';
import { Converter, Type, Validator } from './validator';
@@ -35,7 +36,7 @@ function _buildParam(name: string, source: 'get' | 'post' | 'all' | 'route', ...
}
function _descriptor(v: ParamOption<any>) {
return function desc(this: Handler, target: any, funcName: string, obj: any) {
return function desc<T extends Context>(this: Handler<T>, target: any, funcName: string, obj: any) {
target.__param ||= {};
target.__param[target.constructor.name] ||= {};
if (!target.__param[target.constructor.name][funcName]) {
@@ -44,7 +45,7 @@ function _descriptor(v: ParamOption<any>) {
const firstArg = val.split(')')[0]?.split(',')[0]?.split('(')[1]?.trim() || '';
const domainIdStyle = firstArg.toLowerCase().startsWith('domainid');
target.__param[target.constructor.name][funcName] = [];
obj.value = function validate(this: Handler, rawArgs: any, ...extra: any[]) {
obj.value = function validate(this: Handler<T>, rawArgs: any, ...extra: any[]) {
if (typeof rawArgs !== 'object' || extra.length) return originalMethod.call(this, rawArgs, ...extra);
const c = [];
const arglist: ParamOption<any>[] = target.__param[target.constructor.name][funcName];
+10 -9
View File
@@ -1,16 +1,17 @@
import type { ConnectionHandler, Handler } from './server';
import type { Context as CordisContext } from '@cordisjs/core';
type HandlerEvents<T extends Handler, C extends ConnectionHandler> =
Record<`handler/${HookType}/${string}`, (thisArg: T & Record<string, any>) => VoidReturn>
& Record<`handler/${HookType}`, (thisArg: T) => VoidReturn>
& Record<`handler/register/${string}`, (HandlerClass: new (...args: any[]) => T) => VoidReturn>
& Record<`connection/${'create' | 'active' | 'close'}`, (thisArg: C) => VoidReturn>;
type HandlerEvents<C extends CordisContext> =
Record<`handler/${HookType}/${string}`, (thisArg: Handler<C> & Record<string, any>) => VoidReturn>
& Record<`handler/${HookType}`, (thisArg: Handler<C>) => VoidReturn>
& Record<`handler/register/${string}`, (HandlerClass: new (...args: any[]) => Handler<C>) => VoidReturn>
& Record<`connection/${'create' | 'active' | 'close'}`, (thisArg: ConnectionHandler<C>) => VoidReturn>;
export type VoidReturn = Promise<any> | any;
export type HookType = 'before-prepare' | 'before' | 'before-operation' | 'after' | 'finish';
export interface ServerEvents<T extends Handler = Handler, C extends ConnectionHandler = ConnectionHandler> extends HandlerEvents<T, C> {
'handler/create': (thisArg: Handler, type: 'ws' | 'http') => VoidReturn
'handler/init': (thisArg: Handler) => VoidReturn
'handler/error': (thisArg: Handler, e: Error) => VoidReturn
export interface ServerEvents<C extends CordisContext> extends HandlerEvents<C> {
'handler/create': (thisArg: Handler<C>, type: 'ws' | 'http') => VoidReturn
'handler/init': (thisArg: Handler<C>) => VoidReturn
'handler/error': (thisArg: Handler<C>, e: Error) => VoidReturn
}
+1 -1
View File
@@ -4,7 +4,7 @@
"main": "index.ts",
"license": "MIT",
"peerDependencies": {
"cordis": "*"
"@cordisjs/core": "*"
},
"dependencies": {
"@hydrooj/utils": "workspace:^",
+2 -1
View File
@@ -1,6 +1,7 @@
import type { HandlerCommon } from './server';
import type { Context } from '@cordisjs/core';
export default function serializer(ignoreSerializeFunction = false, h?: HandlerCommon) {
export default function serializer<T extends Context>(ignoreSerializeFunction = false, h?: HandlerCommon<T>) {
return (k: string, v: any) => {
if (k.startsWith('_') && k !== '_id') return undefined;
if (typeof v === 'bigint') return `BigInt::${v.toString()}`;
+48 -55
View File
@@ -2,7 +2,7 @@ import http from 'http';
import { tmpdir } from 'os';
import { join } from 'path';
import { PassThrough } from 'stream';
import { Context, Service } from 'cordis';
import { Context as CordisContext, Service } from '@cordisjs/core';
import type { Files } from 'formidable';
import fs from 'fs-extra';
import Koa from 'koa';
@@ -125,8 +125,8 @@ export interface UserModel {
_id: number;
}
export interface HandlerCommon { }
export class HandlerCommon {
export interface HandlerCommon<C extends CordisContext> { }
export class HandlerCommon<C extends CordisContext> {
static [kHandler]: string | boolean = true;
session: Record<string, any>;
args: Record<string, any>;
@@ -135,7 +135,7 @@ export class HandlerCommon {
UiContext: Record<string, any>;
user: UserModel;
constructor(public context: KoaContext, public ctx: Context) {
constructor(public context: KoaContext, public ctx: C) {
this.renderHTML = this.renderHTML.bind(this);
this.url = this.url.bind(this);
this.session = context.session;
@@ -196,7 +196,7 @@ export class HandlerCommon {
}
}
export class Handler extends HandlerCommon {
export class Handler<C extends CordisContext> extends HandlerCommon<C> {
loginMethods: any;
noCheckPermView = false;
notUsage = false;
@@ -242,33 +242,7 @@ export class Handler extends HandlerCommon {
}
}
const Checker = (permPrivChecker) => {
let perm: bigint;
let priv: number;
let checker = () => { };
for (const item of permPrivChecker) {
if (typeof item === 'object') {
if (typeof item.call !== 'undefined') {
checker = item;
} else if (typeof item[0] === 'number') {
priv = item;
} else if (typeof item[0] === 'bigint') {
perm = item;
}
} else if (typeof item === 'number') {
priv = item;
} else if (typeof item === 'bigint') {
perm = item;
}
}
return function check(this: Handler) {
checker();
if (perm) this.checkPerm(perm);
if (priv) this.checkPriv(priv);
};
};
export class ConnectionHandler extends HandlerCommon {
export class ConnectionHandler<C extends CordisContext> extends HandlerCommon<C> {
conn: WebSocket;
compression: Shorty;
counter = 0;
@@ -305,7 +279,7 @@ export class ConnectionHandler extends HandlerCommon {
}
}
class NotFoundHandler extends Handler {
class NotFoundHandler extends Handler<CordisContext> {
prepare() { throw new NotFoundError(this.request.path); }
all() { }
}
@@ -344,7 +318,7 @@ export interface WebServiceConfig {
xhost?: string;
}
export class WebService extends Service {
export class WebService<C extends CordisContext = CordisContext> extends Service<C> {
private registry: Record<string, any> = Object.create(null);
private registrationCount = Counter();
private serverLayers = [];
@@ -359,7 +333,7 @@ export class WebService extends Service {
Handler = Handler;
ConnectionHandler = ConnectionHandler;
constructor(ctx: Context, public config: WebServiceConfig) {
constructor(ctx: C, public config: WebServiceConfig) {
super(ctx, 'server');
ctx.mixin('server', ['Route', 'Connection', 'withHandlerClass']);
this.server.keys = this.config.keys;
@@ -668,6 +642,33 @@ ${c.response.status} ${endTime - startTime}ms ${c.response.length}`);
}
this.registry[name] = HandlerClass;
this.registrationCount[name]++;
const Checker = (permPrivChecker) => {
let perm: bigint;
let priv: number;
let checker = () => { };
for (const item of permPrivChecker) {
if (typeof item === 'object') {
if (typeof item.call !== 'undefined') {
checker = item;
} else if (typeof item[0] === 'number') {
priv = item;
} else if (typeof item[0] === 'bigint') {
perm = item;
}
} else if (typeof item === 'number') {
priv = item;
} else if (typeof item === 'bigint') {
perm = item;
}
}
return function check(this: Handler<C>) {
checker();
if (perm) this.checkPerm(perm);
if (priv) this.checkPriv(priv);
};
};
if (type === 'route') {
router.all(routeName, path, (ctx) => this.handleHttp(ctx as any, HandlerClass, Checker(permPrivChecker)));
} else {
@@ -688,23 +689,20 @@ ${c.response.status} ${endTime - startTime}ms ${c.response.length}`);
}
public withHandlerClass<T extends string>(
name: T, callback: (HandlerClass: T extends `${string}ConnectionHandler` ? typeof ConnectionHandler : typeof Handler) => any,
name: T, callback: (HandlerClass: T extends `${string}ConnectionHandler` ? typeof ConnectionHandler<C> : typeof Handler<C>) => any,
) {
if (this.registry[name]) callback(this.registry[name]);
// @ts-ignore
const dispose = this.ctx.on(`handler/register/${name}`, callback);
this[Context.current]?.on('dispose', () => {
dispose();
});
this.ctx.on(`handler/register/${name}`, callback);
}
// FIXME: should be typeof Handler<Context> instead of any
// eslint-disable-next-line @typescript-eslint/naming-convention
public Route(name: string, path: string, RouteHandler: typeof Handler, ...permPrivChecker) {
public Route(name: string, path: string, RouteHandler: any, ...permPrivChecker) {
return this.register('route', name, path, RouteHandler, ...permPrivChecker);
}
// eslint-disable-next-line @typescript-eslint/naming-convention
public Connection(name: string, path: string, RouteHandler: typeof ConnectionHandler, ...permPrivChecker) {
public Connection(name: string, path: string, RouteHandler: any, ...permPrivChecker) {
return this.register('conn', name, path, RouteHandler, ...permPrivChecker);
}
@@ -713,7 +711,7 @@ ${c.response.status} ${endTime - startTime}ms ${c.response.length}`);
const dispose = () => {
this[name] = this[name].filter((i) => i !== layer);
};
this[Context.origin]?.on('dispose', dispose);
this[CordisContext.origin]?.on('dispose', dispose);
return dispose;
}
@@ -738,7 +736,7 @@ ${c.response.status} ${endTime - startTime}ms ${c.response.length}`);
this.captureAllRoutes[prefix] = cb;
}
public handlerMixin(MixinClass: Partial<HandlerCommon>) {
public handlerMixin(MixinClass: Partial<HandlerCommon<C>>) {
for (const val of Object.getOwnPropertyNames(MixinClass)) {
HandlerCommon.prototype[val] = MixinClass[val];
}
@@ -755,16 +753,11 @@ ${c.response.status} ${endTime - startTime}ms ${c.response.length}`);
}
}
declare module 'cordis' {
declare module '@cordisjs/core' {
interface Context {
server: WebService;
Route: WebService['Route'];
Connection: WebService['Connection'];
withHandlerClass: WebService['withHandlerClass'];
server: WebService<this>;
Route: WebService<this>['Route'];
Connection: WebService<this>['Connection'];
withHandlerClass: WebService<this>['withHandlerClass'];
}
}
export async function apply(ctx: Context, config: WebServiceConfig) {
ctx.provide('server', undefined, true);
ctx.server = new WebService(ctx, config);
}