@frp-bridge/core 0.0.3 → 0.0.4
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/dist/index.d.ts +1288 -756
- package/dist/index.js +258 -0
- package/package.json +7 -11
- package/dist/index.d.mts +0 -1216
- package/dist/index.mjs +0 -8
package/dist/index.d.ts
CHANGED
|
@@ -1,177 +1,719 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { EventEmitter } from 'node:events';
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
3
2
|
|
|
3
|
+
//#region src/runtime/contracts.d.ts
|
|
4
4
|
type Awaitable<T> = T | Promise<T>;
|
|
5
5
|
type RuntimeMode = 'client' | 'server';
|
|
6
6
|
type RuntimeStatus = 'idle' | 'starting' | 'running' | 'stopping' | 'error';
|
|
7
7
|
interface RuntimeContext {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
logger?: RuntimeLogger;
|
|
8
|
+
id: string;
|
|
9
|
+
mode: RuntimeMode;
|
|
10
|
+
workDir: string;
|
|
11
|
+
platform: string;
|
|
12
|
+
clock?: () => number;
|
|
14
13
|
}
|
|
15
14
|
interface RuntimeLogger {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
debug: (message: string, context?: Record<string, unknown>) => void;
|
|
16
|
+
info: (message: string, context?: Record<string, unknown>) => void;
|
|
17
|
+
warn: (message: string, context?: Record<string, unknown>) => void;
|
|
18
|
+
error: (message: string, context?: Record<string, unknown>) => void;
|
|
20
19
|
}
|
|
21
20
|
interface RuntimeState {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
status: RuntimeStatus;
|
|
22
|
+
version: number;
|
|
23
|
+
lastAppliedAt?: number;
|
|
24
|
+
lastError?: RuntimeError;
|
|
26
25
|
}
|
|
27
26
|
interface CommandMetadata {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
requestId?: string;
|
|
28
|
+
correlationId?: string;
|
|
29
|
+
author?: string;
|
|
30
|
+
issuedAt?: number;
|
|
32
31
|
}
|
|
33
32
|
interface RuntimeCommand<TPayload = unknown> {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
name: string;
|
|
34
|
+
payload: TPayload;
|
|
35
|
+
metadata?: CommandMetadata;
|
|
37
36
|
}
|
|
38
37
|
interface CommandResult<TResult = unknown> {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
38
|
+
status: CommandStatus;
|
|
39
|
+
version?: number;
|
|
40
|
+
events?: RuntimeEvent[];
|
|
41
|
+
result?: TResult;
|
|
42
|
+
error?: RuntimeError;
|
|
43
|
+
snapshot?: ConfigSnapshot;
|
|
45
44
|
}
|
|
46
45
|
type CommandStatus = 'success' | 'failed' | 'pending';
|
|
47
46
|
interface RuntimeQuery<TPayload = unknown> {
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
name: string;
|
|
48
|
+
payload?: TPayload;
|
|
50
49
|
}
|
|
51
50
|
interface QueryResult<TResult = unknown> {
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
result: TResult;
|
|
52
|
+
version: number;
|
|
54
53
|
}
|
|
55
54
|
interface RuntimeEvent<TPayload = unknown> {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
55
|
+
type: string;
|
|
56
|
+
timestamp: number;
|
|
57
|
+
version?: number;
|
|
58
|
+
payload?: TPayload;
|
|
60
59
|
}
|
|
61
60
|
interface RuntimeError {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
code: RuntimeErrorCode;
|
|
62
|
+
message: string;
|
|
63
|
+
details?: Record<string, unknown>;
|
|
65
64
|
}
|
|
66
|
-
type RuntimeErrorCode = 'VALIDATION_ERROR' | 'RUNTIME_ERROR' | 'SYSTEM_ERROR' | 'PORT_CONFLICT' | 'RPC_NOT_AVAILABLE' | 'RPC_ERROR';
|
|
65
|
+
type RuntimeErrorCode = 'VALIDATION_ERROR' | 'RUNTIME_ERROR' | 'SYSTEM_ERROR' | 'PORT_CONFLICT' | 'RPC_NOT_AVAILABLE' | 'RPC_ERROR' | 'MODE_ERROR' | 'UNKNOWN_ERROR';
|
|
67
66
|
interface ConfigSnapshot {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
67
|
+
version: number;
|
|
68
|
+
checksum: string;
|
|
69
|
+
appliedAt: number;
|
|
70
|
+
author?: string;
|
|
71
|
+
summary?: string;
|
|
73
72
|
}
|
|
74
73
|
interface SnapshotStorage {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
save: (snapshot: ConfigSnapshot) => Awaitable<void>;
|
|
75
|
+
load: (version: number) => Awaitable<ConfigSnapshot | undefined>;
|
|
76
|
+
list: () => Awaitable<ConfigSnapshot[]>;
|
|
78
77
|
}
|
|
79
78
|
interface CommandHandlerContext {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
79
|
+
context: RuntimeContext;
|
|
80
|
+
state: RuntimeState;
|
|
81
|
+
emit: (events: RuntimeEvent[]) => void;
|
|
82
|
+
requestVersionBump: () => number;
|
|
84
83
|
}
|
|
85
84
|
type CommandHandler<TPayload = unknown, TResult = unknown> = (command: RuntimeCommand<TPayload>, ctx: CommandHandlerContext) => Awaitable<CommandResult<TResult>>;
|
|
86
85
|
type QueryHandler<TPayload = unknown, TResult = unknown> = (query: RuntimeQuery<TPayload>, ctx: RuntimeContext) => Awaitable<QueryResult<TResult>>;
|
|
87
86
|
interface RuntimeAdapters {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
storage?: SnapshotStorage;
|
|
88
|
+
commands?: Record<string, CommandHandler>;
|
|
89
|
+
queries?: Record<string, QueryHandler>;
|
|
91
90
|
}
|
|
92
|
-
|
|
91
|
+
//#endregion
|
|
92
|
+
//#region src/runtime/runtime.d.ts
|
|
93
93
|
declare class FrpRuntime {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
*
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
94
|
+
private readonly context;
|
|
95
|
+
private readonly storage?;
|
|
96
|
+
private readonly commandHandlers;
|
|
97
|
+
private readonly queryHandlers;
|
|
98
|
+
private eventBuffer;
|
|
99
|
+
private commandQueue;
|
|
100
|
+
private state;
|
|
101
|
+
constructor(context: RuntimeContext, adapters?: RuntimeAdapters);
|
|
102
|
+
registerCommand(name: string, handler: CommandHandler): void;
|
|
103
|
+
registerQuery(name: string, handler: QueryHandler): void;
|
|
104
|
+
execute<TPayload, TResult = unknown>(command: RuntimeCommand<TPayload>): Promise<CommandResult<TResult>>;
|
|
105
|
+
query<TPayload, TResult = unknown>(query: RuntimeQuery<TPayload>): Promise<QueryResult<TResult>>;
|
|
106
|
+
snapshot(): RuntimeState;
|
|
107
|
+
drainEvents(): RuntimeEvent[];
|
|
108
|
+
private runCommand;
|
|
109
|
+
private pushEvents;
|
|
110
|
+
private bumpVersion;
|
|
111
|
+
private persistSnapshot;
|
|
112
|
+
private normalizeError;
|
|
113
|
+
private buildError;
|
|
114
|
+
private now;
|
|
115
|
+
}
|
|
116
|
+
//#endregion
|
|
117
|
+
//#region ../types/src/common.d.ts
|
|
118
|
+
/**
|
|
119
|
+
* FRP 通用配置类型定义
|
|
120
|
+
* 基于 frp 官方文档: https://gofrp.org/zh-cn/docs/reference/common/
|
|
121
|
+
*/
|
|
122
|
+
/** 日志级别类型 */
|
|
123
|
+
type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error';
|
|
124
|
+
/** 日志配置 */
|
|
125
|
+
interface LogConfig {
|
|
126
|
+
/** 日志输出文件路径,如果为 console,则会将日志打印在标准输出中 */
|
|
127
|
+
to?: string;
|
|
128
|
+
/** 日志级别,可选值为 trace, debug, info, warn, error,默认级别为 info */
|
|
129
|
+
level?: LogLevel;
|
|
130
|
+
/** 日志文件最多保留天数,默认为 3 天 */
|
|
131
|
+
maxDays?: number;
|
|
132
|
+
/** 禁用标准输出中的日志颜色 */
|
|
133
|
+
disablePrintColor?: boolean;
|
|
134
|
+
}
|
|
135
|
+
/** TLS 配置 */
|
|
136
|
+
interface TLSConfig {
|
|
137
|
+
/** TLS 证书文件路径 */
|
|
138
|
+
certFile: string;
|
|
139
|
+
/** TLS 密钥文件路径 */
|
|
140
|
+
keyFile: string;
|
|
141
|
+
/** CA 证书文件路径 */
|
|
142
|
+
trustedCaFile?: string;
|
|
143
|
+
/** TLS Server 名称 */
|
|
144
|
+
serverName?: string;
|
|
145
|
+
}
|
|
146
|
+
/** Web 服务器配置 */
|
|
147
|
+
interface WebServerConfig {
|
|
148
|
+
/** webServer 监听地址,默认为 127.0.0.1 */
|
|
149
|
+
addr?: string;
|
|
150
|
+
/** webServer 监听端口 */
|
|
151
|
+
port: number;
|
|
152
|
+
/** HTTP BasicAuth 用户名 */
|
|
153
|
+
user?: string;
|
|
154
|
+
/** HTTP BasicAuth 密码 */
|
|
155
|
+
password?: string;
|
|
156
|
+
/** 静态资源目录,Dashboard 使用的资源默认打包在二进制文件中,通过指定此参数使用自定义的静态资源 */
|
|
157
|
+
assetsDir?: string;
|
|
158
|
+
/** 启动 Go HTTP pprof,用于应用调试 */
|
|
159
|
+
pprofEnable?: boolean;
|
|
160
|
+
/** Dashboard 启用 HTTPS 的 TLS 相关配置 */
|
|
161
|
+
tls?: TLSConfig;
|
|
162
|
+
}
|
|
163
|
+
/** QUIC 协议选项 */
|
|
164
|
+
interface QUICOptions {
|
|
165
|
+
/** 保活周期,默认值为 10 秒 */
|
|
166
|
+
keepalivePeriod?: number;
|
|
167
|
+
/** 最大空闲超时时间,默认值为 30 秒 */
|
|
168
|
+
maxIdleTimeout?: number;
|
|
169
|
+
/** 最大传入流数量,默认值为 100000 */
|
|
170
|
+
maxIncomingStreams?: number;
|
|
171
|
+
}
|
|
172
|
+
/** 端口范围配置 */
|
|
173
|
+
interface PortsRange {
|
|
174
|
+
/** 起始端口 */
|
|
175
|
+
start?: number;
|
|
176
|
+
/** 终止端口 */
|
|
177
|
+
end?: number;
|
|
178
|
+
/** 单一端口 */
|
|
179
|
+
single?: number;
|
|
180
|
+
}
|
|
181
|
+
/** 文件数据源配置 */
|
|
182
|
+
interface FileSource {
|
|
183
|
+
/** 文件路径 */
|
|
184
|
+
path: string;
|
|
185
|
+
}
|
|
186
|
+
/** 数据源类型 */
|
|
187
|
+
type ValueSourceType = 'file';
|
|
188
|
+
/** 值数据源配置 */
|
|
189
|
+
interface ValueSource {
|
|
190
|
+
/** 数据源类型,目前仅支持 "file" */
|
|
191
|
+
type: ValueSourceType;
|
|
192
|
+
/** 文件数据源配置,当 type 为 "file" 时必填 */
|
|
193
|
+
file?: FileSource;
|
|
194
|
+
}
|
|
195
|
+
//#endregion
|
|
196
|
+
//#region ../types/src/server.d.ts
|
|
197
|
+
/** 鉴权方式类型 */
|
|
198
|
+
type AuthMethod = 'token' | 'oidc';
|
|
199
|
+
/** 鉴权信息附加范围类型 */
|
|
200
|
+
type AuthScope = 'HeartBeats' | 'NewWorkConns';
|
|
201
|
+
/** OIDC 服务端鉴权配置 */
|
|
202
|
+
interface AuthOIDCServerConfig {
|
|
203
|
+
/** OIDC 发行者 */
|
|
204
|
+
issuer?: string;
|
|
205
|
+
/** OIDC 受众 */
|
|
206
|
+
audience?: string;
|
|
207
|
+
/** 跳过过期检查 */
|
|
208
|
+
skipExpiryCheck?: boolean;
|
|
209
|
+
/** 跳过发行者检查 */
|
|
210
|
+
skipIssuerCheck?: boolean;
|
|
211
|
+
}
|
|
212
|
+
/** 服务端鉴权配置 */
|
|
213
|
+
interface AuthServerConfig {
|
|
214
|
+
/** 鉴权方式,可选值为 token 或 oidc,默认为 token */
|
|
215
|
+
method?: AuthMethod;
|
|
216
|
+
/** 鉴权信息附加范围,可选值为 HeartBeats 和 NewWorkConns */
|
|
217
|
+
additionalScopes?: AuthScope[];
|
|
218
|
+
/** 在 method 为 token 时生效,客户端需要设置一样的值才能鉴权通过。与 tokenSource 字段互斥 */
|
|
219
|
+
token?: string;
|
|
220
|
+
/** 从文件中加载 token 的配置。与 token 字段互斥 */
|
|
221
|
+
tokenSource?: ValueSource;
|
|
222
|
+
/** oidc 鉴权配置 */
|
|
223
|
+
oidc?: AuthOIDCServerConfig;
|
|
224
|
+
}
|
|
225
|
+
/** 服务端 TLS 配置 */
|
|
226
|
+
interface TLSServerConfig extends TLSConfig {
|
|
227
|
+
/** 是否只接受启用了 TLS 的客户端连接 */
|
|
228
|
+
force?: boolean;
|
|
229
|
+
}
|
|
230
|
+
/** 服务端传输层配置 */
|
|
231
|
+
interface ServerTransportConfig {
|
|
232
|
+
/** tcp mux 的心跳检查间隔时间,单位秒 */
|
|
233
|
+
tcpMuxKeepaliveInterval?: number;
|
|
234
|
+
/** 和客户端底层 TCP 连接的 keepalive 间隔时间,单位秒,配置为负数表示不启用 */
|
|
235
|
+
tcpKeepalive?: number;
|
|
236
|
+
/** 允许客户端设置的最大连接池大小,如果客户端配置的值大于此值,会被强制修改为最大值,默认为 5 */
|
|
237
|
+
maxPoolCount?: number;
|
|
238
|
+
/** 服务端和客户端心跳连接的超时时间,单位秒,默认为 90 秒 */
|
|
239
|
+
heartbeatTimeout?: number;
|
|
240
|
+
/** QUIC 协议配置参数 */
|
|
241
|
+
quic?: QUICOptions;
|
|
242
|
+
/** 服务端 TLS 协议配置 */
|
|
243
|
+
tls?: TLSServerConfig;
|
|
244
|
+
}
|
|
245
|
+
/** HTTP 插件选项 */
|
|
246
|
+
interface HTTPPluginOptions {
|
|
247
|
+
/** 插件名称 */
|
|
248
|
+
name: string;
|
|
249
|
+
/** 插件接口的地址 */
|
|
250
|
+
addr: string;
|
|
251
|
+
/** 插件接口的 Path */
|
|
252
|
+
path: string;
|
|
253
|
+
/** 插件需要生效的操作列表,具体可选值请参考服务端插件的说明文档 */
|
|
254
|
+
ops: string[];
|
|
255
|
+
/** 当插件地址为 HTTPS 协议时,是否校验插件的 TLS 证书,默认为不校验 */
|
|
256
|
+
tlsVerify?: boolean;
|
|
257
|
+
}
|
|
258
|
+
/** SSH 隧道网关配置 */
|
|
259
|
+
interface SSHTunnelGateway {
|
|
260
|
+
/** SSH 服务器监听端口 */
|
|
261
|
+
bindPort: number;
|
|
262
|
+
/** SSH 服务器私钥文件路径。若为空,frps将读取autoGenPrivateKeyPath路径下的私钥文件 */
|
|
263
|
+
privateKeyFile?: string;
|
|
264
|
+
/** 私钥文件自动生成路径,默认为./.autogen_ssh_key。若文件不存在或内容为空,frps将自动生成RSA私钥文件并存储到该路径 */
|
|
265
|
+
autoGenPrivateKeyPath?: string;
|
|
266
|
+
/** SSH 客户端授权密钥文件路径。若为空,则不进行SSH客户端鉴权认证。非空可实现SSH免密登录认证 */
|
|
267
|
+
authorizedKeysFile?: string;
|
|
268
|
+
}
|
|
269
|
+
/** 服务端配置 */
|
|
270
|
+
interface ServerConfig {
|
|
271
|
+
/** 鉴权配置 */
|
|
272
|
+
auth?: AuthServerConfig;
|
|
273
|
+
/** 服务端监听地址,用于接收 frpc 的连接,默认监听 0.0.0.0 */
|
|
274
|
+
bindAddr?: string;
|
|
275
|
+
/** 服务端监听端口,默认值为 7000 */
|
|
276
|
+
bindPort?: number;
|
|
277
|
+
/** 服务端监听 KCP 协议端口,用于接收配置了使用 KCP 协议的 frpc 连接 */
|
|
278
|
+
kcpBindPort?: number;
|
|
279
|
+
/** 服务端监听 QUIC 协议端口,用于接收配置了使用 QUIC 协议的 frpc 连接 */
|
|
280
|
+
quicBindPort?: number;
|
|
281
|
+
/** 代理监听地址,可以使代理监听在不同的网卡地址,默认情况下同 bindAddr */
|
|
282
|
+
proxyBindAddr?: string;
|
|
283
|
+
/** HTTP 类型代理监听的端口,启用后才能支持 HTTP 类型的代理 */
|
|
284
|
+
vhostHTTPPort?: number;
|
|
285
|
+
/** HTTP 类型代理在服务端的 ResponseHeader 超时时间,默认为 60s */
|
|
286
|
+
vhostHTTPTimeout?: number;
|
|
287
|
+
/** HTTPS 类型代理监听的端口,启用后才能支持 HTTPS 类型的代理 */
|
|
288
|
+
vhostHTTPSPort?: number;
|
|
289
|
+
/** tcpmux 类型且复用器为 httpconnect 的代理监听的端口 */
|
|
290
|
+
tcpmuxHTTPConnectPort?: number;
|
|
291
|
+
/** 对于 tcpmux 类型的代理是否透传 CONNECT 请求 */
|
|
292
|
+
tcpmuxPassthrough?: boolean;
|
|
293
|
+
/** 二级域名后缀 */
|
|
294
|
+
subDomainHost?: string;
|
|
295
|
+
/** 自定义 404 错误页面地址 */
|
|
296
|
+
custom404Page?: string;
|
|
297
|
+
/** ssh 隧道网关配置 */
|
|
298
|
+
sshTunnelGateway?: SSHTunnelGateway;
|
|
299
|
+
/** 服务端 Dashboard 配置 */
|
|
300
|
+
webServer?: WebServerConfig;
|
|
301
|
+
/** 是否提供 Prometheus 监控接口,需要同时启用了 webServer 后才会生效 */
|
|
302
|
+
enablePrometheus?: boolean;
|
|
303
|
+
/** 日志配置 */
|
|
304
|
+
log?: LogConfig;
|
|
305
|
+
/** 网络层配置 */
|
|
306
|
+
transport?: ServerTransportConfig;
|
|
307
|
+
/** 服务端返回详细错误信息给客户端,默认为 true */
|
|
308
|
+
detailedErrorsToClient?: boolean;
|
|
309
|
+
/** 限制单个客户端最大同时存在的代理数,默认无限制 */
|
|
310
|
+
maxPortsPerClient?: number;
|
|
311
|
+
/** 用户建立连接后等待客户端响应的超时时间,单位秒,默认为 10 秒 */
|
|
312
|
+
userConnTimeout?: number;
|
|
313
|
+
/** 代理 UDP 服务时支持的最大包长度,默认为 1500,服务端和客户端的值需要一致 */
|
|
314
|
+
udpPacketSize?: number;
|
|
315
|
+
/** 打洞策略数据的保留时间,默认为 168 小时,即 7 天 */
|
|
316
|
+
natholeAnalysisDataReserveHours?: number;
|
|
317
|
+
/** 允许代理绑定的服务端端口 */
|
|
318
|
+
allowPorts?: PortsRange[];
|
|
319
|
+
/** 服务端 HTTP 插件配置 */
|
|
320
|
+
httpPlugins?: HTTPPluginOptions[];
|
|
321
|
+
}
|
|
322
|
+
//#endregion
|
|
323
|
+
//#region ../types/src/client.d.ts
|
|
324
|
+
/** 客户端传输协议类型 */
|
|
325
|
+
type ClientTransportProtocol = 'tcp' | 'kcp' | 'quic' | 'websocket' | 'wss';
|
|
326
|
+
/** OIDC 客户端鉴权配置 */
|
|
327
|
+
interface AuthOIDCClientConfig {
|
|
328
|
+
/** OIDC 客户端 ID */
|
|
329
|
+
clientID?: string;
|
|
330
|
+
/** OIDC 客户端密钥 */
|
|
331
|
+
clientSecret?: string;
|
|
332
|
+
/** OIDC audience 参数 */
|
|
333
|
+
audience?: string;
|
|
334
|
+
/** OIDC scope 参数 */
|
|
335
|
+
scope?: string;
|
|
336
|
+
/** OIDC 令牌端点 URL */
|
|
337
|
+
tokenEndpointURL?: string;
|
|
338
|
+
/** 附加的端点参数 */
|
|
339
|
+
additionalEndpointParams?: Record<string, string>;
|
|
340
|
+
/** 信任的 CA 证书文件路径,用于验证 OIDC 服务器的 TLS 证书 */
|
|
341
|
+
trustedCaFile?: string;
|
|
342
|
+
/** 跳过 TLS 证书验证,不推荐在生产环境使用 */
|
|
343
|
+
insecureSkipVerify?: boolean;
|
|
344
|
+
/** 访问 OIDC 令牌端点时使用的代理服务器 URL */
|
|
345
|
+
proxyURL?: string;
|
|
346
|
+
}
|
|
347
|
+
/** 客户端鉴权配置 */
|
|
348
|
+
interface AuthClientConfig {
|
|
349
|
+
/** 鉴权方式,可选值为 token 或 oidc,默认为 token */
|
|
350
|
+
method?: AuthMethod;
|
|
351
|
+
/** 鉴权信息附加范围,可选值为 HeartBeats 和 NewWorkConns */
|
|
352
|
+
additionalScopes?: AuthScope[];
|
|
353
|
+
/** 在 method 为 token 时生效,客户端需要设置一样的值才能鉴权通过。与 tokenSource 字段互斥 */
|
|
354
|
+
token?: string;
|
|
355
|
+
/** 从文件中加载 token 的配置。与 token 字段互斥 */
|
|
356
|
+
tokenSource?: ValueSource;
|
|
357
|
+
/** oidc 鉴权配置 */
|
|
358
|
+
oidc?: AuthOIDCClientConfig;
|
|
359
|
+
}
|
|
360
|
+
/** 客户端 TLS 配置 */
|
|
361
|
+
interface TLSClientConfig extends TLSConfig {
|
|
362
|
+
/** 是否和服务端之间启用 TLS 连接,默认启用 */
|
|
363
|
+
enable?: boolean;
|
|
364
|
+
/** 启用 TLS 连接时,不发送 0x17 特殊字节。默认为 true。当配置为 true 时,无法和 vhostHTTPSPort 端口复用 */
|
|
365
|
+
disableCustomTLSFirstByte?: boolean;
|
|
366
|
+
}
|
|
367
|
+
/** 客户端传输层配置 */
|
|
368
|
+
interface ClientTransportConfig {
|
|
369
|
+
/** 和 frps 之间的通信协议,可选值为 tcp, kcp, quic, websocket, wss。默认为 tcp */
|
|
370
|
+
protocol?: ClientTransportProtocol;
|
|
371
|
+
/** 连接服务端的超时时间,默认为 10s */
|
|
372
|
+
dialServerTimeout?: number;
|
|
373
|
+
/** 和服务端底层 TCP 连接的 keepalive 间隔时间,单位秒 */
|
|
374
|
+
dialServerKeepalive?: number;
|
|
375
|
+
/** 连接服务端时所绑定的本地 IP */
|
|
376
|
+
connectServerLocalIP?: string;
|
|
377
|
+
/** 连接服务端使用的代理地址,格式为 {protocol}://user:passwd@192.168.1.128:8080 protocol 目前支持 http、socks5、ntlm */
|
|
378
|
+
proxyURL?: string;
|
|
379
|
+
/** 连接池大小 */
|
|
380
|
+
poolCount?: number;
|
|
381
|
+
/** TCP 多路复用,默认启用 */
|
|
382
|
+
tcpMux?: boolean;
|
|
383
|
+
/** tcp_mux 的心跳检查间隔时间 */
|
|
384
|
+
tcpMuxKeepaliveInterval?: number;
|
|
385
|
+
/** QUIC 协议配置参数 */
|
|
386
|
+
quic?: QUICOptions;
|
|
387
|
+
/** 向服务端发送心跳包的间隔时间,默认为 30s。建议启用 tcp_mux_keepalive_interval,将此值设置为 -1 */
|
|
388
|
+
heartbeatInterval?: number;
|
|
389
|
+
/** 和服务端心跳的超时时间,默认为 90s */
|
|
390
|
+
heartbeatTimeout?: number;
|
|
391
|
+
/** 客户端 TLS 协议配置 */
|
|
392
|
+
tls?: TLSClientConfig;
|
|
393
|
+
}
|
|
394
|
+
/** 虚拟网络配置 */
|
|
395
|
+
interface VirtualNetConfig {
|
|
396
|
+
/** 虚拟网络接口的 IP 地址和网段,格式为 CIDR (例如 "100.86.0.1/24") */
|
|
397
|
+
address: string;
|
|
398
|
+
}
|
|
399
|
+
/** 客户端通用配置 */
|
|
400
|
+
interface ClientCommonConfig {
|
|
401
|
+
/** 客户端鉴权配置 */
|
|
402
|
+
auth?: AuthClientConfig;
|
|
403
|
+
/** 用户名,设置此参数后,代理名称会被修改为 {user}.{proxyName},避免代理名称和其他用户冲突 */
|
|
404
|
+
user?: string;
|
|
405
|
+
/** 连接服务端的地址 */
|
|
406
|
+
serverAddr?: string;
|
|
407
|
+
/** 连接服务端的端口,默认为 7000 */
|
|
408
|
+
serverPort?: number;
|
|
409
|
+
/** xtcp 打洞所需的 stun 服务器地址,默认为 stun.easyvoip.com:3478 */
|
|
410
|
+
natHoleStunServer?: string;
|
|
411
|
+
/** 使用 DNS 服务器地址,默认使用系统配置的 DNS 服务器,指定此参数可以强制替换为自定义的 DNS 服务器地址 */
|
|
412
|
+
dnsServer?: string;
|
|
413
|
+
/** 第一次登陆失败后是否退出,默认为 true */
|
|
414
|
+
loginFailExit?: boolean;
|
|
415
|
+
/** 指定启用部分代理,当配置了较多代理,但是只希望启用其中部分时可以通过此参数指定,默认为全部启用 */
|
|
416
|
+
start?: string[];
|
|
417
|
+
/** 日志配置 */
|
|
418
|
+
log?: LogConfig;
|
|
419
|
+
/** 客户端 AdminServer 配置 */
|
|
420
|
+
webServer?: WebServerConfig;
|
|
421
|
+
/** 客户端网络层配置 */
|
|
422
|
+
transport?: ClientTransportConfig;
|
|
423
|
+
/** 虚拟网络配置,Alpha 特性 */
|
|
424
|
+
virtualNet?: VirtualNetConfig;
|
|
425
|
+
/** 特性门控,用于启用或禁用实验性功能 */
|
|
426
|
+
featureGates?: Record<string, boolean>;
|
|
427
|
+
/** 代理 UDP 服务时支持的最大包长度,默认为 1500,服务端和客户端需要保持配置一致 */
|
|
428
|
+
udpPacketSize?: number;
|
|
429
|
+
/** 附加元数据,会传递给服务端插件,提供附加能力 */
|
|
430
|
+
metadatas?: Record<string, string>;
|
|
431
|
+
/** 指定额外的配置文件目录,其中的 proxy 和 visitor 配置会被读取加载 */
|
|
432
|
+
includes?: string[];
|
|
433
|
+
}
|
|
434
|
+
/** 客户端配置 */
|
|
435
|
+
interface ClientConfig extends ClientCommonConfig {}
|
|
436
|
+
//#endregion
|
|
437
|
+
//#region ../types/src/proxy.d.ts
|
|
438
|
+
/**
|
|
439
|
+
* FRP Proxy configuration types
|
|
440
|
+
* Based on: https://gofrp.org/zh-cn/docs/reference/proxy-config/
|
|
441
|
+
*/
|
|
442
|
+
/** Proxy type enum */
|
|
443
|
+
declare enum ProxyType {
|
|
444
|
+
/** TCP proxy */
|
|
445
|
+
TCP = "tcp",
|
|
446
|
+
/** UDP proxy */
|
|
447
|
+
UDP = "udp",
|
|
448
|
+
/** HTTP proxy */
|
|
449
|
+
HTTP = "http",
|
|
450
|
+
/** HTTPS proxy */
|
|
451
|
+
HTTPS = "https",
|
|
452
|
+
/** TCP multiplexer proxy */
|
|
453
|
+
TCPMUX = "tcpmux",
|
|
454
|
+
/** Secure TCP proxy */
|
|
455
|
+
STCP = "stcp",
|
|
456
|
+
/** XTCP (P2P) proxy */
|
|
457
|
+
XTCP = "xtcp",
|
|
458
|
+
/** Secure UDP proxy */
|
|
459
|
+
SUDP = "sudp"
|
|
460
|
+
}
|
|
461
|
+
/** Load balancer strategy */
|
|
462
|
+
type LoadBalancerStrategy = 'random' | 'round_robin';
|
|
463
|
+
/** Base proxy configuration */
|
|
464
|
+
interface BaseProxyConfig {
|
|
465
|
+
/** Proxy name (unique) */
|
|
466
|
+
name: string;
|
|
467
|
+
/** Proxy type */
|
|
468
|
+
type: ProxyType;
|
|
469
|
+
/** Local IP to bind */
|
|
470
|
+
localIP?: string;
|
|
471
|
+
/** Local port */
|
|
472
|
+
localPort?: number;
|
|
473
|
+
/** Additional metadata */
|
|
474
|
+
annotations?: Record<string, string>;
|
|
475
|
+
/** Custom metadata passed to server plugins */
|
|
476
|
+
metadatas?: Record<string, string>;
|
|
477
|
+
/** Load balancer settings */
|
|
478
|
+
loadBalancer?: {
|
|
479
|
+
/** Load balancing strategy */strategy?: LoadBalancerStrategy; /** Health check configuration */
|
|
480
|
+
healthCheck?: {
|
|
481
|
+
/** Health check type */type?: ProxyType.TCP | ProxyType.HTTP; /** Health check timeout (seconds) */
|
|
482
|
+
timeoutSeconds?: number; /** Max failed checks before marking unhealthy */
|
|
483
|
+
maxFailed?: number; /** Check interval (seconds) */
|
|
484
|
+
intervalSeconds?: number; /** HTTP health check path */
|
|
485
|
+
path?: string;
|
|
132
486
|
};
|
|
487
|
+
};
|
|
488
|
+
/** Enable bandwidth limit */
|
|
489
|
+
transport?: {
|
|
490
|
+
/** Bandwidth limit (KB/s) */bandwidthLimit?: string; /** Bandwidth limit mode */
|
|
491
|
+
bandwidthLimitMode?: 'client' | 'server';
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
/** TCP proxy configuration */
|
|
495
|
+
interface TCPProxyConfig extends BaseProxyConfig {
|
|
496
|
+
type: ProxyType.TCP;
|
|
497
|
+
/** Remote port on server */
|
|
498
|
+
remotePort?: number;
|
|
499
|
+
}
|
|
500
|
+
/** UDP proxy configuration */
|
|
501
|
+
interface UDPProxyConfig extends BaseProxyConfig {
|
|
502
|
+
type: ProxyType.UDP;
|
|
503
|
+
/** Remote port on server */
|
|
504
|
+
remotePort?: number;
|
|
505
|
+
}
|
|
506
|
+
/** HTTP proxy configuration */
|
|
507
|
+
interface HTTPProxyConfig extends BaseProxyConfig {
|
|
508
|
+
type: ProxyType.HTTP;
|
|
509
|
+
/** Custom domain names */
|
|
510
|
+
customDomains?: string[];
|
|
511
|
+
/** Subdomain under server's subdomain_host */
|
|
512
|
+
subdomain?: string;
|
|
513
|
+
/** Locations to proxy */
|
|
514
|
+
locations?: string[];
|
|
515
|
+
/** Host header rewrite */
|
|
516
|
+
hostHeaderRewrite?: string;
|
|
517
|
+
/** HTTP username for basic auth */
|
|
518
|
+
httpUser?: string;
|
|
519
|
+
/** HTTP password for basic auth */
|
|
520
|
+
httpPassword?: string;
|
|
521
|
+
/** Request headers to set */
|
|
522
|
+
requestHeaders?: {
|
|
523
|
+
set?: Record<string, string>;
|
|
524
|
+
};
|
|
525
|
+
/** Response headers to set */
|
|
526
|
+
responseHeaders?: {
|
|
527
|
+
set?: Record<string, string>;
|
|
528
|
+
};
|
|
529
|
+
/** Route by HTTP user */
|
|
530
|
+
routeByHTTPUser?: string;
|
|
531
|
+
}
|
|
532
|
+
/** HTTPS proxy configuration */
|
|
533
|
+
interface HTTPSProxyConfig extends BaseProxyConfig {
|
|
534
|
+
type: ProxyType.HTTPS;
|
|
535
|
+
/** Custom domain names */
|
|
536
|
+
customDomains?: string[];
|
|
537
|
+
/** Subdomain under server's subdomain_host */
|
|
538
|
+
subdomain?: string;
|
|
539
|
+
}
|
|
540
|
+
/** TCPMUX proxy configuration */
|
|
541
|
+
interface TCPMUXProxyConfig extends BaseProxyConfig {
|
|
542
|
+
type: ProxyType.TCPMUX;
|
|
543
|
+
/** Multiplexer type */
|
|
544
|
+
multiplexer?: 'httpconnect';
|
|
545
|
+
/** Custom domain names */
|
|
546
|
+
customDomains?: string[];
|
|
547
|
+
/** Subdomain under server's subdomain_host */
|
|
548
|
+
subdomain?: string;
|
|
549
|
+
/** Route by HTTP user */
|
|
550
|
+
routeByHTTPUser?: string;
|
|
551
|
+
/** HTTP username */
|
|
552
|
+
httpUser?: string;
|
|
553
|
+
/** HTTP password */
|
|
554
|
+
httpPassword?: string;
|
|
555
|
+
}
|
|
556
|
+
/** STCP proxy configuration */
|
|
557
|
+
interface STCPProxyConfig extends BaseProxyConfig {
|
|
558
|
+
type: ProxyType.STCP;
|
|
559
|
+
/** Secret key shared with visitor */
|
|
560
|
+
secretKey?: string;
|
|
561
|
+
/** Allowed visitor users */
|
|
562
|
+
allowUsers?: string[];
|
|
563
|
+
}
|
|
564
|
+
/** XTCP proxy configuration */
|
|
565
|
+
interface XTCPProxyConfig extends BaseProxyConfig {
|
|
566
|
+
type: ProxyType.XTCP;
|
|
567
|
+
/** Secret key shared with visitor */
|
|
568
|
+
secretKey?: string;
|
|
569
|
+
/** Allowed visitor users */
|
|
570
|
+
allowUsers?: string[];
|
|
571
|
+
}
|
|
572
|
+
/** SUDP proxy configuration */
|
|
573
|
+
interface SUDPProxyConfig extends BaseProxyConfig {
|
|
574
|
+
type: ProxyType.SUDP;
|
|
575
|
+
/** Secret key shared with visitor */
|
|
576
|
+
secretKey?: string;
|
|
577
|
+
/** Allowed visitor users */
|
|
578
|
+
allowUsers?: string[];
|
|
579
|
+
}
|
|
580
|
+
/** Union type of all proxy configurations */
|
|
581
|
+
type ProxyConfig = TCPProxyConfig | UDPProxyConfig | HTTPProxyConfig | HTTPSProxyConfig | TCPMUXProxyConfig | STCPProxyConfig | XTCPProxyConfig | SUDPProxyConfig;
|
|
582
|
+
//#endregion
|
|
583
|
+
//#region ../types/src/node.d.ts
|
|
584
|
+
/** Node information structure */
|
|
585
|
+
interface NodeInfo$1 {
|
|
586
|
+
id: string;
|
|
587
|
+
ip: string;
|
|
588
|
+
port: number;
|
|
589
|
+
protocol: 'tcp' | 'udp';
|
|
590
|
+
serverAddr: string;
|
|
591
|
+
serverPort: number;
|
|
592
|
+
hostname?: string;
|
|
593
|
+
osType?: string;
|
|
594
|
+
osRelease?: string;
|
|
595
|
+
platform?: string;
|
|
596
|
+
cpuCores?: number;
|
|
597
|
+
memTotal?: number;
|
|
598
|
+
frpVersion?: string;
|
|
599
|
+
bridgeVersion?: string;
|
|
600
|
+
status: 'online' | 'offline' | 'connecting' | 'error';
|
|
601
|
+
lastHeartbeat?: number;
|
|
602
|
+
connectedAt?: number;
|
|
603
|
+
labels?: Record<string, string>;
|
|
604
|
+
metadata?: Record<string, unknown>;
|
|
605
|
+
token?: string;
|
|
606
|
+
tunnels?: ProxyConfig[];
|
|
607
|
+
createdAt: number;
|
|
608
|
+
updatedAt: number;
|
|
609
|
+
}
|
|
610
|
+
/** Payload for node registration (Client → Server) */
|
|
611
|
+
interface NodeRegisterPayload {
|
|
612
|
+
ip: string;
|
|
613
|
+
port: number;
|
|
614
|
+
serverAddr: string;
|
|
615
|
+
serverPort: number;
|
|
616
|
+
protocol: 'tcp' | 'udp';
|
|
617
|
+
hostname: string;
|
|
618
|
+
osType: string;
|
|
619
|
+
osRelease: string;
|
|
620
|
+
platform: string;
|
|
621
|
+
cpuCores: number;
|
|
622
|
+
memTotal: number;
|
|
623
|
+
frpVersion: string;
|
|
624
|
+
bridgeVersion: string;
|
|
625
|
+
token?: string;
|
|
626
|
+
}
|
|
627
|
+
/** Payload for node heartbeat (Client → Server) */
|
|
628
|
+
interface NodeHeartbeatPayload {
|
|
629
|
+
nodeId: string;
|
|
630
|
+
status: 'online' | 'error';
|
|
631
|
+
lastHeartbeat: number;
|
|
632
|
+
cpuCores?: number;
|
|
633
|
+
memTotal?: number;
|
|
634
|
+
}
|
|
635
|
+
/** Payload for tunnel synchronization (Client → Server) */
|
|
636
|
+
interface TunnelSyncPayload {
|
|
637
|
+
nodeId: string;
|
|
638
|
+
tunnels: ProxyConfig[];
|
|
639
|
+
timestamp: number;
|
|
640
|
+
}
|
|
641
|
+
/** Query parameters for listing nodes */
|
|
642
|
+
interface NodeListQuery {
|
|
643
|
+
page?: number;
|
|
644
|
+
pageSize?: number;
|
|
645
|
+
status?: NodeInfo$1['status'];
|
|
646
|
+
labels?: Record<string, string>;
|
|
647
|
+
search?: string;
|
|
648
|
+
}
|
|
649
|
+
/** Response for node list query */
|
|
650
|
+
interface NodeListResponse {
|
|
651
|
+
items: NodeInfo$1[];
|
|
652
|
+
total: number;
|
|
653
|
+
page: number;
|
|
654
|
+
pageSize: number;
|
|
655
|
+
hasMore: boolean;
|
|
656
|
+
}
|
|
657
|
+
/** Node statistics */
|
|
658
|
+
interface NodeStatistics {
|
|
659
|
+
total: number;
|
|
660
|
+
online: number;
|
|
661
|
+
offline: number;
|
|
662
|
+
connecting: number;
|
|
663
|
+
error: number;
|
|
664
|
+
}
|
|
665
|
+
//#endregion
|
|
666
|
+
//#region ../types/src/rpc.d.ts
|
|
667
|
+
interface RpcRequest$1 {
|
|
668
|
+
id: string;
|
|
669
|
+
method: string;
|
|
670
|
+
params: Record<string, unknown>;
|
|
671
|
+
timeout?: number;
|
|
672
|
+
}
|
|
673
|
+
//#endregion
|
|
674
|
+
//#region src/node/client-collector.d.ts
|
|
675
|
+
interface ClientCollectorOptions {
|
|
676
|
+
/** Node ID (set by server after registration) */
|
|
677
|
+
nodeId?: string;
|
|
678
|
+
/** Heartbeat interval in milliseconds (default: 30000) */
|
|
679
|
+
heartbeatInterval?: number;
|
|
133
680
|
}
|
|
134
681
|
/**
|
|
135
682
|
* Collects node information on client side
|
|
136
683
|
* Used in client mode to send system info and heartbeat to server
|
|
137
684
|
*/
|
|
138
685
|
declare class ClientNodeCollector {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
* Node Manager for server-side node management
|
|
163
|
-
* Handles node registration, heartbeat, tunnel registry, and queries
|
|
164
|
-
*/
|
|
165
|
-
|
|
686
|
+
private nodeId?;
|
|
687
|
+
private heartbeatInterval;
|
|
688
|
+
private readonly log;
|
|
689
|
+
private heartbeatTimer?;
|
|
690
|
+
constructor(options?: ClientCollectorOptions);
|
|
691
|
+
/** Set node ID after server registration */
|
|
692
|
+
setNodeId(nodeId: string): void;
|
|
693
|
+
/** Collect current node information */
|
|
694
|
+
collectNodeInfo(): Partial<NodeRegisterPayload>;
|
|
695
|
+
/** Collect heartbeat payload */
|
|
696
|
+
collectHeartbeat(): Partial<NodeHeartbeatPayload>;
|
|
697
|
+
/**
|
|
698
|
+
* Start periodic heartbeat collection
|
|
699
|
+
* Callback will be called at each interval with heartbeat payload
|
|
700
|
+
*/
|
|
701
|
+
startHeartbeat(callback: (payload: Partial<NodeHeartbeatPayload>) => void, interval?: number): void;
|
|
702
|
+
/** Stop periodic heartbeat collection */
|
|
703
|
+
stopHeartbeat(): void;
|
|
704
|
+
/** Check if heartbeat is running */
|
|
705
|
+
isHeartbeatRunning(): boolean;
|
|
706
|
+
}
|
|
707
|
+
//#endregion
|
|
708
|
+
//#region src/node/node-manager.d.ts
|
|
166
709
|
interface NodeManagerOptions {
|
|
167
|
-
|
|
168
|
-
logger?: Partial<RuntimeLogger>;
|
|
710
|
+
heartbeatTimeout?: number;
|
|
169
711
|
}
|
|
170
712
|
interface NodeStorage {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
713
|
+
save: (node: NodeInfo$1) => Promise<void> | void;
|
|
714
|
+
delete: (id: string) => Promise<void> | void;
|
|
715
|
+
load: (id: string) => Promise<NodeInfo$1 | undefined> | NodeInfo$1 | undefined;
|
|
716
|
+
list: () => Promise<NodeInfo$1[]> | NodeInfo$1[];
|
|
175
717
|
}
|
|
176
718
|
type NodeEvent = 'node:registered' | 'node:heartbeat' | 'node:unregistered' | 'node:statusChanged' | 'tunnel:synced';
|
|
177
719
|
/**
|
|
@@ -179,64 +721,60 @@ type NodeEvent = 'node:registered' | 'node:heartbeat' | 'node:unregistered' | 'n
|
|
|
179
721
|
* Stores node info, handles heartbeat, manages global tunnel registry, emits events
|
|
180
722
|
*/
|
|
181
723
|
declare class NodeManager extends EventEmitter {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
724
|
+
private context;
|
|
725
|
+
private nodes;
|
|
726
|
+
private heartbeatTimers;
|
|
727
|
+
private tunnelRegistry;
|
|
728
|
+
private storage?;
|
|
729
|
+
private heartbeatTimeout;
|
|
730
|
+
private readonly log;
|
|
731
|
+
constructor(context: RuntimeContext, options?: NodeManagerOptions, storage?: NodeStorage);
|
|
732
|
+
initialize(): Promise<void>;
|
|
733
|
+
/** Register a new node (called when client connects) */
|
|
734
|
+
registerNode(payload: NodeRegisterPayload): Promise<NodeInfo$1>;
|
|
735
|
+
/** Update node heartbeat and status */
|
|
736
|
+
updateHeartbeat(payload: NodeHeartbeatPayload): Promise<void>;
|
|
737
|
+
/** Unregister a node (called when client disconnects) */
|
|
738
|
+
unregisterNode(nodeId: string): Promise<void>;
|
|
739
|
+
/** Get node by id */
|
|
740
|
+
getNode(id: string): Promise<NodeInfo$1 | undefined>;
|
|
741
|
+
/** List nodes with pagination and filtering */
|
|
742
|
+
listNodes(query?: NodeListQuery): Promise<NodeListResponse>;
|
|
743
|
+
/** Get node statistics */
|
|
744
|
+
getStatistics(): Promise<NodeStatistics>;
|
|
745
|
+
/** Check if node exists */
|
|
746
|
+
hasNode(id: string): boolean;
|
|
747
|
+
/** Get all online nodes */
|
|
748
|
+
getOnlineNodes(): NodeInfo$1[];
|
|
749
|
+
/** Get all offline nodes */
|
|
750
|
+
getOfflineNodes(): NodeInfo$1[];
|
|
751
|
+
/** Get nodes by status */
|
|
752
|
+
getNodesByStatus(status: NodeInfo$1['status']): NodeInfo$1[];
|
|
753
|
+
/** Setup heartbeat timer for a node */
|
|
754
|
+
private setupHeartbeatTimer;
|
|
755
|
+
/** Clear heartbeat timer for a node */
|
|
756
|
+
private clearHeartbeatTimer;
|
|
757
|
+
/** Handle heartbeat timeout */
|
|
758
|
+
private handleHeartbeatTimeout;
|
|
759
|
+
/** Sync tunnels for a node (called when node connects or updates tunnels) */
|
|
760
|
+
syncTunnels(payload: TunnelSyncPayload): Promise<void>;
|
|
761
|
+
/** Get tunnels for a specific node */
|
|
762
|
+
getNodeTunnels(nodeId: string): ProxyConfig[];
|
|
763
|
+
/** Get all tunnels across all nodes */
|
|
764
|
+
getAllTunnels(): Map<string, ProxyConfig[]>;
|
|
765
|
+
/** Check if a remotePort is in use across all nodes (for conflict detection) */
|
|
766
|
+
isRemotePortInUse(remotePort: number, excludeNodeId?: string): {
|
|
767
|
+
inUse: boolean;
|
|
768
|
+
nodeId?: string;
|
|
769
|
+
tunnelName?: string;
|
|
770
|
+
};
|
|
771
|
+
/** Clear tunnels for a node (called when node disconnects) */
|
|
772
|
+
private clearNodeTunnels;
|
|
773
|
+
/** Update dispose method to clear tunnels */
|
|
774
|
+
dispose(): Promise<void>;
|
|
233
775
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
* File-based node storage implementation
|
|
237
|
-
* Persists node information to disk
|
|
238
|
-
*/
|
|
239
|
-
|
|
776
|
+
//#endregion
|
|
777
|
+
//#region src/node/file-node-storage.d.ts
|
|
240
778
|
/**
|
|
241
779
|
* Stores nodes in JSON files
|
|
242
780
|
* Directory structure:
|
|
@@ -245,51 +783,47 @@ declare class NodeManager extends EventEmitter {
|
|
|
245
783
|
* └── node-{id}.json (individual node data)
|
|
246
784
|
*/
|
|
247
785
|
declare class FileNodeStorage implements NodeStorage {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
* 配置合并方法 - core 包内部使用
|
|
266
|
-
* 将预设配置和用户配置合并成最终的 frp 配置
|
|
267
|
-
*/
|
|
268
|
-
|
|
786
|
+
private storagePath;
|
|
787
|
+
private indexPath;
|
|
788
|
+
private nodeDir;
|
|
789
|
+
constructor(storagePath: string);
|
|
790
|
+
/** Save or update a node */
|
|
791
|
+
save(node: NodeInfo$1): Promise<void>;
|
|
792
|
+
/** Delete a node */
|
|
793
|
+
delete(id: string): Promise<void>;
|
|
794
|
+
/** Load a single node */
|
|
795
|
+
load(id: string): Promise<NodeInfo$1 | undefined>;
|
|
796
|
+
/** Load all nodes */
|
|
797
|
+
list(): Promise<NodeInfo$1[]>;
|
|
798
|
+
/** Update the index of node IDs */
|
|
799
|
+
private updateIndex;
|
|
800
|
+
}
|
|
801
|
+
//#endregion
|
|
802
|
+
//#region src/config-merger.d.ts
|
|
269
803
|
/**
|
|
270
804
|
* 预设配置接口
|
|
271
805
|
*/
|
|
272
806
|
interface PresetConfig {
|
|
273
|
-
|
|
274
|
-
|
|
807
|
+
frps?: FrpsPresetConfig;
|
|
808
|
+
frpc?: FrpcPresetConfig;
|
|
275
809
|
}
|
|
276
810
|
interface FrpsPresetConfig {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
811
|
+
bindPort?: number;
|
|
812
|
+
vhostHTTPPort?: number;
|
|
813
|
+
vhostHTTPSPort?: number;
|
|
814
|
+
domain?: string;
|
|
815
|
+
dashboardPort?: number;
|
|
816
|
+
dashboardUser?: string;
|
|
817
|
+
dashboardPassword?: string;
|
|
818
|
+
authToken?: string;
|
|
819
|
+
subdomainHost?: string;
|
|
286
820
|
}
|
|
287
821
|
interface FrpcPresetConfig {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
822
|
+
serverAddr?: string;
|
|
823
|
+
serverPort?: number;
|
|
824
|
+
authToken?: string;
|
|
825
|
+
user?: string;
|
|
826
|
+
heartbeatInterval?: number;
|
|
293
827
|
}
|
|
294
828
|
/**
|
|
295
829
|
* 默认预设配置
|
|
@@ -302,55 +836,60 @@ declare function mergeConfigs(presetConfig: PresetConfig, userConfig: string, ty
|
|
|
302
836
|
/**
|
|
303
837
|
* 从 tunnels 数组生成并保存 FRP 配置文件
|
|
304
838
|
*/
|
|
305
|
-
declare function saveFrpConfigFile(configPath: string, tunnels: ProxyConfig[], presetConfig: PresetConfig, type: 'frps' | 'frpc'): void
|
|
839
|
+
declare function saveFrpConfigFile(configPath: string, tunnels: ProxyConfig[], presetConfig: PresetConfig, type: 'frps' | 'frpc'): Promise<void>;
|
|
306
840
|
/**
|
|
307
841
|
* 将配置对象转换为 TOML 格式
|
|
308
842
|
*/
|
|
309
|
-
declare function configToToml(config: Record<string,
|
|
843
|
+
declare function configToToml(config: Record<string, unknown>): string;
|
|
310
844
|
/**
|
|
311
845
|
* 验证预设配置
|
|
312
846
|
*/
|
|
313
847
|
declare function validatePresetConfig(config: PresetConfig, type: 'frps' | 'frpc'): {
|
|
314
|
-
|
|
315
|
-
|
|
848
|
+
valid: boolean;
|
|
849
|
+
errors: string[];
|
|
316
850
|
};
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
851
|
+
//#endregion
|
|
852
|
+
//#region src/process/controllers/process-controller.d.ts
|
|
853
|
+
type ProcessEventType = 'process:started' | 'process:stopped' | 'process:exited' | 'process:error' | 'status';
|
|
854
|
+
//#endregion
|
|
855
|
+
//#region src/process/index.d.ts
|
|
856
|
+
interface ProcessEvent {
|
|
857
|
+
type: ProcessEventType;
|
|
858
|
+
timestamp: number;
|
|
859
|
+
payload?: {
|
|
860
|
+
code?: number;
|
|
861
|
+
signal?: string;
|
|
862
|
+
error?: string;
|
|
863
|
+
pid?: number;
|
|
864
|
+
uptime?: number;
|
|
865
|
+
running?: boolean;
|
|
866
|
+
};
|
|
867
|
+
}
|
|
329
868
|
interface FrpProcessManagerOptions {
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
869
|
+
/** Working directory for FRP files */
|
|
870
|
+
workDir?: string;
|
|
871
|
+
/** Path to config file (overrides default) */
|
|
872
|
+
configPath?: string;
|
|
873
|
+
/** Config directory for preset configs (overrides workDir/config) */
|
|
874
|
+
configDir?: string;
|
|
875
|
+
/** FRP version (defaults to latest) */
|
|
876
|
+
version?: string;
|
|
877
|
+
/** Mode: client or server */
|
|
878
|
+
mode: 'client' | 'server';
|
|
340
879
|
}
|
|
341
880
|
interface NodeInfo {
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
881
|
+
/** Node ID */
|
|
882
|
+
id: string;
|
|
883
|
+
/** Node name */
|
|
884
|
+
name: string;
|
|
885
|
+
/** Server address */
|
|
886
|
+
serverAddr: string;
|
|
887
|
+
/** Server port */
|
|
888
|
+
serverPort?: number;
|
|
889
|
+
/** Authentication token */
|
|
890
|
+
token?: string;
|
|
891
|
+
/** Additional config */
|
|
892
|
+
config?: Partial<ClientConfig | ServerConfig>;
|
|
354
893
|
}
|
|
355
894
|
/**
|
|
356
895
|
* Manages FRP client/server lifecycle, config, and tunnels
|
|
@@ -363,87 +902,91 @@ interface NodeInfo {
|
|
|
363
902
|
* - BinaryManager: Binary file management
|
|
364
903
|
*/
|
|
365
904
|
declare class FrpProcessManager extends EventEmitter {
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
905
|
+
private readonly workDir;
|
|
906
|
+
private readonly mode;
|
|
907
|
+
private readonly specifiedVersion?;
|
|
908
|
+
private readonly configPath;
|
|
909
|
+
private readonly configDir;
|
|
910
|
+
private readonly processController;
|
|
911
|
+
private readonly configStore;
|
|
912
|
+
private readonly binaryManager;
|
|
913
|
+
private readonly presetConfigManager;
|
|
914
|
+
private tunnelManager;
|
|
915
|
+
private nodeManager;
|
|
916
|
+
private uptime;
|
|
917
|
+
private isManualStop;
|
|
918
|
+
constructor(options: FrpProcessManagerOptions);
|
|
919
|
+
/** Ensure version is fetched and binary path is set */
|
|
920
|
+
private ensureVersion;
|
|
921
|
+
/** Download FRP binary for current platform */
|
|
922
|
+
downloadFrpBinary(): Promise<void>;
|
|
923
|
+
/** Update FRP binary to latest version */
|
|
924
|
+
updateFrpBinary(newVersion?: string): Promise<void>;
|
|
925
|
+
/** Check if binary exists */
|
|
926
|
+
hasBinary(): boolean;
|
|
927
|
+
/** Get current configuration */
|
|
928
|
+
getConfig(): Promise<ClientConfig | ServerConfig | null>;
|
|
929
|
+
/** Update configuration */
|
|
930
|
+
updateConfig(config: Partial<ClientConfig | ServerConfig>): Promise<void>;
|
|
931
|
+
/** Backup configuration */
|
|
932
|
+
backupConfig(): Promise<string>;
|
|
933
|
+
/** Return the absolute config file path */
|
|
934
|
+
getConfigPath(): string;
|
|
935
|
+
/** Read raw config file contents */
|
|
936
|
+
getConfigRaw(): string | null;
|
|
937
|
+
/** Overwrite config file with provided content */
|
|
938
|
+
updateConfigRaw(content: string): void;
|
|
939
|
+
/** Start FRP process */
|
|
940
|
+
start(): Promise<void>;
|
|
941
|
+
/** Stop FRP process */
|
|
942
|
+
stop(): Promise<void>;
|
|
943
|
+
/** Check if process is running */
|
|
944
|
+
isRunning(): boolean;
|
|
945
|
+
/** Add node (for client mode) */
|
|
946
|
+
addNode(node: NodeInfo): Promise<void>;
|
|
947
|
+
/** Get node info */
|
|
948
|
+
getNode(): Promise<NodeInfo | null>;
|
|
949
|
+
/** Update node info */
|
|
950
|
+
updateNode(node: Partial<NodeInfo>): Promise<void>;
|
|
951
|
+
/** Remove node */
|
|
952
|
+
removeNode(): Promise<void>;
|
|
953
|
+
/** Add tunnel (proxy) */
|
|
954
|
+
addTunnel(proxy: ProxyConfig): Promise<void>;
|
|
955
|
+
/** Get tunnel by name */
|
|
956
|
+
getTunnel(name: string): Promise<ProxyConfig | null>;
|
|
957
|
+
/** Update tunnel */
|
|
958
|
+
updateTunnel(name: string, proxy: Partial<ProxyConfig>): Promise<void>;
|
|
959
|
+
/** Remove tunnel */
|
|
960
|
+
removeTunnel(name: string): Promise<void>;
|
|
961
|
+
/** List all tunnels */
|
|
962
|
+
listTunnels(): Promise<ProxyConfig[]>;
|
|
963
|
+
/**
|
|
964
|
+
* 生成 FRP 配置文件(合并预设配置和用户 tunnels)
|
|
965
|
+
* @param force 是否强制重新生成
|
|
966
|
+
*/
|
|
967
|
+
generateConfig(force?: boolean): Promise<void>;
|
|
968
|
+
/**
|
|
969
|
+
* 获取预设配置
|
|
970
|
+
*/
|
|
971
|
+
getPresetConfig(): PresetConfig;
|
|
972
|
+
/**
|
|
973
|
+
* 保存预设配置
|
|
974
|
+
*/
|
|
975
|
+
savePresetConfig(config: Record<string, any>): void;
|
|
976
|
+
/**
|
|
977
|
+
* Query current process status
|
|
978
|
+
*/
|
|
979
|
+
queryProcess(): {
|
|
980
|
+
pid?: number;
|
|
981
|
+
uptime: number;
|
|
982
|
+
};
|
|
983
|
+
/**
|
|
984
|
+
* Dispose and clean up resources
|
|
985
|
+
*/
|
|
986
|
+
dispose(): Promise<void>;
|
|
987
|
+
}
|
|
988
|
+
//#endregion
|
|
989
|
+
//#region src/rpc/message-types.d.ts
|
|
447
990
|
/**
|
|
448
991
|
* RPC 消息类型定义
|
|
449
992
|
* 提供类型安全的消息结构和类型守卫
|
|
@@ -452,28 +995,28 @@ declare class FrpProcessManager extends EventEmitter {
|
|
|
452
995
|
* RPC 消息类型枚举
|
|
453
996
|
*/
|
|
454
997
|
declare enum RpcMessageType {
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
998
|
+
REGISTER = "register",
|
|
999
|
+
COMMAND = "command",
|
|
1000
|
+
RESPONSE = "response",
|
|
1001
|
+
PING = "ping",
|
|
1002
|
+
PONG = "pong"
|
|
460
1003
|
}
|
|
461
1004
|
/**
|
|
462
1005
|
* 节点注册消息
|
|
463
1006
|
*/
|
|
464
1007
|
interface RegisterMessage {
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
1008
|
+
type: RpcMessageType.REGISTER;
|
|
1009
|
+
nodeId: string;
|
|
1010
|
+
payload: Record<string, unknown>;
|
|
468
1011
|
}
|
|
469
1012
|
/**
|
|
470
1013
|
* RPC 请求
|
|
471
1014
|
*/
|
|
472
1015
|
interface RpcRequest {
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
1016
|
+
id: string;
|
|
1017
|
+
method: string;
|
|
1018
|
+
params: Record<string, unknown>;
|
|
1019
|
+
timeout?: number;
|
|
477
1020
|
}
|
|
478
1021
|
/**
|
|
479
1022
|
* RPC 响应状态
|
|
@@ -483,27 +1026,27 @@ type RpcResponseStatus = 'success' | 'error';
|
|
|
483
1026
|
* RPC 响应
|
|
484
1027
|
*/
|
|
485
1028
|
interface RpcResponse {
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
1029
|
+
id: string;
|
|
1030
|
+
status: RpcResponseStatus;
|
|
1031
|
+
result?: unknown;
|
|
1032
|
+
error?: {
|
|
1033
|
+
code: string;
|
|
1034
|
+
message: string;
|
|
1035
|
+
};
|
|
493
1036
|
}
|
|
494
1037
|
/**
|
|
495
1038
|
* Ping 消息
|
|
496
1039
|
*/
|
|
497
1040
|
interface PingMessage {
|
|
498
|
-
|
|
499
|
-
|
|
1041
|
+
type: RpcMessageType.PING;
|
|
1042
|
+
timestamp: number;
|
|
500
1043
|
}
|
|
501
1044
|
/**
|
|
502
1045
|
* Pong 消息
|
|
503
1046
|
*/
|
|
504
1047
|
interface PongMessage {
|
|
505
|
-
|
|
506
|
-
|
|
1048
|
+
type: RpcMessageType.PONG;
|
|
1049
|
+
timestamp: number;
|
|
507
1050
|
}
|
|
508
1051
|
/**
|
|
509
1052
|
* 所有 RPC 消息类型
|
|
@@ -513,67 +1056,68 @@ type RpcMessage = RegisterMessage | RpcRequest | RpcResponse | PingMessage | Pon
|
|
|
513
1056
|
* Event-based RPC message type (matching document spec)
|
|
514
1057
|
*/
|
|
515
1058
|
interface EventRpcMessage {
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
1059
|
+
type: 'command' | 'event';
|
|
1060
|
+
action: string;
|
|
1061
|
+
payload: unknown;
|
|
1062
|
+
id?: string;
|
|
1063
|
+
targetNodeId?: string;
|
|
1064
|
+
[key: string]: unknown;
|
|
521
1065
|
}
|
|
522
1066
|
/**
|
|
523
1067
|
* Command message (frps -> frpc)
|
|
524
1068
|
*/
|
|
525
1069
|
interface CommandRpcMessage extends EventRpcMessage {
|
|
526
|
-
|
|
527
|
-
|
|
1070
|
+
type: 'command';
|
|
1071
|
+
id: string;
|
|
528
1072
|
}
|
|
529
1073
|
/**
|
|
530
1074
|
* Event message (frpc -> frps)
|
|
531
1075
|
*/
|
|
532
1076
|
interface EventRpcMessageEvent extends EventRpcMessage {
|
|
533
|
-
|
|
534
|
-
|
|
1077
|
+
type: 'event';
|
|
1078
|
+
id?: string;
|
|
535
1079
|
}
|
|
536
1080
|
/**
|
|
537
1081
|
* Tunnel add payload
|
|
538
1082
|
*/
|
|
539
1083
|
interface TunnelAddPayload {
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
1084
|
+
name: string;
|
|
1085
|
+
type: 'tcp' | 'http' | 'https' | 'stcp' | 'sudp' | 'xtcp';
|
|
1086
|
+
localPort: number;
|
|
1087
|
+
remotePort?: number;
|
|
1088
|
+
customDomains?: string[];
|
|
1089
|
+
subdomain?: string;
|
|
1090
|
+
nodeId?: string;
|
|
1091
|
+
[key: string]: unknown;
|
|
548
1092
|
}
|
|
549
1093
|
/**
|
|
550
1094
|
* Tunnel delete payload
|
|
551
1095
|
*/
|
|
552
1096
|
interface TunnelDeletePayload {
|
|
553
|
-
|
|
554
|
-
|
|
1097
|
+
name: string;
|
|
1098
|
+
nodeId?: string;
|
|
555
1099
|
}
|
|
556
1100
|
/**
|
|
557
1101
|
* Tunnel response payload
|
|
558
1102
|
*/
|
|
559
1103
|
interface TunnelResponsePayload {
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
1104
|
+
success: boolean;
|
|
1105
|
+
error?: string;
|
|
1106
|
+
tunnel?: TunnelAddPayload;
|
|
563
1107
|
}
|
|
564
1108
|
/**
|
|
565
1109
|
* Node delete payload
|
|
566
1110
|
*/
|
|
567
1111
|
interface NodeDeletePayload {
|
|
568
|
-
|
|
1112
|
+
name: string;
|
|
569
1113
|
}
|
|
570
1114
|
/**
|
|
571
1115
|
* Node response payload
|
|
572
1116
|
*/
|
|
573
1117
|
interface NodeResponsePayload {
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
1118
|
+
success: boolean;
|
|
1119
|
+
error?: string;
|
|
1120
|
+
deletedNode?: string;
|
|
577
1121
|
}
|
|
578
1122
|
/**
|
|
579
1123
|
* All message types including event-based
|
|
@@ -623,19 +1167,15 @@ declare function isTunnelDeletePayload(data: unknown): data is TunnelDeletePaylo
|
|
|
623
1167
|
* 类型守卫:检查是否为 NodeDeletePayload
|
|
624
1168
|
*/
|
|
625
1169
|
declare function isNodeDeletePayload(data: unknown): data is NodeDeletePayload;
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
* RPC 中间件系统
|
|
629
|
-
* 提供可扩展的请求处理管道
|
|
630
|
-
*/
|
|
631
|
-
|
|
1170
|
+
//#endregion
|
|
1171
|
+
//#region src/rpc/middleware.d.ts
|
|
632
1172
|
/**
|
|
633
1173
|
* 中间件上下文
|
|
634
1174
|
*/
|
|
635
1175
|
interface MiddlewareContext {
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
1176
|
+
request: RpcRequest;
|
|
1177
|
+
response: Partial<RpcResponse>;
|
|
1178
|
+
startTime: number;
|
|
639
1179
|
}
|
|
640
1180
|
/**
|
|
641
1181
|
* 中间件函数类型
|
|
@@ -645,17 +1185,13 @@ type MiddlewareFn = (context: MiddlewareContext, next: () => Promise<void>) => P
|
|
|
645
1185
|
* 中间件选项
|
|
646
1186
|
*/
|
|
647
1187
|
interface MiddlewareOptions {
|
|
648
|
-
|
|
649
|
-
|
|
1188
|
+
preHooks?: MiddlewareFn[];
|
|
1189
|
+
postHooks?: MiddlewareFn[];
|
|
650
1190
|
}
|
|
651
1191
|
/**
|
|
652
1192
|
* 日志中间件
|
|
653
1193
|
*/
|
|
654
|
-
declare function loggingMiddleware(
|
|
655
|
-
info?: (msg: string, data?: unknown) => void;
|
|
656
|
-
warn?: (msg: string, data?: unknown) => void;
|
|
657
|
-
error?: (msg: string, data?: unknown) => void;
|
|
658
|
-
}): MiddlewareFn;
|
|
1194
|
+
declare function loggingMiddleware(): MiddlewareFn;
|
|
659
1195
|
/**
|
|
660
1196
|
* 认证中间件
|
|
661
1197
|
*/
|
|
@@ -667,32 +1203,31 @@ declare function timeoutMiddleware(timeoutMs: number): MiddlewareFn;
|
|
|
667
1203
|
/**
|
|
668
1204
|
* 错误处理中间件
|
|
669
1205
|
*/
|
|
670
|
-
declare function errorHandlerMiddleware(
|
|
671
|
-
error?: (msg: string, data?: unknown) => void;
|
|
672
|
-
}): MiddlewareFn;
|
|
1206
|
+
declare function errorHandlerMiddleware(): MiddlewareFn;
|
|
673
1207
|
/**
|
|
674
1208
|
* 中间件管道
|
|
675
1209
|
*/
|
|
676
1210
|
declare class MiddlewarePipeline {
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
}
|
|
695
|
-
|
|
1211
|
+
private middlewares;
|
|
1212
|
+
/**
|
|
1213
|
+
* 添加中间件
|
|
1214
|
+
*/
|
|
1215
|
+
use(middleware: MiddlewareFn): this;
|
|
1216
|
+
/**
|
|
1217
|
+
* 执行中间件管道
|
|
1218
|
+
*/
|
|
1219
|
+
execute(request: RpcRequest, handler: () => Promise<unknown>): Promise<Partial<RpcResponse>>;
|
|
1220
|
+
/**
|
|
1221
|
+
* 执行处理器
|
|
1222
|
+
*/
|
|
1223
|
+
private executeHandler;
|
|
1224
|
+
/**
|
|
1225
|
+
* 清空中间件
|
|
1226
|
+
*/
|
|
1227
|
+
clear(): void;
|
|
1228
|
+
}
|
|
1229
|
+
//#endregion
|
|
1230
|
+
//#region src/rpc/reconnect-strategy.d.ts
|
|
696
1231
|
/**
|
|
697
1232
|
* RPC 重连策略
|
|
698
1233
|
* 提供可配置的重连机制,包括指数退避
|
|
@@ -701,236 +1236,230 @@ declare class MiddlewarePipeline {
|
|
|
701
1236
|
* 重连策略接口
|
|
702
1237
|
*/
|
|
703
1238
|
interface ReconnectStrategy {
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
1239
|
+
/**
|
|
1240
|
+
* 判断是否应该重连
|
|
1241
|
+
*/
|
|
1242
|
+
shouldReconnect: (attempt: number) => boolean;
|
|
1243
|
+
/**
|
|
1244
|
+
* 获取重连延迟时间(毫秒)
|
|
1245
|
+
*/
|
|
1246
|
+
getDelay: (attempt: number) => number;
|
|
1247
|
+
/**
|
|
1248
|
+
* 达到最大重连次数时的回调
|
|
1249
|
+
*/
|
|
1250
|
+
onMaxAttemptsReached: () => void;
|
|
716
1251
|
}
|
|
717
1252
|
/**
|
|
718
1253
|
* 指数退避重连策略
|
|
719
1254
|
*/
|
|
720
1255
|
declare class ExponentialBackoffStrategy implements ReconnectStrategy {
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
shouldReconnect(attempt: number): boolean;
|
|
729
|
-
getDelay(attempt: number): number;
|
|
730
|
-
onMaxAttemptsReached(): void;
|
|
1256
|
+
private maxAttempts;
|
|
1257
|
+
private baseDelay;
|
|
1258
|
+
private maxDelay;
|
|
1259
|
+
constructor(maxAttempts?: number, baseDelay?: number, maxDelay?: number);
|
|
1260
|
+
shouldReconnect(attempt: number): boolean;
|
|
1261
|
+
getDelay(attempt: number): number;
|
|
1262
|
+
onMaxAttemptsReached(): void;
|
|
731
1263
|
}
|
|
732
1264
|
/**
|
|
733
1265
|
* 固定间隔重连策略
|
|
734
1266
|
*/
|
|
735
1267
|
declare class FixedIntervalStrategy implements ReconnectStrategy {
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
shouldReconnect(attempt: number): boolean;
|
|
743
|
-
getDelay(): number;
|
|
744
|
-
onMaxAttemptsReached(): void;
|
|
1268
|
+
private maxAttempts;
|
|
1269
|
+
private interval;
|
|
1270
|
+
constructor(maxAttempts?: number, interval?: number);
|
|
1271
|
+
shouldReconnect(attempt: number): boolean;
|
|
1272
|
+
getDelay(): number;
|
|
1273
|
+
onMaxAttemptsReached(): void;
|
|
745
1274
|
}
|
|
746
1275
|
/**
|
|
747
1276
|
* 线性增长重连策略
|
|
748
1277
|
*/
|
|
749
1278
|
declare class LinearBackoffStrategy implements ReconnectStrategy {
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
shouldReconnect(attempt: number): boolean;
|
|
759
|
-
getDelay(attempt: number): number;
|
|
760
|
-
onMaxAttemptsReached(): void;
|
|
1279
|
+
private maxAttempts;
|
|
1280
|
+
private baseDelay;
|
|
1281
|
+
private increment;
|
|
1282
|
+
private maxDelay;
|
|
1283
|
+
constructor(maxAttempts?: number, baseDelay?: number, increment?: number, maxDelay?: number);
|
|
1284
|
+
shouldReconnect(attempt: number): boolean;
|
|
1285
|
+
getDelay(attempt: number): number;
|
|
1286
|
+
onMaxAttemptsReached(): void;
|
|
761
1287
|
}
|
|
762
1288
|
/**
|
|
763
1289
|
* 无限重连策略(永不停止)
|
|
764
1290
|
*/
|
|
765
1291
|
declare class InfiniteReconnectStrategy implements ReconnectStrategy {
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
}
|
|
773
|
-
|
|
1292
|
+
private baseDelay;
|
|
1293
|
+
private maxDelay;
|
|
1294
|
+
constructor(baseDelay?: number, maxDelay?: number);
|
|
1295
|
+
shouldReconnect(): boolean;
|
|
1296
|
+
getDelay(attempt: number): number;
|
|
1297
|
+
onMaxAttemptsReached(): void;
|
|
1298
|
+
}
|
|
1299
|
+
//#endregion
|
|
1300
|
+
//#region src/rpc/rpc-client.d.ts
|
|
774
1301
|
interface RpcClientOptions {
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
logger?: Partial<RuntimeLogger>;
|
|
1302
|
+
url: string;
|
|
1303
|
+
nodeId: string;
|
|
1304
|
+
getRegisterPayload: () => Promise<NodeInfo$1> | NodeInfo$1;
|
|
1305
|
+
handleRequest: (req: RpcRequest$1) => Promise<unknown>;
|
|
1306
|
+
handleCommand?: (command: CommandRpcMessage) => Promise<unknown>;
|
|
1307
|
+
reconnectStrategy?: ReconnectStrategy;
|
|
782
1308
|
}
|
|
783
1309
|
declare class RpcClient {
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
}
|
|
816
|
-
|
|
1310
|
+
private readonly options;
|
|
1311
|
+
private ws;
|
|
1312
|
+
private reconnectTimer?;
|
|
1313
|
+
private reconnectAttempt;
|
|
1314
|
+
private readonly reconnectStrategy;
|
|
1315
|
+
private connectionState;
|
|
1316
|
+
private readonly log;
|
|
1317
|
+
constructor(options: RpcClientOptions);
|
|
1318
|
+
connect(): Promise<void>;
|
|
1319
|
+
disconnect(): void;
|
|
1320
|
+
/**
|
|
1321
|
+
* Get current connection state
|
|
1322
|
+
*/
|
|
1323
|
+
getConnectionState(): 'connecting' | 'connected' | 'disconnected';
|
|
1324
|
+
/**
|
|
1325
|
+
* Check if connected
|
|
1326
|
+
*/
|
|
1327
|
+
isConnected(): boolean;
|
|
1328
|
+
/**
|
|
1329
|
+
* Send an event message to server (matching document spec)
|
|
1330
|
+
*/
|
|
1331
|
+
sendEvent(event: EventRpcMessageEvent): boolean;
|
|
1332
|
+
private createConnection;
|
|
1333
|
+
private handleMessage;
|
|
1334
|
+
/**
|
|
1335
|
+
* Handle event-based command messages from server (matching document spec)
|
|
1336
|
+
*/
|
|
1337
|
+
private handleCommandEvent;
|
|
1338
|
+
private handleRpcRequest;
|
|
1339
|
+
private send;
|
|
1340
|
+
private scheduleReconnect;
|
|
1341
|
+
}
|
|
1342
|
+
//#endregion
|
|
1343
|
+
//#region src/rpc/rpc-server.d.ts
|
|
817
1344
|
/**
|
|
818
1345
|
* Command status for tracking
|
|
819
1346
|
*/
|
|
820
1347
|
interface RpcCommandStatus {
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
1348
|
+
commandId: string;
|
|
1349
|
+
nodeId: string;
|
|
1350
|
+
action: string;
|
|
1351
|
+
status: 'pending' | 'completed' | 'failed';
|
|
1352
|
+
result?: unknown;
|
|
1353
|
+
error?: string;
|
|
1354
|
+
timestamp: number;
|
|
828
1355
|
}
|
|
829
1356
|
interface RpcServerOptions {
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
logger?: Partial<RuntimeLogger>;
|
|
1357
|
+
port: number;
|
|
1358
|
+
heartbeatInterval?: number;
|
|
1359
|
+
validateToken?: (token: string | undefined, nodeId: string | undefined) => boolean | Promise<boolean>;
|
|
1360
|
+
authorize?: (nodeId: string, method: string) => boolean | Promise<boolean>;
|
|
1361
|
+
onRegister?: (nodeId: string, payload: NodeInfo$1) => void | Promise<void>;
|
|
1362
|
+
onEvent?: (nodeId: string, event: EventRpcMessage) => void | Promise<void>;
|
|
1363
|
+
commandTimeout?: number;
|
|
838
1364
|
}
|
|
839
1365
|
declare class RpcServer {
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
1366
|
+
private readonly options;
|
|
1367
|
+
private readonly clients;
|
|
1368
|
+
private readonly pendingRequests;
|
|
1369
|
+
private readonly commandStatuses;
|
|
1370
|
+
private readonly commandTimers;
|
|
1371
|
+
private readonly wsToNode;
|
|
1372
|
+
private heartbeatTimer?;
|
|
1373
|
+
private cleanupTimer?;
|
|
1374
|
+
private server?;
|
|
1375
|
+
private readonly defaultCommandTimeout;
|
|
1376
|
+
private readonly log;
|
|
1377
|
+
constructor(options: RpcServerOptions);
|
|
1378
|
+
start(): void;
|
|
1379
|
+
stop(): void;
|
|
1380
|
+
rpcCall(nodeId: string, method: string, params: Record<string, unknown>, timeout?: number): Promise<unknown>;
|
|
1381
|
+
/**
|
|
1382
|
+
* Send event-based message to a specific node (matching document spec)
|
|
1383
|
+
*/
|
|
1384
|
+
sendToNode(nodeId: string, message: EventRpcMessage): boolean;
|
|
1385
|
+
/**
|
|
1386
|
+
* Broadcast event-based message to all connected nodes
|
|
1387
|
+
*/
|
|
1388
|
+
broadcast(message: EventRpcMessage): void;
|
|
1389
|
+
/**
|
|
1390
|
+
* Get list of all online node IDs
|
|
1391
|
+
*/
|
|
1392
|
+
getOnlineNodes(): string[];
|
|
1393
|
+
/**
|
|
1394
|
+
* Check if a specific node is online
|
|
1395
|
+
*/
|
|
1396
|
+
isNodeOnline(nodeId: string): boolean;
|
|
1397
|
+
/**
|
|
1398
|
+
* Get the count of online nodes
|
|
1399
|
+
*/
|
|
1400
|
+
getOnlineNodeCount(): number;
|
|
1401
|
+
/**
|
|
1402
|
+
* Get command status by ID
|
|
1403
|
+
*/
|
|
1404
|
+
getRpcCommandStatus(commandId: string): RpcCommandStatus | undefined;
|
|
1405
|
+
/**
|
|
1406
|
+
* Get all command statuses
|
|
1407
|
+
*/
|
|
1408
|
+
getAllRpcCommandStatuses(): RpcCommandStatus[];
|
|
1409
|
+
/**
|
|
1410
|
+
* Clear completed/failed command statuses older than specified milliseconds
|
|
1411
|
+
*/
|
|
1412
|
+
clearOldStatuses(maxAge?: number): void;
|
|
1413
|
+
private handleMessage;
|
|
1414
|
+
/**
|
|
1415
|
+
* Handle event-based messages from clients
|
|
1416
|
+
*/
|
|
1417
|
+
private handleEventMessage;
|
|
1418
|
+
private handleRegister;
|
|
1419
|
+
private handleRpcResponse;
|
|
1420
|
+
private handleClose;
|
|
1421
|
+
private startHeartbeat;
|
|
1422
|
+
}
|
|
1423
|
+
//#endregion
|
|
1424
|
+
//#region src/bridge/initializer.d.ts
|
|
896
1425
|
interface FrpBridgeRuntimeOptions {
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
workDir?: string;
|
|
1426
|
+
id?: string;
|
|
1427
|
+
mode?: RuntimeMode;
|
|
1428
|
+
clock?: () => number;
|
|
1429
|
+
platform?: string;
|
|
1430
|
+
workDir?: string;
|
|
903
1431
|
}
|
|
904
1432
|
interface FrpBridgeProcessOptions extends Partial<Omit<FrpProcessManagerOptions, 'mode'>> {
|
|
905
|
-
|
|
1433
|
+
mode?: 'client' | 'server';
|
|
906
1434
|
}
|
|
907
1435
|
interface FrpBridgeRpcOptions {
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
}
|
|
922
|
-
|
|
1436
|
+
serverPort?: number;
|
|
1437
|
+
serverHeartbeatInterval?: number;
|
|
1438
|
+
serverValidateToken?: (token: string | undefined, nodeId: string | undefined) => boolean | Promise<boolean>;
|
|
1439
|
+
serverAuthorize?: (nodeId: string, method: string) => boolean | Promise<boolean>;
|
|
1440
|
+
serverOnRegister?: (nodeId: string, payload: NodeInfo$1) => void | Promise<void>;
|
|
1441
|
+
serverOnEvent?: (nodeId: string, event: EventRpcMessage) => void | Promise<void>;
|
|
1442
|
+
serverCommandTimeout?: number;
|
|
1443
|
+
clientUrl?: string;
|
|
1444
|
+
clientNodeId?: string;
|
|
1445
|
+
clientToken?: string;
|
|
1446
|
+
clientReconnectInterval?: number;
|
|
1447
|
+
getRegisterPayload?: () => Promise<NodeInfo$1> | NodeInfo$1;
|
|
1448
|
+
handleRequest?: (req: RpcRequest$1) => Promise<unknown>;
|
|
1449
|
+
}
|
|
1450
|
+
//#endregion
|
|
1451
|
+
//#region src/bridge/index.d.ts
|
|
923
1452
|
interface FrpBridgeOptions {
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
1453
|
+
mode: 'client' | 'server';
|
|
1454
|
+
workDir?: string;
|
|
1455
|
+
configPath?: string;
|
|
1456
|
+
runtime?: FrpBridgeRuntimeOptions;
|
|
1457
|
+
process?: FrpBridgeProcessOptions;
|
|
1458
|
+
rpc?: FrpBridgeRpcOptions;
|
|
1459
|
+
storage?: SnapshotStorage;
|
|
1460
|
+
commands?: Record<string, CommandHandler>;
|
|
1461
|
+
queries?: Record<string, QueryHandler>;
|
|
1462
|
+
eventSink?: (event: RuntimeEvent) => void;
|
|
934
1463
|
}
|
|
935
1464
|
/**
|
|
936
1465
|
* FrpBridge - Main facade class for managing FRP bridge operations.
|
|
@@ -947,51 +1476,52 @@ interface FrpBridgeOptions {
|
|
|
947
1476
|
* - Factory Pattern: Handlers created via factory functions
|
|
948
1477
|
*/
|
|
949
1478
|
declare class FrpBridge {
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
}
|
|
994
|
-
|
|
1479
|
+
private readonly runtime;
|
|
1480
|
+
private readonly process;
|
|
1481
|
+
private readonly mode;
|
|
1482
|
+
private readonly eventSink?;
|
|
1483
|
+
private readonly nodeManager?;
|
|
1484
|
+
private readonly clientCollector?;
|
|
1485
|
+
private readonly rpcServer?;
|
|
1486
|
+
private readonly rpcClient?;
|
|
1487
|
+
constructor(options: FrpBridgeOptions);
|
|
1488
|
+
/**
|
|
1489
|
+
* Execute a command
|
|
1490
|
+
*/
|
|
1491
|
+
execute<TPayload, TResult = unknown>(command: RuntimeCommand<TPayload>): Promise<CommandResult<TResult>>;
|
|
1492
|
+
/**
|
|
1493
|
+
* Execute a query
|
|
1494
|
+
*/
|
|
1495
|
+
query<TPayload, TResult = unknown>(query: RuntimeQuery<TPayload>): Promise<QueryResult<TResult>>;
|
|
1496
|
+
/**
|
|
1497
|
+
* Get current runtime state snapshot
|
|
1498
|
+
*/
|
|
1499
|
+
snapshot(): RuntimeState;
|
|
1500
|
+
/**
|
|
1501
|
+
* Drain and return all pending events
|
|
1502
|
+
*/
|
|
1503
|
+
drainEvents(): RuntimeEvent[];
|
|
1504
|
+
getProcessManager(): FrpProcessManager;
|
|
1505
|
+
getRuntime(): FrpRuntime;
|
|
1506
|
+
getNodeManager(): NodeManager | undefined;
|
|
1507
|
+
getClientCollector(): ClientNodeCollector | undefined;
|
|
1508
|
+
getRpcServer(): RpcServer | undefined;
|
|
1509
|
+
getRpcClient(): RpcClient | undefined;
|
|
1510
|
+
/**
|
|
1511
|
+
* Initialize all async components
|
|
1512
|
+
*/
|
|
1513
|
+
initialize(): Promise<void>;
|
|
1514
|
+
/**
|
|
1515
|
+
* Cleanup and dispose all resources
|
|
1516
|
+
*/
|
|
1517
|
+
dispose(): Promise<void>;
|
|
1518
|
+
/**
|
|
1519
|
+
* Forward runtime events to external event sink
|
|
1520
|
+
*/
|
|
1521
|
+
private forwardEvents;
|
|
1522
|
+
}
|
|
1523
|
+
//#endregion
|
|
1524
|
+
//#region src/constants/index.d.ts
|
|
995
1525
|
/**
|
|
996
1526
|
* Core constants
|
|
997
1527
|
*/
|
|
@@ -1001,156 +1531,155 @@ declare const GITHUB_OWNER = "fatedier";
|
|
|
1001
1531
|
declare const GITHUB_REPO = "frp";
|
|
1002
1532
|
/** Platform-specific binary names */
|
|
1003
1533
|
declare const BINARY_NAMES: {
|
|
1004
|
-
|
|
1005
|
-
|
|
1534
|
+
readonly client: "frpc.exe" | "frpc";
|
|
1535
|
+
readonly server: "frps.exe" | "frps";
|
|
1006
1536
|
};
|
|
1007
1537
|
/** Platform architecture mapping */
|
|
1008
1538
|
declare const ARCH_MAP: Record<string, string>;
|
|
1009
1539
|
/** Platform OS mapping */
|
|
1010
1540
|
declare const OS_MAP: Record<string, string>;
|
|
1011
|
-
|
|
1541
|
+
//#endregion
|
|
1542
|
+
//#region src/errors/base-error.d.ts
|
|
1012
1543
|
/**
|
|
1013
1544
|
* Base error class for all FRP Bridge errors
|
|
1014
1545
|
* Provides consistent error structure and handling
|
|
1015
1546
|
*/
|
|
1016
1547
|
declare abstract class FrpBridgeErrorBase extends Error {
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1548
|
+
/**
|
|
1549
|
+
* Error code for programmatic error handling
|
|
1550
|
+
*/
|
|
1551
|
+
abstract readonly code: string;
|
|
1552
|
+
/**
|
|
1553
|
+
* HTTP status code (optional, for API responses)
|
|
1554
|
+
*/
|
|
1555
|
+
readonly statusCode?: number;
|
|
1556
|
+
/**
|
|
1557
|
+
* Additional error details
|
|
1558
|
+
*/
|
|
1559
|
+
readonly details?: unknown;
|
|
1560
|
+
constructor(message: string, details?: unknown);
|
|
1561
|
+
/**
|
|
1562
|
+
* Convert error to plain object for serialization
|
|
1563
|
+
*/
|
|
1564
|
+
toJSON(): {
|
|
1565
|
+
code: string;
|
|
1566
|
+
message: string;
|
|
1567
|
+
statusCode?: number;
|
|
1568
|
+
details?: unknown;
|
|
1569
|
+
};
|
|
1039
1570
|
}
|
|
1040
1571
|
/**
|
|
1041
1572
|
* Generic error for uncategorized errors
|
|
1042
1573
|
*/
|
|
1043
1574
|
declare class GenericError extends FrpBridgeErrorBase {
|
|
1044
|
-
|
|
1045
|
-
|
|
1575
|
+
readonly code: string;
|
|
1576
|
+
constructor(message: string, code: string, details?: unknown);
|
|
1046
1577
|
}
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
* Categorized error classes for FRP Bridge
|
|
1050
|
-
* Each error extends FrpBridgeErrorBase directly
|
|
1051
|
-
*/
|
|
1052
|
-
|
|
1578
|
+
//#endregion
|
|
1579
|
+
//#region src/errors/categories.d.ts
|
|
1053
1580
|
/**
|
|
1054
1581
|
* Configuration errors (400 Bad Request)
|
|
1055
1582
|
*/
|
|
1056
1583
|
declare class ConfigNotFoundError extends FrpBridgeErrorBase {
|
|
1057
|
-
|
|
1058
|
-
|
|
1584
|
+
readonly code = "CONFIG_NOT_FOUND";
|
|
1585
|
+
readonly statusCode = 400;
|
|
1059
1586
|
}
|
|
1060
1587
|
declare class ConfigInvalidError extends FrpBridgeErrorBase {
|
|
1061
|
-
|
|
1062
|
-
|
|
1588
|
+
readonly code = "CONFIG_INVALID";
|
|
1589
|
+
readonly statusCode = 400;
|
|
1063
1590
|
}
|
|
1064
1591
|
/**
|
|
1065
1592
|
* Process errors
|
|
1066
1593
|
*/
|
|
1067
1594
|
declare class ProcessNotRunningError extends FrpBridgeErrorBase {
|
|
1068
|
-
|
|
1069
|
-
|
|
1595
|
+
readonly code = "PROCESS_NOT_RUNNING";
|
|
1596
|
+
readonly statusCode = 409;
|
|
1070
1597
|
}
|
|
1071
1598
|
declare class ProcessAlreadyRunningError extends FrpBridgeErrorBase {
|
|
1072
|
-
|
|
1073
|
-
|
|
1599
|
+
readonly code = "PROCESS_ALREADY_RUNNING";
|
|
1600
|
+
readonly statusCode = 409;
|
|
1074
1601
|
}
|
|
1075
1602
|
declare class ProcessStartFailedError extends FrpBridgeErrorBase {
|
|
1076
|
-
|
|
1077
|
-
|
|
1603
|
+
readonly code = "PROCESS_START_FAILED";
|
|
1604
|
+
readonly statusCode = 500;
|
|
1078
1605
|
}
|
|
1079
1606
|
/**
|
|
1080
1607
|
* Binary errors (500 Internal Server Error)
|
|
1081
1608
|
*/
|
|
1082
1609
|
declare class BinaryNotFoundError extends FrpBridgeErrorBase {
|
|
1083
|
-
|
|
1084
|
-
|
|
1610
|
+
readonly code = "BINARY_NOT_FOUND";
|
|
1611
|
+
readonly statusCode = 500;
|
|
1085
1612
|
}
|
|
1086
1613
|
declare class DownloadFailedError extends FrpBridgeErrorBase {
|
|
1087
|
-
|
|
1088
|
-
|
|
1614
|
+
readonly code = "DOWNLOAD_FAILED";
|
|
1615
|
+
readonly statusCode = 500;
|
|
1089
1616
|
}
|
|
1090
1617
|
declare class ExtractionFailedError extends FrpBridgeErrorBase {
|
|
1091
|
-
|
|
1092
|
-
|
|
1618
|
+
readonly code = "EXTRACTION_FAILED";
|
|
1619
|
+
readonly statusCode = 500;
|
|
1093
1620
|
}
|
|
1094
1621
|
/**
|
|
1095
1622
|
* Network/Version errors (503 Service Unavailable)
|
|
1096
1623
|
*/
|
|
1097
1624
|
declare class VersionFetchError extends FrpBridgeErrorBase {
|
|
1098
|
-
|
|
1099
|
-
|
|
1625
|
+
readonly code = "VERSION_FETCH_FAILED";
|
|
1626
|
+
readonly statusCode = 503;
|
|
1100
1627
|
}
|
|
1101
1628
|
/**
|
|
1102
1629
|
* Validation errors (400 Bad Request)
|
|
1103
1630
|
*/
|
|
1104
1631
|
declare class ValidationError extends FrpBridgeErrorBase {
|
|
1105
|
-
|
|
1106
|
-
|
|
1632
|
+
readonly code = "VALIDATION_ERROR";
|
|
1633
|
+
readonly statusCode = 400;
|
|
1107
1634
|
}
|
|
1108
1635
|
/**
|
|
1109
1636
|
* Mode/State errors (409 Conflict)
|
|
1110
1637
|
*/
|
|
1111
1638
|
declare class ModeError extends FrpBridgeErrorBase {
|
|
1112
|
-
|
|
1113
|
-
|
|
1639
|
+
readonly code = "MODE_ERROR";
|
|
1640
|
+
readonly statusCode = 409;
|
|
1114
1641
|
}
|
|
1115
1642
|
/**
|
|
1116
1643
|
* Resource not found (404 Not Found)
|
|
1117
1644
|
*/
|
|
1118
1645
|
declare class NotFoundError extends FrpBridgeErrorBase {
|
|
1119
|
-
|
|
1120
|
-
|
|
1646
|
+
readonly code = "NOT_FOUND";
|
|
1647
|
+
readonly statusCode = 404;
|
|
1121
1648
|
}
|
|
1122
1649
|
/**
|
|
1123
1650
|
* Platform errors (500 Internal Server Error)
|
|
1124
1651
|
*/
|
|
1125
1652
|
declare class PlatformError extends FrpBridgeErrorBase {
|
|
1126
|
-
|
|
1127
|
-
|
|
1653
|
+
readonly code = "UNSUPPORTED_PLATFORM";
|
|
1654
|
+
readonly statusCode = 500;
|
|
1128
1655
|
}
|
|
1129
|
-
|
|
1656
|
+
//#endregion
|
|
1657
|
+
//#region src/runtime/file-snapshot-storage.d.ts
|
|
1130
1658
|
declare class FileSnapshotStorage implements SnapshotStorage {
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1659
|
+
private readonly directory;
|
|
1660
|
+
constructor(directory: string);
|
|
1661
|
+
save(snapshot: ConfigSnapshot): Promise<void>;
|
|
1662
|
+
load(version: number): Promise<ConfigSnapshot | undefined>;
|
|
1663
|
+
list(): Promise<ConfigSnapshot[]>;
|
|
1664
|
+
private buildPath;
|
|
1137
1665
|
}
|
|
1138
|
-
|
|
1666
|
+
//#endregion
|
|
1667
|
+
//#region src/toml/index.d.ts
|
|
1139
1668
|
/**
|
|
1140
1669
|
* Unified TOML parsing and serialization module
|
|
1141
1670
|
* Wraps smol-toml with consistent error handling
|
|
1142
1671
|
*/
|
|
1143
1672
|
interface ParseOptions {
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1673
|
+
/**
|
|
1674
|
+
* Parse integers as BigInt
|
|
1675
|
+
*/
|
|
1676
|
+
integersAsBigInt?: boolean | 'asNeeded';
|
|
1148
1677
|
}
|
|
1149
1678
|
interface StringifyOptions {
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1679
|
+
/**
|
|
1680
|
+
* Serialize numbers as floats
|
|
1681
|
+
*/
|
|
1682
|
+
numbersAsFloat?: boolean;
|
|
1154
1683
|
}
|
|
1155
1684
|
/**
|
|
1156
1685
|
* Parse TOML string to JavaScript object
|
|
@@ -1180,22 +1709,29 @@ declare function isValidToml(content: string): boolean;
|
|
|
1180
1709
|
* @returns Parsed object or null if parsing fails
|
|
1181
1710
|
*/
|
|
1182
1711
|
declare function safeParse<T = Record<string, any>>(content: string): T | null;
|
|
1183
|
-
|
|
1712
|
+
//#endregion
|
|
1713
|
+
//#region src/utils/proxy-utils.d.ts
|
|
1184
1714
|
/**
|
|
1185
|
-
*
|
|
1715
|
+
* Proxy/_tunnel related utility functions
|
|
1186
1716
|
*/
|
|
1717
|
+
/**
|
|
1718
|
+
* Check if proxy type uses remotePort field
|
|
1719
|
+
*/
|
|
1720
|
+
declare function typeUsesRemotePort(type: string): boolean;
|
|
1721
|
+
//#endregion
|
|
1722
|
+
//#region src/utils/index.d.ts
|
|
1187
1723
|
/** Get latest FRP version from GitHub releases */
|
|
1188
1724
|
declare function getLatestVersion(): Promise<string>;
|
|
1189
1725
|
/** Get platform identifier for FRP release */
|
|
1190
1726
|
declare function getPlatform(): string;
|
|
1191
1727
|
/** Get GitHub release download URL */
|
|
1192
1728
|
declare function getDownloadUrl(version: string, platform: string): string;
|
|
1193
|
-
/** Download file from URL */
|
|
1194
|
-
declare function downloadFile(url: string, dest: string): Promise<void>;
|
|
1729
|
+
/** Download file from URL with redirect limit */
|
|
1730
|
+
declare function downloadFile(url: string, dest: string, maxRedirects?: number): Promise<void>;
|
|
1195
1731
|
/** Execute command */
|
|
1196
1732
|
declare function executeCommand(command: string): Promise<{
|
|
1197
|
-
|
|
1198
|
-
|
|
1733
|
+
stdout: string;
|
|
1734
|
+
stderr: string;
|
|
1199
1735
|
}>;
|
|
1200
1736
|
/** Check if command exists */
|
|
1201
1737
|
declare function commandExists(command: string): Promise<boolean>;
|
|
@@ -1204,13 +1740,9 @@ declare function ensureDir(dirPath: string): void;
|
|
|
1204
1740
|
/** Find existing FRP version in work directory */
|
|
1205
1741
|
declare function findExistingVersion(workDir: string): string | null;
|
|
1206
1742
|
/**
|
|
1207
|
-
*
|
|
1208
|
-
|
|
1209
|
-
declare function parseToml(content: string): Record<string, any>;
|
|
1210
|
-
/**
|
|
1211
|
-
* Convert JSON to TOML-like config
|
|
1743
|
+
* Omit undefined values from an object
|
|
1744
|
+
* Returns a new object with only defined values
|
|
1212
1745
|
*/
|
|
1213
|
-
declare function
|
|
1214
|
-
|
|
1215
|
-
export { ARCH_MAP, BINARY_NAMES, BinaryNotFoundError, ClientNodeCollector, ConfigInvalidError, ConfigNotFoundError, DEFAULT_PRESET_CONFIG, DownloadFailedError, FrpBridgeErrorBase as Error, ExponentialBackoffStrategy, ExtractionFailedError, FileNodeStorage, FileSnapshotStorage, FixedIntervalStrategy, FrpBridge,
|
|
1216
|
-
export type { AllRpcMessage, Awaitable, ClientCollectorOptions, CommandHandler, CommandHandlerContext, CommandMetadata, CommandResult, CommandRpcMessage, CommandStatus, ConfigSnapshot, EventRpcMessage, EventRpcMessageEvent, FrpBridgeOptions, FrpProcessManagerOptions, FrpcPresetConfig, FrpsPresetConfig, MiddlewareContext, MiddlewareFn, MiddlewareOptions, NodeDeletePayload, NodeEvent, NodeInfo, NodeManagerOptions, NodeResponsePayload, NodeStorage, ParseOptions, PingMessage, PongMessage, PresetConfig, QueryHandler, QueryResult, ReconnectStrategy, RegisterMessage, RpcClientOptions, RpcCommandStatus, RpcMessage, RpcRequest, RpcResponse, RpcResponseStatus, RpcServerOptions, RuntimeAdapters, RuntimeCommand, RuntimeContext, RuntimeError, RuntimeErrorCode, RuntimeEvent, RuntimeLogger, RuntimeMode, RuntimeQuery, RuntimeState, RuntimeStatus, SnapshotStorage, StringifyOptions, TunnelAddPayload, TunnelDeletePayload, TunnelResponsePayload };
|
|
1746
|
+
declare function omitUndefined<T extends Record<string, unknown>>(obj: T): T;
|
|
1747
|
+
//#endregion
|
|
1748
|
+
export { ARCH_MAP, AllRpcMessage, Awaitable, BINARY_NAMES, BinaryNotFoundError, type ClientCollectorOptions, ClientNodeCollector, CommandHandler, CommandHandlerContext, CommandMetadata, CommandResult, CommandRpcMessage, CommandStatus, ConfigInvalidError, ConfigNotFoundError, ConfigSnapshot, DEFAULT_PRESET_CONFIG, DownloadFailedError, FrpBridgeErrorBase as Error, FrpBridgeErrorBase, EventRpcMessage, EventRpcMessageEvent, ExponentialBackoffStrategy, ExtractionFailedError, FileNodeStorage, FileSnapshotStorage, FixedIntervalStrategy, FrpBridge, type FrpBridgeOptions, FrpProcessManager, type FrpProcessManagerOptions, FrpRuntime, FrpcPresetConfig, FrpsPresetConfig, GITHUB_OWNER, GITHUB_REPO, GenericError, InfiniteReconnectStrategy, LinearBackoffStrategy, MiddlewareContext, MiddlewareFn, MiddlewareOptions, MiddlewarePipeline, ModeError, NodeDeletePayload, type NodeEvent, type NodeInfo, NodeManager, type NodeManagerOptions, NodeResponsePayload, type NodeStorage, NotFoundError, OS_MAP, ParseOptions, PingMessage, PlatformError, PongMessage, PresetConfig, ProcessAlreadyRunningError, type ProcessEvent, type ProcessEventType, ProcessNotRunningError, ProcessStartFailedError, QueryHandler, QueryResult, ReconnectStrategy, RegisterMessage, RpcClient, RpcClientOptions, RpcCommandStatus, RpcMessage, RpcMessageType, RpcRequest, RpcResponse, RpcResponseStatus, RpcServer, RpcServerOptions, RuntimeAdapters, RuntimeCommand, RuntimeContext, RuntimeError, RuntimeErrorCode, RuntimeEvent, RuntimeLogger, RuntimeMode, RuntimeQuery, RuntimeState, RuntimeStatus, SnapshotStorage, StringifyOptions, TunnelAddPayload, TunnelDeletePayload, TunnelResponsePayload, ValidationError, VersionFetchError, authMiddleware, commandExists, configToToml, downloadFile, ensureDir, errorHandlerMiddleware, executeCommand, findExistingVersion, getDownloadUrl, getLatestVersion, getPlatform, isCommandMessage, isEventMessage, isEventRpcMessage, isNodeDeletePayload, isPingMessage, isPongMessage, isRegisterMessage, isRpcRequest, isRpcResponse, isTunnelAddPayload, isTunnelDeletePayload, isValidToml, loggingMiddleware, mergeConfigs, omitUndefined, parse, safeParse, saveFrpConfigFile, stringify, timeoutMiddleware, typeUsesRemotePort, validatePresetConfig };
|