@onebots/core 0.5.0 → 1.0.0
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.
- package/README.md +3 -3
- package/lib/__tests__/config-validator.test.d.ts +4 -0
- package/lib/__tests__/config-validator.test.js +152 -0
- package/lib/__tests__/di-container.test.d.ts +4 -0
- package/lib/__tests__/di-container.test.js +114 -0
- package/lib/__tests__/errors.test.d.ts +4 -0
- package/lib/__tests__/errors.test.js +111 -0
- package/lib/__tests__/integration.test.d.ts +5 -0
- package/lib/__tests__/integration.test.js +112 -0
- package/lib/__tests__/lifecycle.test.d.ts +4 -0
- package/lib/__tests__/lifecycle.test.js +163 -0
- package/lib/account.js +2 -1
- package/lib/base-app.d.ts +14 -3
- package/lib/base-app.js +215 -137
- package/lib/config-validator.d.ts +45 -0
- package/lib/config-validator.js +173 -0
- package/lib/db.d.ts +1 -1
- package/lib/di-container.d.ts +60 -0
- package/lib/di-container.js +103 -0
- package/lib/errors.d.ts +157 -0
- package/lib/errors.js +257 -0
- package/lib/index.d.ts +8 -4
- package/lib/index.js +11 -3
- package/lib/lifecycle.d.ts +75 -0
- package/lib/lifecycle.js +175 -0
- package/lib/logger.d.ts +76 -0
- package/lib/logger.js +156 -0
- package/lib/protocol.d.ts +2 -3
- package/lib/protocol.js +4 -0
- package/lib/rate-limiter.d.ts +88 -0
- package/lib/rate-limiter.js +196 -0
- package/lib/registry.js +0 -5
- package/lib/retry.d.ts +87 -0
- package/lib/retry.js +205 -0
- package/lib/router.d.ts +43 -6
- package/lib/router.js +139 -12
- package/lib/types.d.ts +1 -0
- package/lib/types.js +2 -1
- package/package.json +19 -10
package/lib/retry.js
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 重试策略和网络请求重试机制
|
|
3
|
+
* 提供统一的重试逻辑,支持指数退避
|
|
4
|
+
*/
|
|
5
|
+
const DEFAULT_OPTIONS = {
|
|
6
|
+
maxRetries: 3,
|
|
7
|
+
initialDelay: 1000,
|
|
8
|
+
maxDelay: 30000,
|
|
9
|
+
backoffMultiplier: 2,
|
|
10
|
+
jitter: true,
|
|
11
|
+
shouldRetry: (error) => {
|
|
12
|
+
// 默认对网络错误和超时错误进行重试
|
|
13
|
+
const message = error.message.toLowerCase();
|
|
14
|
+
return (message.includes('timeout') ||
|
|
15
|
+
message.includes('network') ||
|
|
16
|
+
message.includes('econnreset') ||
|
|
17
|
+
message.includes('econnrefused') ||
|
|
18
|
+
message.includes('socket') ||
|
|
19
|
+
message.includes('fetch failed'));
|
|
20
|
+
},
|
|
21
|
+
onRetry: () => { },
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* 计算下一次重试的延迟时间
|
|
25
|
+
*/
|
|
26
|
+
function calculateDelay(attempt, options) {
|
|
27
|
+
let delay = options.initialDelay * Math.pow(options.backoffMultiplier, attempt - 1);
|
|
28
|
+
// 添加随机抖动(±25%)
|
|
29
|
+
if (options.jitter) {
|
|
30
|
+
const jitterFactor = 0.75 + Math.random() * 0.5;
|
|
31
|
+
delay *= jitterFactor;
|
|
32
|
+
}
|
|
33
|
+
return Math.min(delay, options.maxDelay);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* 等待指定时间
|
|
37
|
+
*/
|
|
38
|
+
function sleep(ms) {
|
|
39
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* 带重试的异步函数执行器
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* const result = await retry(
|
|
47
|
+
* () => fetch('https://api.example.com/data'),
|
|
48
|
+
* { maxRetries: 3, initialDelay: 1000 }
|
|
49
|
+
* );
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export async function retry(fn, options = {}) {
|
|
53
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
54
|
+
let lastError;
|
|
55
|
+
for (let attempt = 1; attempt <= opts.maxRetries + 1; attempt++) {
|
|
56
|
+
try {
|
|
57
|
+
return await fn();
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
61
|
+
// 检查是否还有重试机会
|
|
62
|
+
if (attempt > opts.maxRetries) {
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
// 检查是否应该重试
|
|
66
|
+
if (!opts.shouldRetry(lastError, attempt)) {
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
// 计算延迟并等待
|
|
70
|
+
const delay = calculateDelay(attempt, opts);
|
|
71
|
+
opts.onRetry(lastError, attempt, delay);
|
|
72
|
+
await sleep(delay);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
throw lastError;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* 创建一个带重试功能的函数包装器
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```typescript
|
|
82
|
+
* const fetchWithRetry = withRetry(fetch, { maxRetries: 3 });
|
|
83
|
+
* const response = await fetchWithRetry('https://api.example.com/data');
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
export function withRetry(fn, options = {}) {
|
|
87
|
+
return ((...args) => {
|
|
88
|
+
return retry(() => fn(...args), options);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* 重试策略预设
|
|
93
|
+
*/
|
|
94
|
+
export const RetryPresets = {
|
|
95
|
+
/** 快速重试:3次,1秒起始 */
|
|
96
|
+
fast: {
|
|
97
|
+
maxRetries: 3,
|
|
98
|
+
initialDelay: 1000,
|
|
99
|
+
maxDelay: 5000,
|
|
100
|
+
backoffMultiplier: 1.5,
|
|
101
|
+
},
|
|
102
|
+
/** 标准重试:5次,2秒起始 */
|
|
103
|
+
standard: {
|
|
104
|
+
maxRetries: 5,
|
|
105
|
+
initialDelay: 2000,
|
|
106
|
+
maxDelay: 30000,
|
|
107
|
+
backoffMultiplier: 2,
|
|
108
|
+
},
|
|
109
|
+
/** 持久重试:10次,5秒起始 */
|
|
110
|
+
persistent: {
|
|
111
|
+
maxRetries: 10,
|
|
112
|
+
initialDelay: 5000,
|
|
113
|
+
maxDelay: 60000,
|
|
114
|
+
backoffMultiplier: 2,
|
|
115
|
+
},
|
|
116
|
+
/** WebSocket 重连:无限重试 */
|
|
117
|
+
websocket: {
|
|
118
|
+
maxRetries: Infinity,
|
|
119
|
+
initialDelay: 1000,
|
|
120
|
+
maxDelay: 30000,
|
|
121
|
+
backoffMultiplier: 2,
|
|
122
|
+
jitter: true,
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* 连接管理器 - 用于 WebSocket 等长连接的重连管理
|
|
127
|
+
*/
|
|
128
|
+
export class ConnectionManager {
|
|
129
|
+
connect;
|
|
130
|
+
reconnectAttempt = 0;
|
|
131
|
+
reconnectTimer = null;
|
|
132
|
+
isConnecting = false;
|
|
133
|
+
options;
|
|
134
|
+
constructor(connect, options = RetryPresets.websocket) {
|
|
135
|
+
this.connect = connect;
|
|
136
|
+
this.options = { ...DEFAULT_OPTIONS, ...options };
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* 开始连接
|
|
140
|
+
*/
|
|
141
|
+
async start() {
|
|
142
|
+
this.stop();
|
|
143
|
+
this.reconnectAttempt = 0;
|
|
144
|
+
await this.tryConnect();
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* 停止连接和重连
|
|
148
|
+
*/
|
|
149
|
+
stop() {
|
|
150
|
+
if (this.reconnectTimer) {
|
|
151
|
+
clearTimeout(this.reconnectTimer);
|
|
152
|
+
this.reconnectTimer = null;
|
|
153
|
+
}
|
|
154
|
+
this.isConnecting = false;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* 触发重连
|
|
158
|
+
*/
|
|
159
|
+
scheduleReconnect(error) {
|
|
160
|
+
if (this.isConnecting)
|
|
161
|
+
return;
|
|
162
|
+
this.reconnectAttempt++;
|
|
163
|
+
if (this.reconnectAttempt > this.options.maxRetries) {
|
|
164
|
+
console.error('[ConnectionManager] 达到最大重试次数,停止重连');
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const delay = calculateDelay(this.reconnectAttempt, this.options);
|
|
168
|
+
console.log(`[ConnectionManager] 将在 ${Math.round(delay / 1000)}s 后进行第 ${this.reconnectAttempt} 次重连`);
|
|
169
|
+
if (error) {
|
|
170
|
+
this.options.onRetry(error, this.reconnectAttempt, delay);
|
|
171
|
+
}
|
|
172
|
+
this.reconnectTimer = setTimeout(() => {
|
|
173
|
+
this.tryConnect();
|
|
174
|
+
}, delay);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* 重置重连计数(连接成功时调用)
|
|
178
|
+
*/
|
|
179
|
+
resetAttempts() {
|
|
180
|
+
this.reconnectAttempt = 0;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* 获取当前重连次数
|
|
184
|
+
*/
|
|
185
|
+
getAttempts() {
|
|
186
|
+
return this.reconnectAttempt;
|
|
187
|
+
}
|
|
188
|
+
async tryConnect() {
|
|
189
|
+
if (this.isConnecting)
|
|
190
|
+
return;
|
|
191
|
+
this.isConnecting = true;
|
|
192
|
+
try {
|
|
193
|
+
await this.connect();
|
|
194
|
+
this.resetAttempts();
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
198
|
+
console.error('[ConnectionManager] 连接失败:', err.message);
|
|
199
|
+
this.scheduleReconnect(err);
|
|
200
|
+
}
|
|
201
|
+
finally {
|
|
202
|
+
this.isConnecting = false;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
package/lib/router.d.ts
CHANGED
|
@@ -1,16 +1,53 @@
|
|
|
1
1
|
import KoaRouter from "@koa/router";
|
|
2
2
|
import { WebSocketServer, WebSocket, ServerOptions } from "ws";
|
|
3
3
|
import { IncomingMessage, Server } from "http";
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
import type { RouterContext as KoaRouterContext } from "@koa/router";
|
|
5
|
+
import type { Request } from 'koa';
|
|
6
|
+
export type RouterContext = KoaRouterContext & {
|
|
7
|
+
request: Request & {
|
|
8
|
+
body: any;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
export type { Next } from "koa";
|
|
12
|
+
export declare class WsServer<T extends typeof WebSocket = typeof WebSocket, U extends typeof IncomingMessage = typeof IncomingMessage> extends WebSocketServer<T, U> {
|
|
13
|
+
readonly path: string;
|
|
14
|
+
constructor(options: WsServer.Options<T, U>);
|
|
6
15
|
}
|
|
7
16
|
export declare namespace WsServer {
|
|
8
|
-
interface Options<T extends typeof WebSocket
|
|
17
|
+
interface Options<T extends typeof WebSocket = typeof WebSocket, U extends typeof IncomingMessage = typeof IncomingMessage> extends ServerOptions<T, U> {
|
|
9
18
|
path: string;
|
|
10
19
|
}
|
|
11
20
|
}
|
|
12
21
|
export declare class Router extends KoaRouter {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
22
|
+
private wsMap;
|
|
23
|
+
private upgradeHandler?;
|
|
24
|
+
private readonly server;
|
|
25
|
+
constructor(server: Server, options?: ConstructorParameters<typeof KoaRouter>[0]);
|
|
26
|
+
/**
|
|
27
|
+
* 设置 WebSocket upgrade 处理器
|
|
28
|
+
*/
|
|
29
|
+
private setupUpgradeHandler;
|
|
30
|
+
/**
|
|
31
|
+
* 创建并注册一个新的 WebSocket 服务器
|
|
32
|
+
* @param path WebSocket 路径(客户端请求的完整路径,不受 router prefix 影响)
|
|
33
|
+
* @returns WebSocket 服务器实例
|
|
34
|
+
*/
|
|
35
|
+
ws(path: string): WsServer;
|
|
36
|
+
/**
|
|
37
|
+
* 移除 WebSocket 服务器
|
|
38
|
+
* @param path WebSocket 路径(客户端请求的完整路径)
|
|
39
|
+
*/
|
|
40
|
+
removeWs(path: string): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* 清理所有 WebSocket 服务器和事件监听器
|
|
43
|
+
*/
|
|
44
|
+
cleanup(): void;
|
|
45
|
+
/**
|
|
46
|
+
* 异步清理(返回 Promise)
|
|
47
|
+
*/
|
|
48
|
+
cleanupAsync(): Promise<void>;
|
|
49
|
+
/**
|
|
50
|
+
* 获取所有已注册的 WebSocket 路径
|
|
51
|
+
*/
|
|
52
|
+
getWsPaths(): string[];
|
|
16
53
|
}
|
package/lib/router.js
CHANGED
|
@@ -1,28 +1,155 @@
|
|
|
1
1
|
import KoaRouter from "@koa/router";
|
|
2
2
|
import { WebSocketServer } from "ws";
|
|
3
3
|
export class WsServer extends WebSocketServer {
|
|
4
|
+
path = '';
|
|
4
5
|
constructor(options) {
|
|
5
6
|
super(options);
|
|
7
|
+
// 设置 path(基类可能不会自动设置,因为使用了 noServer: true)
|
|
6
8
|
this.path = options.path;
|
|
7
9
|
}
|
|
8
10
|
}
|
|
9
11
|
export class Router extends KoaRouter {
|
|
10
|
-
|
|
12
|
+
wsMap = new Map();
|
|
13
|
+
upgradeHandler;
|
|
14
|
+
server;
|
|
11
15
|
constructor(server, options) {
|
|
12
16
|
super(options);
|
|
13
|
-
server
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
this.server = server;
|
|
18
|
+
this.setupUpgradeHandler();
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* 设置 WebSocket upgrade 处理器
|
|
22
|
+
*/
|
|
23
|
+
setupUpgradeHandler() {
|
|
24
|
+
this.upgradeHandler = (request, socket, head) => {
|
|
25
|
+
try {
|
|
26
|
+
const url = new URL(request.url || "/", `http://localhost`);
|
|
27
|
+
const pathname = url.pathname;
|
|
28
|
+
// WebSocket upgrade 请求的路径是客户端直接请求的完整路径
|
|
29
|
+
// 不受 Koa router prefix 影响,所以直接使用 pathname 进行匹配
|
|
30
|
+
const wsServer = this.wsMap.get(pathname);
|
|
31
|
+
if (!wsServer) {
|
|
32
|
+
// 没有找到匹配的 WebSocket 服务器,优雅地关闭连接
|
|
33
|
+
socket.write("HTTP/1.1 404 Not Found\r\n\r\n");
|
|
34
|
+
socket.destroy();
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
// 处理 WebSocket 升级
|
|
38
|
+
wsServer.handleUpgrade(request, socket, head, (ws) => {
|
|
39
|
+
wsServer.emit("connection", ws, request);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
// 处理 URL 解析错误
|
|
44
|
+
socket.write("HTTP/1.1 400 Bad Request\r\n\r\n");
|
|
45
|
+
socket.destroy();
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
this.server.on("upgrade", this.upgradeHandler);
|
|
22
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* 创建并注册一个新的 WebSocket 服务器
|
|
52
|
+
* @param path WebSocket 路径(客户端请求的完整路径,不受 router prefix 影响)
|
|
53
|
+
* @returns WebSocket 服务器实例
|
|
54
|
+
*/
|
|
23
55
|
ws(path) {
|
|
24
|
-
|
|
25
|
-
|
|
56
|
+
// 规范化路径:确保以 / 开头
|
|
57
|
+
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
58
|
+
// WebSocket 路径不受 Router prefix 影响
|
|
59
|
+
// 因为 WebSocket upgrade 是直接处理 HTTP upgrade 请求的,使用原始 pathname
|
|
60
|
+
// 所以直接使用传入的路径,不添加 prefix
|
|
61
|
+
const fullPath = normalizedPath;
|
|
62
|
+
// 检查路径是否已存在
|
|
63
|
+
if (this.wsMap.has(fullPath)) {
|
|
64
|
+
throw new Error(`WebSocket server already exists at path: ${fullPath}`);
|
|
65
|
+
}
|
|
66
|
+
// 创建 WebSocket 服务器
|
|
67
|
+
const wsServer = new WsServer({
|
|
68
|
+
noServer: true,
|
|
69
|
+
path: fullPath
|
|
70
|
+
});
|
|
71
|
+
// 存储完整路径(客户端请求的路径,不受 prefix 影响)
|
|
72
|
+
this.wsMap.set(fullPath, wsServer);
|
|
26
73
|
return wsServer;
|
|
27
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* 移除 WebSocket 服务器
|
|
77
|
+
* @param path WebSocket 路径(客户端请求的完整路径)
|
|
78
|
+
*/
|
|
79
|
+
removeWs(path) {
|
|
80
|
+
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
81
|
+
// 尝试匹配完整路径或相对路径
|
|
82
|
+
let fullPath;
|
|
83
|
+
if (this.opts.prefix && !normalizedPath.startsWith(this.opts.prefix)) {
|
|
84
|
+
fullPath = `${this.opts.prefix}${normalizedPath}`;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
fullPath = normalizedPath;
|
|
88
|
+
}
|
|
89
|
+
const wsServer = this.wsMap.get(fullPath) || this.wsMap.get(normalizedPath);
|
|
90
|
+
if (wsServer) {
|
|
91
|
+
// 关闭所有连接
|
|
92
|
+
wsServer.close();
|
|
93
|
+
this.wsMap.delete(fullPath);
|
|
94
|
+
if (fullPath !== normalizedPath && this.wsMap.has(normalizedPath)) {
|
|
95
|
+
this.wsMap.delete(normalizedPath);
|
|
96
|
+
}
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* 清理所有 WebSocket 服务器和事件监听器
|
|
103
|
+
*/
|
|
104
|
+
cleanup() {
|
|
105
|
+
// 关闭所有 WebSocket 服务器
|
|
106
|
+
for (const wsServer of this.wsMap.values()) {
|
|
107
|
+
try {
|
|
108
|
+
wsServer.close();
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
// 忽略关闭错误
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
this.wsMap.clear();
|
|
115
|
+
// 移除 upgrade 事件监听器
|
|
116
|
+
if (this.upgradeHandler) {
|
|
117
|
+
this.server.removeListener("upgrade", this.upgradeHandler);
|
|
118
|
+
this.upgradeHandler = undefined;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* 异步清理(返回 Promise)
|
|
123
|
+
*/
|
|
124
|
+
async cleanupAsync() {
|
|
125
|
+
return new Promise((resolve) => {
|
|
126
|
+
// 关闭所有 WebSocket 服务器
|
|
127
|
+
const closePromises = [];
|
|
128
|
+
for (const wsServer of this.wsMap.values()) {
|
|
129
|
+
closePromises.push(new Promise((resolve) => {
|
|
130
|
+
try {
|
|
131
|
+
wsServer.close(() => resolve());
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
resolve();
|
|
135
|
+
}
|
|
136
|
+
}));
|
|
137
|
+
}
|
|
138
|
+
Promise.all(closePromises).then(() => {
|
|
139
|
+
this.wsMap.clear();
|
|
140
|
+
// 移除 upgrade 事件监听器
|
|
141
|
+
if (this.upgradeHandler) {
|
|
142
|
+
this.server.removeListener("upgrade", this.upgradeHandler);
|
|
143
|
+
this.upgradeHandler = undefined;
|
|
144
|
+
}
|
|
145
|
+
resolve();
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* 获取所有已注册的 WebSocket 路径
|
|
151
|
+
*/
|
|
152
|
+
getWsPaths() {
|
|
153
|
+
return Array.from(this.wsMap.keys());
|
|
154
|
+
}
|
|
28
155
|
}
|
package/lib/types.d.ts
CHANGED
package/lib/types.js
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
// 导入 koa-body 的类型定义,它会自动扩展 Request 接口
|
|
2
|
+
import 'koa-body';
|
package/package.json
CHANGED
|
@@ -1,13 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onebots/core",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "IMHelper 核心抽象层,提供适配器、协议、账号等基础接口和类型",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"types": "lib/index.d.ts",
|
|
8
8
|
"engines": {
|
|
9
9
|
"node": ">=22"
|
|
10
10
|
},
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./lib/index.d.ts",
|
|
14
|
+
"import": "./lib/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./types": {
|
|
17
|
+
"types": "./lib/types.d.ts",
|
|
18
|
+
"import": "./lib/types.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
11
21
|
"keywords": [
|
|
12
22
|
"onebot",
|
|
13
23
|
"qq",
|
|
@@ -19,11 +29,10 @@
|
|
|
19
29
|
"author": "凉菜",
|
|
20
30
|
"license": "MIT",
|
|
21
31
|
"devDependencies": {
|
|
22
|
-
"@types/koa": "^
|
|
23
|
-
"@types/koa-basic-auth": "^2.0.6",
|
|
24
|
-
"@types/koa-bodyparser": "^4.3.7",
|
|
25
|
-
"@types/koa__router": "^8.0.11",
|
|
32
|
+
"@types/koa": "^3.0.1",
|
|
26
33
|
"@types/node": "^22.7.3",
|
|
34
|
+
"@types/koa-basic-auth": "^2.0.6",
|
|
35
|
+
"@types/koa__router": "^12.0.5",
|
|
27
36
|
"@types/ws": "^8.5.3",
|
|
28
37
|
"tsc-alias": "latest",
|
|
29
38
|
"tsconfig-paths": "latest",
|
|
@@ -36,18 +45,18 @@
|
|
|
36
45
|
"/lib/**/*.d.ts"
|
|
37
46
|
],
|
|
38
47
|
"dependencies": {
|
|
39
|
-
"@koa/router": "^
|
|
48
|
+
"@koa/router": "^15.1.0",
|
|
40
49
|
"js-yaml": "^4.1.0",
|
|
41
|
-
"koa": "^
|
|
50
|
+
"koa": "^3.1.1",
|
|
42
51
|
"koa-basic-auth": "^4.0.0",
|
|
43
|
-
"koa-
|
|
52
|
+
"koa-body": "^7.0.0",
|
|
44
53
|
"log4js": "^6.5.2",
|
|
45
54
|
"reflect-metadata": "^0.1.13",
|
|
46
55
|
"ws": "^8.16.0"
|
|
47
56
|
},
|
|
48
57
|
"scripts": {
|
|
49
58
|
"start": "node .",
|
|
50
|
-
"build": "tsc --project tsconfig.json && tsc-alias -p tsconfig.json",
|
|
59
|
+
"build": "rm -f *.tsbuildinfo && tsc --project tsconfig.json && tsc-alias -p tsconfig.json",
|
|
51
60
|
"clean": "rm -rf lib *.tsbuildinfo"
|
|
52
61
|
}
|
|
53
62
|
}
|