@kevisual/router 0.0.10 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -55,14 +55,29 @@ type RouteContext<T = {
55
55
  /** return msg */
56
56
  message?: string;
57
57
  state?: S;
58
+ /**
59
+ * 当前路径
60
+ */
58
61
  currentPath?: string;
62
+ /**
63
+ * 当前key
64
+ */
59
65
  currentKey?: string;
66
+ /**
67
+ * 当前route
68
+ */
60
69
  currentRoute?: Route;
61
- progress?: [[string, string]][];
70
+ /**
71
+ * 进度
72
+ */
73
+ progress?: [string, string][];
62
74
  nextQuery?: {
63
75
  [key: string]: any;
64
76
  };
65
77
  end?: boolean;
78
+ /**
79
+ * 请求 route的返回结果,包函ctx
80
+ */
66
81
  queryRouter?: QueryRouter;
67
82
  error?: any;
68
83
  /** 请求 route的返回结果,包函ctx */
@@ -5868,6 +5868,13 @@ class QueryRouter {
5868
5868
  ctx.currentKey = key;
5869
5869
  ctx.currentRoute = route;
5870
5870
  ctx.index = (ctx.index || 0) + 1;
5871
+ const progress = [path, key];
5872
+ if (ctx.progress) {
5873
+ ctx.progress.push(progress);
5874
+ }
5875
+ else {
5876
+ ctx.progress = [progress];
5877
+ }
5871
5878
  if (ctx.index > maxNextRoute) {
5872
5879
  ctx.code = 500;
5873
5880
  ctx.message = 'Too many nextRoute';
@@ -6054,7 +6061,7 @@ class QueryRouter {
6054
6061
  const { path, key = '', payload = {}, ...query } = message;
6055
6062
  ctx = ctx || {};
6056
6063
  ctx.query = { ...ctx.query, ...query, ...payload };
6057
- ctx.state = {};
6064
+ ctx.state = { ...ctx?.state };
6058
6065
  ctx.throw = this.throw;
6059
6066
  // put queryRouter to ctx
6060
6067
  // TODO: 是否需要queryRouter,函数内部处理router路由执行,这应该是避免去内部去包含的功能过
@@ -6062,6 +6069,7 @@ class QueryRouter {
6062
6069
  ctx.call = this.call.bind(this);
6063
6070
  ctx.queryRoute = this.queryRoute.bind(this);
6064
6071
  ctx.index = 0;
6072
+ ctx.progress = ctx.progress || [];
6065
6073
  const res = await this.runRoute(path, key, ctx);
6066
6074
  const serialize = ctx.needSerialize ?? true; // 是否需要序列化
6067
6075
  if (serialize) {
@@ -1,4 +1,4 @@
1
- import url from 'url';
1
+ import url from 'node:url';
2
2
 
3
3
  var dist = {};
4
4
 
package/dist/router.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { Schema } from 'zod';
2
2
  export { Schema } from 'zod';
3
- import http, { IncomingMessage, ServerResponse } from 'http';
4
- import https from 'https';
5
- import http2 from 'http2';
3
+ import http, { IncomingMessage, ServerResponse } from 'node:http';
4
+ import https from 'node:https';
5
+ import http2 from 'node:http2';
6
6
  import * as cookie from 'cookie';
7
7
  import { WebSocketServer, WebSocket } from 'ws';
8
8
 
@@ -60,14 +60,29 @@ type RouteContext<T = {
60
60
  /** return msg */
61
61
  message?: string;
62
62
  state?: S;
63
+ /**
64
+ * 当前路径
65
+ */
63
66
  currentPath?: string;
67
+ /**
68
+ * 当前key
69
+ */
64
70
  currentKey?: string;
71
+ /**
72
+ * 当前route
73
+ */
65
74
  currentRoute?: Route;
66
- progress?: [[string, string]][];
75
+ /**
76
+ * 进度
77
+ */
78
+ progress?: [string, string][];
67
79
  nextQuery?: {
68
80
  [key: string]: any;
69
81
  };
70
82
  end?: boolean;
83
+ /**
84
+ * 请求 route的返回结果,包函ctx
85
+ */
71
86
  queryRouter?: QueryRouter;
72
87
  error?: any;
73
88
  /** 请求 route的返回结果,包函ctx */
@@ -457,7 +472,7 @@ declare class Server {
457
472
  listen(path: string, listeningListener?: () => void): void;
458
473
  listen(handle: any, backlog?: number, listeningListener?: () => void): void;
459
474
  listen(handle: any, listeningListener?: () => void): void;
460
- createServer(): http.Server<typeof http.IncomingMessage, typeof http.ServerResponse> | https.Server<typeof http.IncomingMessage, typeof http.ServerResponse> | http2.Http2SecureServer<typeof http.IncomingMessage, typeof http.ServerResponse, typeof http2.Http2ServerRequest, typeof http2.Http2ServerResponse>;
475
+ createServer(): http.Server<typeof IncomingMessage, typeof ServerResponse> | https.Server<typeof IncomingMessage, typeof ServerResponse> | http2.Http2SecureServer<typeof IncomingMessage, typeof ServerResponse, typeof http2.Http2ServerRequest, typeof http2.Http2ServerResponse>;
461
476
  setHandle(handle?: any): void;
462
477
  /**
463
478
  * get callback
@@ -473,7 +488,7 @@ declare class Server {
473
488
  */
474
489
  on(listener: Listener | Listener[]): void;
475
490
  get callback(): any;
476
- get server(): http.Server<typeof http.IncomingMessage, typeof http.ServerResponse> | https.Server<typeof http.IncomingMessage, typeof http.ServerResponse> | http2.Http2SecureServer<typeof http.IncomingMessage, typeof http.ServerResponse, typeof http2.Http2ServerRequest, typeof http2.Http2ServerResponse>;
491
+ get server(): http.Server<typeof IncomingMessage, typeof ServerResponse> | https.Server<typeof IncomingMessage, typeof ServerResponse> | http2.Http2SecureServer<typeof IncomingMessage, typeof ServerResponse, typeof http2.Http2ServerRequest, typeof http2.Http2ServerResponse>;
477
492
  }
478
493
 
479
494
  /**
package/dist/router.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { webcrypto } from 'node:crypto';
2
- import http from 'http';
3
- import https from 'https';
4
- import http2 from 'http2';
5
- import url from 'url';
2
+ import http from 'node:http';
3
+ import https from 'node:https';
4
+ import http2 from 'node:http2';
5
+ import url from 'node:url';
6
6
  import { WebSocketServer } from 'ws';
7
7
 
8
8
  const urlAlphabet =
@@ -5887,6 +5887,13 @@ class QueryRouter {
5887
5887
  ctx.currentKey = key;
5888
5888
  ctx.currentRoute = route;
5889
5889
  ctx.index = (ctx.index || 0) + 1;
5890
+ const progress = [path, key];
5891
+ if (ctx.progress) {
5892
+ ctx.progress.push(progress);
5893
+ }
5894
+ else {
5895
+ ctx.progress = [progress];
5896
+ }
5890
5897
  if (ctx.index > maxNextRoute) {
5891
5898
  ctx.code = 500;
5892
5899
  ctx.message = 'Too many nextRoute';
@@ -6073,7 +6080,7 @@ class QueryRouter {
6073
6080
  const { path, key = '', payload = {}, ...query } = message;
6074
6081
  ctx = ctx || {};
6075
6082
  ctx.query = { ...ctx.query, ...query, ...payload };
6076
- ctx.state = {};
6083
+ ctx.state = { ...ctx?.state };
6077
6084
  ctx.throw = this.throw;
6078
6085
  // put queryRouter to ctx
6079
6086
  // TODO: 是否需要queryRouter,函数内部处理router路由执行,这应该是避免去内部去包含的功能过
@@ -6081,6 +6088,7 @@ class QueryRouter {
6081
6088
  ctx.call = this.call.bind(this);
6082
6089
  ctx.queryRoute = this.queryRoute.bind(this);
6083
6090
  ctx.index = 0;
6091
+ ctx.progress = ctx.progress || [];
6084
6092
  const res = await this.runRoute(path, key, ctx);
6085
6093
  const serialize = ctx.needSerialize ?? true; // 是否需要序列化
6086
6094
  if (serialize) {
@@ -6848,7 +6856,10 @@ class WsServerBase {
6848
6856
  listeners = [];
6849
6857
  listening = false;
6850
6858
  constructor(opts) {
6851
- this.wss = opts.wss || new WebSocketServer();
6859
+ this.wss = opts.wss;
6860
+ if (!this.wss) {
6861
+ throw new Error('wss is required');
6862
+ }
6852
6863
  this.path = opts.path || '';
6853
6864
  }
6854
6865
  setPath(path) {
package/package.json CHANGED
@@ -1,11 +1,8 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package",
3
3
  "name": "@kevisual/router",
4
- "version": "0.0.10",
4
+ "version": "0.0.11",
5
5
  "description": "",
6
- "main": "dist/index.js",
7
- "module": "dist/index.js",
8
- "types": "dist/index.d.ts",
9
6
  "type": "module",
10
7
  "scripts": {
11
8
  "build": "npm run clean && rollup -c",
@@ -14,7 +11,8 @@
14
11
  "clean": "rm -rf dist"
15
12
  },
16
13
  "files": [
17
- "dist"
14
+ "dist",
15
+ "src"
18
16
  ],
19
17
  "keywords": [],
20
18
  "author": "abearxiong",
@@ -24,20 +22,20 @@
24
22
  "@rollup/plugin-node-resolve": "^16.0.1",
25
23
  "@rollup/plugin-typescript": "^12.1.2",
26
24
  "@types/lodash-es": "^4.17.12",
27
- "@types/node": "^22.14.0",
25
+ "@types/node": "^22.14.1",
28
26
  "@types/ws": "^8.18.1",
29
27
  "@types/xml2js": "^0.4.14",
30
28
  "cookie": "^1.0.2",
31
29
  "lodash-es": "^4.17.21",
32
30
  "nanoid": "^5.1.5",
33
- "rollup": "^4.39.0",
31
+ "rollup": "^4.40.0",
34
32
  "rollup-plugin-dts": "^6.2.1",
35
33
  "ts-loader": "^9.5.2",
36
34
  "ts-node": "^10.9.2",
37
35
  "tslib": "^2.8.1",
38
- "typescript": "^5.8.2",
36
+ "typescript": "^5.8.3",
39
37
  "xml2js": "^0.6.2",
40
- "zod": "^3.24.2"
38
+ "zod": "^3.24.3"
41
39
  },
42
40
  "repository": {
43
41
  "type": "git",
@@ -71,6 +69,10 @@
71
69
  "./simple-lib": {
72
70
  "import": "./dist/router-simple-lib.js",
73
71
  "require": "./dist/router-simple-lib.js"
72
+ },
73
+ "./mod.ts": {
74
+ "import": "./src/mod.ts",
75
+ "require": "./src/mod.ts"
74
76
  }
75
77
  }
76
78
  }
package/src/app.ts ADDED
@@ -0,0 +1,103 @@
1
+ import { QueryRouter, Route, RouteContext, RouteOpts } from './route.ts';
2
+ import { Server, ServerOpts, HandleCtx } from './server/server.ts';
3
+ import { WsServer } from './server/ws-server.ts';
4
+ import { CustomError } from './result/error.ts';
5
+
6
+ type RouterHandle = (msg: { path: string; [key: string]: any }) => { code: string; data?: any; message?: string; [key: string]: any };
7
+ type AppOptions<T = {}> = {
8
+ router?: QueryRouter;
9
+ server?: Server;
10
+ /** handle msg 关联 */
11
+ routerHandle?: RouterHandle;
12
+ routerContext?: RouteContext<T>;
13
+ serverOptions?: ServerOpts;
14
+ io?: boolean;
15
+ ioOpts?: { routerHandle?: RouterHandle; routerContext?: RouteContext<T>; path?: string };
16
+ };
17
+ export type AppReqRes = HandleCtx;
18
+
19
+ /**
20
+ * 封装了 Router 和 Server 的 App 模块,处理http的请求和响应,内置了 Cookie 和 Token 和 res 的处理
21
+ */
22
+ export class App<T = {}, U = AppReqRes> {
23
+ router: QueryRouter;
24
+ server: Server;
25
+ io: WsServer;
26
+ constructor(opts?: AppOptions<T>) {
27
+ const router = opts?.router || new QueryRouter();
28
+ const server = opts?.server || new Server(opts?.serverOptions || {});
29
+ server.setHandle(router.getHandle(router, opts?.routerHandle, opts?.routerContext));
30
+ router.setContext({ needSerialize: true, ...opts?.routerContext });
31
+ this.router = router;
32
+ this.server = server;
33
+ if (opts?.io) {
34
+ this.io = new WsServer(server, opts?.ioOpts);
35
+ }
36
+ }
37
+ listen(port: number, hostname?: string, backlog?: number, listeningListener?: () => void): void;
38
+ listen(port: number, hostname?: string, listeningListener?: () => void): void;
39
+ listen(port: number, backlog?: number, listeningListener?: () => void): void;
40
+ listen(port: number, listeningListener?: () => void): void;
41
+ listen(path: string, backlog?: number, listeningListener?: () => void): void;
42
+ listen(path: string, listeningListener?: () => void): void;
43
+ listen(handle: any, backlog?: number, listeningListener?: () => void): void;
44
+ listen(handle: any, listeningListener?: () => void): void;
45
+ listen(...args: any[]) {
46
+ // @ts-ignore
47
+ this.server.listen(...args);
48
+ if (this.io) {
49
+ this.io.listen();
50
+ }
51
+ }
52
+ use(path: string, fn: (ctx: any) => any, opts?: RouteOpts) {
53
+ const route = new Route(path, '', opts);
54
+ route.run = fn;
55
+ this.router.add(route);
56
+ }
57
+ addRoute(route: Route) {
58
+ this.router.add(route);
59
+ }
60
+ add = this.addRoute;
61
+
62
+ Route = Route;
63
+ route(opts: RouteOpts): Route<U>;
64
+ route(path: string, key?: string): Route<U>;
65
+ route(path: string, opts?: RouteOpts): Route<U>;
66
+ route(path: string, key?: string, opts?: RouteOpts): Route<U>;
67
+ route(...args: any[]) {
68
+ const [path, key, opts] = args;
69
+ if (typeof path === 'object') {
70
+ return new Route(path.path, path.key, path);
71
+ }
72
+ if (typeof path === 'string') {
73
+ if (opts) {
74
+ return new Route(path, key, opts);
75
+ }
76
+ if (key && typeof key === 'object') {
77
+ return new Route(path, key?.key || '', key);
78
+ }
79
+ return new Route(path, key);
80
+ }
81
+ return new Route(path, key, opts);
82
+ }
83
+ async call(message: { path: string; key?: string; payload?: any }, ctx?: RouteContext & { [key: string]: any }) {
84
+ const router = this.router;
85
+ return await router.call(message, ctx);
86
+ }
87
+ async queryRoute(path: string, key?: string, payload?: any, ctx?: RouteContext & { [key: string]: any }) {
88
+ return await this.router.queryRoute({ path, key, payload }, ctx);
89
+ }
90
+ exportRoutes() {
91
+ return this.router.exportRoutes();
92
+ }
93
+ importRoutes(routes: any[]) {
94
+ this.router.importRoutes(routes);
95
+ }
96
+ importApp(app: App) {
97
+ this.importRoutes(app.exportRoutes());
98
+ }
99
+ throw(code?: number | string, message?: string, tips?: string): void;
100
+ throw(...args: any[]) {
101
+ throw new CustomError(...args);
102
+ }
103
+ }
package/src/browser.ts ADDED
@@ -0,0 +1,9 @@
1
+ export { Route, QueryRouter, QueryRouterServer } from './route.ts';
2
+
3
+ export { Rule, Schema, createSchema } from './validator/index.ts';
4
+
5
+ export type { RouteContext, RouteOpts } from './route.ts';
6
+
7
+ export type { Run } from './route.ts';
8
+
9
+ export { CustomError } from './result/error.ts';
package/src/connect.ts ADDED
@@ -0,0 +1,67 @@
1
+ import { nanoid } from 'nanoid';
2
+ import { RouteContext } from './route.ts';
3
+
4
+ export class Connect {
5
+ path: string;
6
+ key?: string;
7
+ _fn?: (ctx?: RouteContext) => Promise<RouteContext>;
8
+ description?: string;
9
+ connects: { path: string; key?: string }[];
10
+ share = false;
11
+
12
+ constructor(path: string) {
13
+ this.path = path;
14
+ this.key = nanoid();
15
+ }
16
+ use(path: string) {
17
+ this.connects.push({ path });
18
+ }
19
+ useList(paths: string[]) {
20
+ paths.forEach((path) => {
21
+ this.connects.push({ path });
22
+ });
23
+ }
24
+ useConnect(connect: Connect) {
25
+ this.connects.push({ path: connect.path, key: connect.key });
26
+ }
27
+ useConnectList(connects: Connect[]) {
28
+ connects.forEach((connect) => {
29
+ this.connects.push({ path: connect.path, key: connect.key });
30
+ });
31
+ }
32
+ getPathList() {
33
+ return this.connects.map((c) => c.path).filter(Boolean);
34
+ }
35
+ set fn(fn: (ctx?: RouteContext) => Promise<RouteContext>) {
36
+ this._fn = fn;
37
+ }
38
+ get fn() {
39
+ return this._fn;
40
+ }
41
+ }
42
+ export class QueryConnect {
43
+ connects: Connect[];
44
+ constructor() {
45
+ this.connects = [];
46
+ }
47
+ add(connect: Connect) {
48
+ const has = this.connects.find((c) => c.path === connect.path && c.key === connect.key);
49
+ if (has) {
50
+ // remove the old connect
51
+ console.log('[replace connect]:', connect.path, connect.key);
52
+ this.connects = this.connects.filter((c) => c.path !== connect.path && c.key !== connect.key);
53
+ }
54
+ this.connects.push(connect);
55
+ }
56
+ remove(connect: Connect) {
57
+ this.connects = this.connects.filter((c) => c.path !== connect.path && c.key !== connect.key);
58
+ }
59
+ getList() {
60
+ return this.connects.map((c) => {
61
+ return {
62
+ path: c.path,
63
+ key: c.key,
64
+ };
65
+ });
66
+ }
67
+ }
package/src/index.ts ADDED
@@ -0,0 +1,16 @@
1
+ export { Route, QueryRouter, QueryRouterServer } from './route.ts';
2
+ export { Connect, QueryConnect } from './connect.ts';
3
+
4
+ export type { RouteContext, RouteOpts } from './route.ts';
5
+
6
+ export type { Run } from './route.ts';
7
+
8
+ export { Server, handleServer } from './server/index.ts';
9
+ /**
10
+ * 自定义错误
11
+ */
12
+ export { CustomError } from './result/error.ts';
13
+
14
+ export { Rule, Schema, createSchema } from './validator/index.ts';
15
+
16
+ export { App } from './app.ts';
package/src/io.ts ADDED
@@ -0,0 +1,6 @@
1
+ // TODO: Implement IOApp
2
+ export class IOApp {
3
+ constructor() {
4
+ console.log('IoApp');
5
+ }
6
+ }
package/src/mod.ts ADDED
@@ -0,0 +1,13 @@
1
+ import { Route, QueryRouter, QueryRouterServer } from './route.ts';
2
+
3
+ export { App } from './app.ts';
4
+
5
+ export { Route, QueryRouter, QueryRouterServer };
6
+
7
+ export { Rule, Schema, createSchema } from './validator/index.ts';
8
+
9
+ export type { RouteContext, RouteOpts } from './route.ts';
10
+
11
+ export type { Run } from './route.ts';
12
+
13
+ export { CustomError } from './result/error.ts';
@@ -0,0 +1,67 @@
1
+ /** 自定义错误 */
2
+ export class CustomError extends Error {
3
+ code?: number;
4
+ data?: any;
5
+ message: string;
6
+ tips?: string;
7
+ constructor(code?: number | string, message?: string, tips?: string) {
8
+ super(message || String(code));
9
+ this.name = 'CustomError';
10
+ if (typeof code === 'number') {
11
+ this.code = code;
12
+ this.message = message;
13
+ } else {
14
+ this.code = 500;
15
+ this.message = code;
16
+ }
17
+ this.tips = tips;
18
+ // 这一步可不写,默认会保存堆栈追踪信息到自定义错误构造函数之前,
19
+ // 而如果写成 `Error.captureStackTrace(this)` 则自定义错误的构造函数也会被保存到堆栈追踪信息
20
+ Error.captureStackTrace(this, this.constructor);
21
+ }
22
+ static fromCode(code?: number) {
23
+ return new this(code);
24
+ }
25
+ static fromErrorData(code?: number, data?: any) {
26
+ const error = new this(code);
27
+ error.data = data;
28
+ return error;
29
+ }
30
+ static parseError(e: CustomError) {
31
+ return {
32
+ code: e?.code,
33
+ data: e?.data,
34
+ message: e?.message,
35
+ tips: e?.tips,
36
+ };
37
+ }
38
+ parse(e?: CustomError) {
39
+ if (e) {
40
+ return CustomError.parseError(e);
41
+ } else {
42
+ return {
43
+ code: e?.code,
44
+ data: e?.data,
45
+ message: e?.message,
46
+ tips: e?.tips,
47
+ };
48
+ }
49
+ }
50
+ }
51
+
52
+ /*
53
+ try {
54
+ //
55
+ } catch(e) {
56
+ if (e instanceof CustomError) {
57
+ const errorInfo = e.parse();
58
+ if (dev) {
59
+ return {
60
+ error: errorInfo,
61
+ };
62
+ } else {
63
+ return errorInfo;
64
+ }
65
+ }
66
+ }
67
+ */
@@ -0,0 +1 @@
1
+ export * from './error.ts';