temp
This commit is contained in:
45
src/app.ts
45
src/app.ts
@@ -1,4 +1,4 @@
|
|||||||
import { AddOpts, QueryRouter, Route, RouteContext, RouteOpts } from './route.ts';
|
import { AddOpts, QueryRouter, QueryRouterServer, Route, RouteContext, RouteOpts } from './route.ts';
|
||||||
import { ServerNode, ServerNodeOpts } from './server/server.ts';
|
import { ServerNode, ServerNodeOpts } from './server/server.ts';
|
||||||
import { HandleCtx } from './server/server-base.ts';
|
import { HandleCtx } from './server/server-base.ts';
|
||||||
import { ServerType } from './server/server-type.ts';
|
import { ServerType } from './server/server-type.ts';
|
||||||
@@ -10,7 +10,7 @@ import { randomId } from './utils/random.ts';
|
|||||||
|
|
||||||
type RouterHandle = (msg: { path: string;[key: string]: any }) => { code: string; data?: any; message?: string;[key: string]: any };
|
type RouterHandle = (msg: { path: string;[key: string]: any }) => { code: string; data?: any; message?: string;[key: string]: any };
|
||||||
type AppOptions<T = {}> = {
|
type AppOptions<T = {}> = {
|
||||||
router?: QueryRouter;
|
router?: QueryRouterServer;
|
||||||
server?: ServerType;
|
server?: ServerType;
|
||||||
/** handle msg 关联 */
|
/** handle msg 关联 */
|
||||||
routerHandle?: RouterHandle;
|
routerHandle?: RouterHandle;
|
||||||
@@ -25,12 +25,12 @@ export type AppRouteContext<T = {}> = HandleCtx & RouteContext<T> & { app: App<T
|
|||||||
* 封装了 Router 和 Server 的 App 模块,处理http的请求和响应,内置了 Cookie 和 Token 和 res 的处理
|
* 封装了 Router 和 Server 的 App 模块,处理http的请求和响应,内置了 Cookie 和 Token 和 res 的处理
|
||||||
* U - Route Context的扩展类型
|
* U - Route Context的扩展类型
|
||||||
*/
|
*/
|
||||||
export class App<U = {}> extends QueryRouter {
|
export class App<U = {}> extends QueryRouterServer {
|
||||||
declare appId: string;
|
declare appId: string;
|
||||||
router: QueryRouter;
|
router: QueryRouterServer;
|
||||||
server: ServerType;
|
server: ServerType;
|
||||||
constructor(opts?: AppOptions<U>) {
|
constructor(opts?: AppOptions<U>) {
|
||||||
super();
|
super({ initHandle: false, context: { needSerialize: true, ...opts?.routerContext } });
|
||||||
const router = this;
|
const router = this;
|
||||||
let server = opts?.server;
|
let server = opts?.server;
|
||||||
if (!server) {
|
if (!server) {
|
||||||
@@ -42,7 +42,6 @@ export class App<U = {}> extends QueryRouter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
server.setHandle(router.getHandle(router, opts?.routerHandle, opts?.routerContext));
|
server.setHandle(router.getHandle(router, opts?.routerHandle, opts?.routerContext));
|
||||||
router.setContext({ needSerialize: true, ...opts?.routerContext });
|
|
||||||
this.router = router;
|
this.router = router;
|
||||||
this.server = server;
|
this.server = server;
|
||||||
if (opts?.appId) {
|
if (opts?.appId) {
|
||||||
@@ -64,47 +63,15 @@ export class App<U = {}> extends QueryRouter {
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
this.server.listen(...args);
|
this.server.listen(...args);
|
||||||
}
|
}
|
||||||
addRoute(route: Route, opts?: AddOpts) {
|
|
||||||
super.add(route, opts);
|
|
||||||
}
|
|
||||||
|
|
||||||
Route = Route;
|
Route = Route;
|
||||||
route(opts: RouteOpts<AppRouteContext<U>>): Route<AppRouteContext<U>>;
|
route(opts: RouteOpts<AppRouteContext<U>>): Route<AppRouteContext<U>>;
|
||||||
route(path: string, key?: string): Route<AppRouteContext<U>>;
|
route(path: string, key?: string): Route<AppRouteContext<U>>;
|
||||||
route(path: string, opts?: RouteOpts<AppRouteContext<U>>): Route<AppRouteContext<U>>;
|
route(path: string, opts?: RouteOpts<AppRouteContext<U>>): Route<AppRouteContext<U>>;
|
||||||
route(path: string, key?: string, opts?: RouteOpts<AppRouteContext<U>>): Route<AppRouteContext<U>>;
|
route(path: string, key?: string, opts?: RouteOpts<AppRouteContext<U>>): Route<AppRouteContext<U>>;
|
||||||
route(...args: any[]) {
|
route(...args: any[]) {
|
||||||
const [path, key, opts] = args;
|
return super.route(...args as any[]);
|
||||||
if (typeof path === 'object') {
|
|
||||||
return new Route(path.path, path.key, path);
|
|
||||||
}
|
|
||||||
if (typeof path === 'string') {
|
|
||||||
if (opts) {
|
|
||||||
return new Route(path, key, opts);
|
|
||||||
}
|
|
||||||
if (key && typeof key === 'object') {
|
|
||||||
return new Route(path, key?.key || '', key);
|
|
||||||
}
|
|
||||||
return new Route(path, key);
|
|
||||||
}
|
|
||||||
return new Route(path, key, opts);
|
|
||||||
}
|
|
||||||
prompt(description: string): Route<AppRouteContext<U>>
|
|
||||||
prompt(description: Function): Route<AppRouteContext<U>>
|
|
||||||
prompt(...args: any[]) {
|
|
||||||
const [desc] = args;
|
|
||||||
let description = ''
|
|
||||||
if (typeof desc === 'string') {
|
|
||||||
description = desc;
|
|
||||||
} else if (typeof desc === 'function') {
|
|
||||||
description = desc() || ''; // 如果是Promise,需要addTo App之前就要获取应有的函数了。
|
|
||||||
}
|
|
||||||
return new Route('', '', { description });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async call(message: { id?: string, path?: string; key?: string; payload?: any }, ctx?: AppRouteContext<U> & { [key: string]: any }) {
|
|
||||||
return await super.call(message, ctx);
|
|
||||||
}
|
|
||||||
async run(msg: { id?: string, path?: string; key?: string; payload?: any }, ctx?: Partial<AppRouteContext<U>> & { [key: string]: any }) {
|
async run(msg: { id?: string, path?: string; key?: string; payload?: any }, ctx?: Partial<AppRouteContext<U>> & { [key: string]: any }) {
|
||||||
return await super.run(msg, ctx);
|
return await super.run(msg, ctx);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,9 +59,16 @@ export const createRouterAgentPluginFn = (opts?: {
|
|||||||
if (!router.hasRoute('call', '')) {
|
if (!router.hasRoute('call', '')) {
|
||||||
addCallFn(router as App)
|
addCallFn(router as App)
|
||||||
}
|
}
|
||||||
if (!router.hasRoute('auth', '')) {
|
if (router) {
|
||||||
router.route({ path: 'auth', key: '', id: 'auth', description: '认证' }).define(async (ctx) => { }).addTo(router as App)
|
(router as any).route({ path: 'auth', key: '', id: 'auth', description: '认证' }).define(async (ctx) => { }).addTo(router as App, {
|
||||||
|
overwrite: false
|
||||||
|
});
|
||||||
|
|
||||||
|
(router as any).route({ path: 'auth-admin', key: '', id: 'auth-admin', description: '认证' }).define(async (ctx) => { }).addTo(router as App, {
|
||||||
|
overwrite: false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const _routes = filter(router.routes, opts?.query || '')
|
const _routes = filter(router.routes, opts?.query || '')
|
||||||
const routes = _routes.filter(r => {
|
const routes = _routes.filter(r => {
|
||||||
const metadata = r.metadata as Skill
|
const metadata = r.metadata as Skill
|
||||||
|
|||||||
79
src/route.ts
79
src/route.ts
@@ -6,6 +6,23 @@ import { randomId } from './utils/random.ts';
|
|||||||
import * as schema from './validator/schema.ts';
|
import * as schema from './validator/schema.ts';
|
||||||
|
|
||||||
export type RouterContextT = { code?: number;[key: string]: any };
|
export type RouterContextT = { code?: number;[key: string]: any };
|
||||||
|
|
||||||
|
type ExtractArgs<A> = A extends z.ZodTypeAny ? z.infer<A> : A;
|
||||||
|
|
||||||
|
type OptionalKeys<T> = {
|
||||||
|
[K in keyof T]-?: {} extends Pick<T, K> ? K : never;
|
||||||
|
}[keyof T];
|
||||||
|
|
||||||
|
type MakeOptional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
|
||||||
|
|
||||||
|
type BuildRouteContext<M, U> = M extends { args?: infer A }
|
||||||
|
? A extends z.ZodObject<any>
|
||||||
|
? RouteContext<{ args?: z.infer<A> }, U>
|
||||||
|
: A extends Record<string, z.ZodTypeAny>
|
||||||
|
? RouteContext<{ args?: { [K in keyof A]: z.infer<A[K]> } }, U>
|
||||||
|
: RouteContext<U>
|
||||||
|
: RouteContext<U>;
|
||||||
|
|
||||||
export type RouteContext<T = { code?: number }, S = any> = {
|
export type RouteContext<T = { code?: number }, S = any> = {
|
||||||
/**
|
/**
|
||||||
* 本地自己调用的时候使用,可以标识为当前自调用,那么 auth 就不许重复的校验
|
* 本地自己调用的时候使用,可以标识为当前自调用,那么 auth 就不许重复的校验
|
||||||
@@ -23,7 +40,9 @@ export type RouteContext<T = { code?: number }, S = any> = {
|
|||||||
code?: number;
|
code?: number;
|
||||||
/** return msg */
|
/** return msg */
|
||||||
message?: string;
|
message?: string;
|
||||||
// 传递状态
|
/**
|
||||||
|
* 传递状态
|
||||||
|
*/
|
||||||
state?: S;
|
state?: S;
|
||||||
// transfer data
|
// transfer data
|
||||||
/**
|
/**
|
||||||
@@ -127,7 +146,9 @@ export const createSkill = <T = SimpleObject>(skill: Skill<T>): Skill<T> => {
|
|||||||
|
|
||||||
export type RouteInfo = Pick<Route, (typeof pickValue)[number]>;
|
export type RouteInfo = Pick<Route, (typeof pickValue)[number]>;
|
||||||
|
|
||||||
export class Route<U = { [key: string]: any }, T extends SimpleObject = SimpleObject> implements throwError {
|
type ExtractMetadata<M> = M extends { metadata?: infer Meta } ? Meta extends SimpleObject ? Meta : SimpleObject : SimpleObject;
|
||||||
|
|
||||||
|
export class Route<M extends SimpleObject = SimpleObject, U extends SimpleObject = SimpleObject, T extends SimpleObject = SimpleObject> implements throwError {
|
||||||
/**
|
/**
|
||||||
* 一级路径
|
* 一级路径
|
||||||
*/
|
*/
|
||||||
@@ -137,10 +158,10 @@ export class Route<U = { [key: string]: any }, T extends SimpleObject = SimpleOb
|
|||||||
*/
|
*/
|
||||||
key?: string;
|
key?: string;
|
||||||
id?: string;
|
id?: string;
|
||||||
run?: Run;
|
run?: Run<BuildRouteContext<M, U>>;
|
||||||
nextRoute?: NextRoute; // route to run after this route
|
nextRoute?: NextRoute; // route to run after this route
|
||||||
description?: string;
|
description?: string;
|
||||||
metadata?: T;
|
metadata?: M;
|
||||||
middleware?: RouteMiddleware[]; // middleware
|
middleware?: RouteMiddleware[]; // middleware
|
||||||
type? = 'route';
|
type? = 'route';
|
||||||
/**
|
/**
|
||||||
@@ -161,10 +182,10 @@ export class Route<U = { [key: string]: any }, T extends SimpleObject = SimpleOb
|
|||||||
const delimiter = opts.delimiter ?? '$#$';
|
const delimiter = opts.delimiter ?? '$#$';
|
||||||
this.id = path + delimiter + key;
|
this.id = path + delimiter + key;
|
||||||
}
|
}
|
||||||
this.run = opts.run;
|
this.run = opts.run as Run<BuildRouteContext<M, U>>;
|
||||||
this.nextRoute = opts.nextRoute;
|
this.nextRoute = opts.nextRoute;
|
||||||
this.description = opts.description;
|
this.description = opts.description;
|
||||||
this.metadata = opts.metadata as T;
|
this.metadata = opts.metadata as M;
|
||||||
this.type = opts.type || 'route';
|
this.type = opts.type || 'route';
|
||||||
this.middleware = opts.middleware || [];
|
this.middleware = opts.middleware || [];
|
||||||
this.key = opts.key || key;
|
this.key = opts.key || key;
|
||||||
@@ -188,9 +209,9 @@ export class Route<U = { [key: string]: any }, T extends SimpleObject = SimpleOb
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
define<T extends { [key: string]: any } = RouterContextT>(opts: DefineRouteOpts): this;
|
define<T extends { [key: string]: any } = RouterContextT>(opts: DefineRouteOpts): this;
|
||||||
define<T extends { [key: string]: any } = RouterContextT>(fn: Run<T & U>): this;
|
define<T extends { [key: string]: any } = RouterContextT>(fn: Run<T & BuildRouteContext<M, U>>): this;
|
||||||
define<T extends { [key: string]: any } = RouterContextT>(key: string, fn: Run<T & U>): this;
|
define<T extends { [key: string]: any } = RouterContextT>(key: string, fn: Run<T & BuildRouteContext<M, U>>): this;
|
||||||
define<T extends { [key: string]: any } = RouterContextT>(path: string, key: string, fn: Run<T & U>): this;
|
define<T extends { [key: string]: any } = RouterContextT>(path: string, key: string, fn: Run<T & BuildRouteContext<M, U>>): this;
|
||||||
define(...args: any[]) {
|
define(...args: any[]) {
|
||||||
const [path, key, opts] = args;
|
const [path, key, opts] = args;
|
||||||
// 全覆盖,所以opts需要准确,不能由idUsePath 需要check的变量
|
// 全覆盖,所以opts需要准确,不能由idUsePath 需要check的变量
|
||||||
@@ -213,7 +234,7 @@ export class Route<U = { [key: string]: any }, T extends SimpleObject = SimpleOb
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
if (typeof path === 'function') {
|
if (typeof path === 'function') {
|
||||||
this.run = path;
|
this.run = path as Run<BuildRouteContext<M, U>>;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
if (typeof path === 'string' && typeof key === 'function') {
|
if (typeof path === 'string' && typeof key === 'function') {
|
||||||
@@ -692,6 +713,7 @@ type QueryRouterServerOpts = {
|
|||||||
handleFn?: HandleFn;
|
handleFn?: HandleFn;
|
||||||
context?: RouteContext;
|
context?: RouteContext;
|
||||||
appId?: string;
|
appId?: string;
|
||||||
|
initHandle?: boolean;
|
||||||
};
|
};
|
||||||
interface HandleFn<T = any> {
|
interface HandleFn<T = any> {
|
||||||
(msg: { path: string;[key: string]: any }, ctx?: any): { code: string; data?: any; message?: string;[key: string]: any };
|
(msg: { path: string;[key: string]: any }, ctx?: any): { code: string; data?: any; message?: string;[key: string]: any };
|
||||||
@@ -706,7 +728,10 @@ export class QueryRouterServer extends QueryRouter {
|
|||||||
handle: any;
|
handle: any;
|
||||||
constructor(opts?: QueryRouterServerOpts) {
|
constructor(opts?: QueryRouterServerOpts) {
|
||||||
super();
|
super();
|
||||||
this.handle = this.getHandle(this, opts?.handleFn, opts?.context);
|
const initHandle = opts?.initHandle ?? true;
|
||||||
|
if (initHandle || opts?.handleFn) {
|
||||||
|
this.handle = this.getHandle(this, opts?.handleFn, opts?.context);
|
||||||
|
}
|
||||||
this.setContext({ needSerialize: false, ...opts?.context });
|
this.setContext({ needSerialize: false, ...opts?.context });
|
||||||
if (opts?.appId) {
|
if (opts?.appId) {
|
||||||
this.appId = opts.appId;
|
this.appId = opts.appId;
|
||||||
@@ -721,37 +746,25 @@ export class QueryRouterServer extends QueryRouter {
|
|||||||
this.add(route, opts);
|
this.add(route, opts);
|
||||||
}
|
}
|
||||||
Route = Route;
|
Route = Route;
|
||||||
route(opts: RouteOpts): Route<Required<RouteContext>>;
|
route<M extends SimpleObject = SimpleObject>(opts: RouteOpts & { metadata?: M }): Route<M, Required<RouteContext>>;
|
||||||
route(path: string, key?: string): Route<Required<RouteContext>>;
|
route<M extends SimpleObject = SimpleObject>(path: string, opts?: RouteOpts & { metadata?: M }): Route<M, Required<RouteContext>>;
|
||||||
route(path: string, opts?: RouteOpts): Route<Required<RouteContext>>;
|
route<M extends SimpleObject = SimpleObject>(path: string, key?: string): Route<M, Required<RouteContext>>;
|
||||||
route(path: string, key?: string, opts?: RouteOpts): Route<Required<RouteContext>>;
|
route<M extends SimpleObject = SimpleObject>(path: string, key?: string, opts?: RouteOpts & { metadata?: M }): Route<M, Required<RouteContext>>;
|
||||||
route(...args: any[]) {
|
route<M extends SimpleObject = SimpleObject>(...args: any[]) {
|
||||||
const [path, key, opts] = args;
|
const [path, key, opts] = args;
|
||||||
if (typeof path === 'object') {
|
if (typeof path === 'object') {
|
||||||
return new Route(path.path, path.key, path);
|
return new Route<M, Required<RouteContext>>(path.path, path.key, path);
|
||||||
}
|
}
|
||||||
if (typeof path === 'string') {
|
if (typeof path === 'string') {
|
||||||
if (opts) {
|
if (opts) {
|
||||||
return new Route(path, key, opts);
|
return new Route<M, Required<RouteContext>>(path, key, opts);
|
||||||
}
|
}
|
||||||
if (key && typeof key === 'object') {
|
if (key && typeof key === 'object') {
|
||||||
return new Route(path, key?.key || '', key);
|
return new Route<M, Required<RouteContext>>(path, key?.key || '', key);
|
||||||
}
|
}
|
||||||
return new Route(path, key);
|
return new Route<M, Required<RouteContext>>(path, key);
|
||||||
}
|
}
|
||||||
return new Route(path, key, opts);
|
return new Route<M, Required<RouteContext>>(path, key, opts);
|
||||||
}
|
|
||||||
prompt(description: string): Route<Required<RouteContext>>;
|
|
||||||
prompt(description: Function): Route<Required<RouteContext>>;
|
|
||||||
prompt(...args: any[]) {
|
|
||||||
const [desc] = args;
|
|
||||||
let description = ''
|
|
||||||
if (typeof desc === 'string') {
|
|
||||||
description = desc;
|
|
||||||
} else if (typeof desc === 'function') {
|
|
||||||
description = desc() || ''; // 如果是Promise,需要addTo App之前就要获取应有的函数了。
|
|
||||||
}
|
|
||||||
return new Route('', '', { description });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
15
src/test/route-ts.ts
Normal file
15
src/test/route-ts.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { QueryRouterServer } from "@/route.ts";
|
||||||
|
import z from "zod";
|
||||||
|
|
||||||
|
const router = new QueryRouterServer()
|
||||||
|
|
||||||
|
router.route({
|
||||||
|
metadata: {
|
||||||
|
args: {
|
||||||
|
a: z.string(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}).define(async (ctx) => {
|
||||||
|
const argA: string = ctx.args.a;
|
||||||
|
ctx.body = '1';
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user