@zhin.js/client 1.0.17 → 1.0.18

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.
Files changed (76) hide show
  1. package/client/app.ts +228 -0
  2. package/client/index.ts +42 -14
  3. package/client/websocket/hooks.ts +218 -510
  4. package/client/websocket/index.ts +6 -43
  5. package/client/websocket/instance.ts +10 -32
  6. package/client/websocket/manager.ts +173 -390
  7. package/client/websocket/types.ts +58 -222
  8. package/dist/app.d.ts +95 -0
  9. package/dist/app.d.ts.map +1 -0
  10. package/dist/app.js +147 -0
  11. package/dist/app.js.map +1 -0
  12. package/dist/index.d.ts +7 -7
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +10 -14
  15. package/dist/index.js.map +1 -1
  16. package/dist/websocket/hooks.d.ts +35 -58
  17. package/dist/websocket/hooks.d.ts.map +1 -1
  18. package/dist/websocket/hooks.js +134 -410
  19. package/dist/websocket/hooks.js.map +1 -1
  20. package/dist/websocket/index.d.ts +5 -10
  21. package/dist/websocket/index.d.ts.map +1 -1
  22. package/dist/websocket/index.js +5 -25
  23. package/dist/websocket/index.js.map +1 -1
  24. package/dist/websocket/instance.d.ts +1 -14
  25. package/dist/websocket/instance.d.ts.map +1 -1
  26. package/dist/websocket/instance.js +2 -20
  27. package/dist/websocket/instance.js.map +1 -1
  28. package/dist/websocket/manager.d.ts +23 -93
  29. package/dist/websocket/manager.d.ts.map +1 -1
  30. package/dist/websocket/manager.js +87 -227
  31. package/dist/websocket/manager.js.map +1 -1
  32. package/dist/websocket/types.d.ts +35 -122
  33. package/dist/websocket/types.d.ts.map +1 -1
  34. package/dist/websocket/types.js +4 -13
  35. package/dist/websocket/types.js.map +1 -1
  36. package/package.json +12 -11
  37. package/client/router/index.tsx +0 -54
  38. package/client/store/index.ts +0 -132
  39. package/client/store/reducers/config.ts +0 -135
  40. package/client/store/reducers/index.ts +0 -19
  41. package/client/store/reducers/route.ts +0 -126
  42. package/client/store/reducers/script.ts +0 -109
  43. package/client/store/reducers/ui.ts +0 -31
  44. package/client/websocket/messageHandler.ts +0 -208
  45. package/dist/router/index.d.ts +0 -25
  46. package/dist/router/index.d.ts.map +0 -1
  47. package/dist/router/index.js +0 -48
  48. package/dist/router/index.js.map +0 -1
  49. package/dist/store/index.d.ts +0 -19
  50. package/dist/store/index.d.ts.map +0 -1
  51. package/dist/store/index.js +0 -67
  52. package/dist/store/index.js.map +0 -1
  53. package/dist/store/reducers/config.d.ts +0 -54
  54. package/dist/store/reducers/config.d.ts.map +0 -1
  55. package/dist/store/reducers/config.js +0 -78
  56. package/dist/store/reducers/config.js.map +0 -1
  57. package/dist/store/reducers/index.d.ts +0 -13
  58. package/dist/store/reducers/index.d.ts.map +0 -1
  59. package/dist/store/reducers/index.js +0 -11
  60. package/dist/store/reducers/index.js.map +0 -1
  61. package/dist/store/reducers/route.d.ts +0 -30
  62. package/dist/store/reducers/route.d.ts.map +0 -1
  63. package/dist/store/reducers/route.js +0 -85
  64. package/dist/store/reducers/route.js.map +0 -1
  65. package/dist/store/reducers/script.d.ts +0 -13
  66. package/dist/store/reducers/script.d.ts.map +0 -1
  67. package/dist/store/reducers/script.js +0 -78
  68. package/dist/store/reducers/script.js.map +0 -1
  69. package/dist/store/reducers/ui.d.ts +0 -8
  70. package/dist/store/reducers/ui.d.ts.map +0 -1
  71. package/dist/store/reducers/ui.js +0 -23
  72. package/dist/store/reducers/ui.js.map +0 -1
  73. package/dist/websocket/messageHandler.d.ts +0 -58
  74. package/dist/websocket/messageHandler.d.ts.map +0 -1
  75. package/dist/websocket/messageHandler.js +0 -174
  76. package/dist/websocket/messageHandler.js.map +0 -1
@@ -1,581 +1,289 @@
1
- /**
2
- * WebSocket React Hooks
3
- * 提供在 React 组件中使用 WebSocket 功能的便捷接口
4
- */
5
-
6
- import { useCallback, useEffect, useMemo, useState } from 'react'
7
- import {
8
- useSelector,
9
- useDispatch,
10
- selectConfig,
11
- selectSchema,
12
- selectConfigLoading,
13
- selectConfigError,
14
- selectConfigConnected,
15
- selectAllConfigs,
16
- selectAllSchemas,
17
- setLoading,
18
- setError,
19
- updateConfig,
20
- updateSchema
21
- } from '../store'
22
- import { getWebSocketManager } from './instance'
23
- import type { UseConfigOptions, UseWebSocketOptions, FileTreeNode, DatabaseInfo, TableInfo, SelectResult, KvEntry, DatabaseType } from './types'
24
-
25
- // ============================================================================
26
- // WebSocket 连接 Hook
27
- // ============================================================================
28
-
29
- /**
30
- * WebSocket 连接状态和基础功能 Hook
31
- */
1
+ import { useCallback, useEffect, useMemo, useState } from "react";
2
+ import { getWebSocketManager } from "./instance";
3
+ import type { UseWebSocketOptions } from "./types";
4
+
32
5
  export function useWebSocket(options: UseWebSocketOptions = {}) {
33
- const { autoConnect = true } = options
34
-
35
- const wsManager = getWebSocketManager()
36
-
37
- // 从 Redux 获取状态
38
- const connected = useSelector(selectConfigConnected)
39
- const entries = useSelector((state: any) => state.script?.entries || [])
40
- const loadedScripts = useSelector((state: any) => state.script?.loadedScripts || [])
41
-
42
- // 连接控制
43
- const connect = useCallback(() => {
44
- wsManager.connect()
45
- }, [wsManager])
46
-
47
- const disconnect = useCallback(() => {
48
- wsManager.disconnect()
49
- }, [wsManager])
50
-
51
- // 消息发送
52
- const send = useCallback((message: any) => {
53
- wsManager.send(message)
54
- }, [wsManager])
55
-
56
- const sendRequest = useCallback(async <T = any>(message: any): Promise<T> => {
57
- // 临时使用旧方法,后续完善
58
- return (wsManager as any).sendRequest(message)
59
- }, [wsManager])
60
-
61
- // 状态查询
62
- const isConnected = useCallback(() => {
63
- return wsManager.isConnected()
64
- }, [wsManager])
65
-
66
- const getState = useCallback(() => {
67
- // 临时返回连接状态,后续完善
68
- return wsManager.isConnected() ? 'connected' : 'disconnected'
69
- }, [wsManager])
70
-
71
- // 自动连接
6
+ const { autoConnect = true } = options;
7
+ const wsManager = getWebSocketManager();
8
+ const [connected, setConnected] = useState(wsManager.isConnected());
9
+
72
10
  useEffect(() => {
73
- if (autoConnect && !connected) {
74
- connect()
75
- }
76
- }, [autoConnect, connected, connect])
77
-
78
- return {
79
- // 状态
80
- connected,
81
- entries,
82
- loadedScripts,
83
-
84
- // 方法
85
- connect,
86
- disconnect,
87
- send,
88
- sendRequest,
89
- isConnected,
90
- getState,
91
-
92
- // WebSocket 实例(高级用法)
93
- manager: wsManager
94
- }
95
- }
11
+ return wsManager.onConnectionChange(setConnected);
12
+ }, [wsManager]);
96
13
 
97
- // ============================================================================
98
- // 配置管理 Hook
99
- // ============================================================================
100
-
101
- /**
102
- * 插件配置管理 Hook
103
- */
104
- export function useConfig(pluginName: string, options: UseConfigOptions = {}) {
105
- const { autoLoad = true, autoLoadSchema = true } = options
106
-
107
- const dispatch = useDispatch()
108
- const wsManager = getWebSocketManager()
109
-
110
- // 状态选择器
111
- const config = useSelector((state: any) => selectConfig(state, pluginName))
112
- const schema = useSelector((state: any) => selectSchema(state, pluginName))
113
- const loading = useSelector((state: any) => selectConfigLoading(state, pluginName))
114
- const error = useSelector((state: any) => selectConfigError(state, pluginName))
115
- const connected = useSelector(selectConfigConnected)
116
-
117
- // 配置操作
118
- const getConfig = useCallback(async () => {
119
- dispatch(setLoading({ pluginName, loading: true }))
120
- dispatch(setError({ pluginName, error: null }))
14
+ const connect = useCallback(() => wsManager.connect(), [wsManager]);
15
+ const disconnect = useCallback(() => wsManager.disconnect(), [wsManager]);
16
+ const send = useCallback((message: unknown) => wsManager.send(message), [wsManager]);
17
+ const sendRequest = useCallback(
18
+ <T = unknown>(message: unknown) => wsManager.sendRequest<T>(message),
19
+ [wsManager],
20
+ );
121
21
 
122
- try {
123
- const result = await wsManager.getConfig(pluginName)
124
- dispatch(updateConfig({ pluginName, config: result }))
125
- return result
126
- } catch (error) {
127
- console.error('[useConfig] getConfig failed:', error)
128
- const errorMessage = error instanceof Error ? error.message : 'Unknown error'
129
- dispatch(setError({ pluginName, error: errorMessage }))
130
- throw error
131
- } finally {
132
- dispatch(setLoading({ pluginName, loading: false }))
133
- }
134
- }, [pluginName, wsManager, dispatch])
22
+ useEffect(() => {
23
+ if (autoConnect && !connected) connect();
24
+ }, [autoConnect, connected, connect]);
25
+
26
+ return { connected, connect, disconnect, send, sendRequest, manager: wsManager };
27
+ }
135
28
 
136
- const setConfig = useCallback(async (newConfig: any): Promise<{ reloaded?: boolean; message?: string }> => {
137
- dispatch(setLoading({ pluginName, loading: true }))
138
- dispatch(setError({ pluginName, error: null }))
29
+ export function useConfig(pluginName: string, options?: { autoLoad?: boolean; autoLoadSchema?: boolean }) {
30
+ const { autoLoad = true, autoLoadSchema = true } = options ?? {};
31
+ const wsManager = getWebSocketManager();
32
+ const [connected, setConnected] = useState(wsManager.isConnected());
33
+ const [config, setConfigState] = useState<unknown>(null);
34
+ const [schema, setSchemaState] = useState<unknown>(null);
35
+ const [loading, setLoading] = useState(false);
36
+ const [error, setError] = useState<string | null>(null);
139
37
 
38
+ useEffect(() => wsManager.onConnectionChange(setConnected), [wsManager]);
39
+
40
+ const getConfig = useCallback(async () => {
41
+ setLoading(true);
42
+ setError(null);
140
43
  try {
141
- const result = await wsManager.setConfig(pluginName, newConfig)
142
- return { reloaded: result?.reloaded, message: result?.message }
143
- } catch (error) {
144
- console.error('[useConfig] setConfig failed:', error)
145
- const errorMessage = error instanceof Error ? error.message : 'Unknown error'
146
- dispatch(setError({ pluginName, error: errorMessage }))
147
- throw error
44
+ const result = await wsManager.getConfig(pluginName);
45
+ setConfigState(result);
46
+ return result;
47
+ } catch (e) {
48
+ setError(e instanceof Error ? e.message : "Unknown error");
49
+ throw e;
148
50
  } finally {
149
- dispatch(setLoading({ pluginName, loading: false }))
150
- }
151
- }, [pluginName, wsManager, dispatch])
51
+ setLoading(false);
52
+ }
53
+ }, [pluginName, wsManager]);
54
+
55
+ const setConfig = useCallback(
56
+ async (newConfig: unknown) => {
57
+ setLoading(true);
58
+ setError(null);
59
+ try {
60
+ return await wsManager.setConfig(pluginName, newConfig);
61
+ } catch (e) {
62
+ setError(e instanceof Error ? e.message : "Unknown error");
63
+ throw e;
64
+ } finally {
65
+ setLoading(false);
66
+ }
67
+ },
68
+ [pluginName, wsManager],
69
+ );
152
70
 
153
71
  const getSchema = useCallback(async () => {
154
72
  try {
155
- const result = await wsManager.getSchema(pluginName)
156
- if (result) {
157
- dispatch(updateSchema({ pluginName, schema: result }))
158
- }
159
- return result
160
- } catch (error) {
161
- console.error(`Failed to get schema for plugin ${pluginName}:`, error)
162
- throw error
73
+ const result = await wsManager.getSchema(pluginName);
74
+ if (result) setSchemaState(result);
75
+ return result;
76
+ } catch (e) {
77
+ throw e;
163
78
  }
164
- }, [pluginName, wsManager, dispatch])
165
-
166
- // 重新加载配置和 Schema
167
- const reload = useCallback(async () => {
168
- const promises = []
169
-
170
- if (autoLoad) {
171
- promises.push(getConfig())
172
- }
173
-
174
- if (autoLoadSchema) {
175
- promises.push(getSchema())
176
- }
177
-
178
- await Promise.all(promises)
179
- }, [autoLoad, autoLoadSchema, getConfig, getSchema])
79
+ }, [pluginName, wsManager]);
180
80
 
181
- // 自动加载
182
81
  useEffect(() => {
183
- if (connected && autoLoad && !config && !loading) {
184
- getConfig().catch(console.error)
185
- }
186
- }, [connected, autoLoad, config, loading, getConfig])
82
+ if (connected && autoLoad && !config && !loading) getConfig().catch(() => {});
83
+ }, [connected, autoLoad, config, loading, getConfig]);
187
84
 
188
85
  useEffect(() => {
189
- if (connected && autoLoadSchema && !schema) {
190
- getSchema().catch(console.error)
191
- }
192
- }, [connected, autoLoadSchema, schema, getSchema])
193
-
194
- return useMemo(() => ({
195
- // 状态
196
- config,
197
- schema,
198
- loading,
199
- error,
200
- connected,
201
-
202
- // 方法
203
- getConfig,
204
- setConfig,
205
- getSchema,
206
- reload
207
- }), [config, schema, loading, error, connected, getConfig, setConfig, getSchema, reload])
208
- }
86
+ if (connected && autoLoadSchema && !schema) getSchema().catch(() => {});
87
+ }, [connected, autoLoadSchema, schema, getSchema]);
209
88
 
210
- // ============================================================================
211
- // 批量配置管理 Hook
212
- // ============================================================================
213
-
214
- /**
215
- * 所有配置管理 Hook
216
- */
217
- export function useAllConfigs() {
218
- const wsManager = getWebSocketManager()
219
-
220
- const allConfigs = useSelector(selectAllConfigs)
221
- const allSchemas = useSelector(selectAllSchemas)
222
- const connected = useSelector(selectConfigConnected)
223
-
224
- const refreshAll = useCallback(async () => {
225
- try {
226
- const [configs, schemas] = await Promise.all([
227
- (wsManager as any).getAllConfigs(),
228
- (wsManager as any).getAllSchemas()
229
- ])
230
-
231
- return { configs, schemas }
232
- } catch (error) {
233
- console.error('Failed to refresh all configs:', error)
234
- throw error
235
- }
236
- }, [wsManager])
237
-
238
- return useMemo(() => ({
239
- configs: allConfigs,
240
- schemas: allSchemas,
241
- connected,
242
- refreshAll
243
- }), [allConfigs, allSchemas, connected, refreshAll])
89
+ return useMemo(
90
+ () => ({ config, schema, loading, error, connected, getConfig, setConfig, getSchema }),
91
+ [config, schema, loading, error, connected, getConfig, setConfig, getSchema],
92
+ );
244
93
  }
245
94
 
246
- // ============================================================================
247
- // 配置文件 YAML 读写 Hook
248
- // ============================================================================
249
-
250
95
  export function useConfigYaml() {
251
- const wsManager = getWebSocketManager()
252
- const connected = useSelector(selectConfigConnected)
96
+ const wsManager = getWebSocketManager();
97
+ const [connected, setConnected] = useState(wsManager.isConnected());
98
+ const [yaml, setYaml] = useState("");
99
+ const [pluginKeys, setPluginKeys] = useState<string[]>([]);
100
+ const [loading, setLoading] = useState(false);
101
+ const [error, setError] = useState<string | null>(null);
253
102
 
254
- const [yaml, setYaml] = useState('')
255
- const [pluginKeys, setPluginKeys] = useState<string[]>([])
256
- const [loading, setLoadingState] = useState(false)
257
- const [error, setErrorState] = useState<string | null>(null)
103
+ useEffect(() => wsManager.onConnectionChange(setConnected), [wsManager]);
258
104
 
259
105
  const load = useCallback(async () => {
260
- setLoadingState(true)
261
- setErrorState(null)
262
- try {
263
- const result = await wsManager.getConfigYaml()
264
- setYaml(result.yaml)
265
- setPluginKeys(result.pluginKeys)
266
- return result
267
- } catch (err) {
268
- const msg = err instanceof Error ? err.message : 'Unknown error'
269
- setErrorState(msg)
270
- throw err
271
- } finally {
272
- setLoadingState(false)
273
- }
274
- }, [wsManager])
275
-
276
- const save = useCallback(async (content: string) => {
277
- setLoadingState(true)
278
- setErrorState(null)
106
+ setLoading(true);
107
+ setError(null);
279
108
  try {
280
- const result = await wsManager.saveConfigYaml(content)
281
- setYaml(content)
282
- return result
283
- } catch (err) {
284
- const msg = err instanceof Error ? err.message : 'Unknown error'
285
- setErrorState(msg)
286
- throw err
109
+ const result = await wsManager.getConfigYaml();
110
+ setYaml(result.yaml);
111
+ setPluginKeys(result.pluginKeys);
112
+ return result;
113
+ } catch (e) {
114
+ setError(e instanceof Error ? e.message : "Unknown error");
115
+ throw e;
287
116
  } finally {
288
- setLoadingState(false)
289
- }
290
- }, [wsManager])
117
+ setLoading(false);
118
+ }
119
+ }, [wsManager]);
120
+
121
+ const save = useCallback(
122
+ async (content: string) => {
123
+ setLoading(true);
124
+ setError(null);
125
+ try {
126
+ const result = await wsManager.saveConfigYaml(content);
127
+ setYaml(content);
128
+ return result;
129
+ } catch (e) {
130
+ setError(e instanceof Error ? e.message : "Unknown error");
131
+ throw e;
132
+ } finally {
133
+ setLoading(false);
134
+ }
135
+ },
136
+ [wsManager],
137
+ );
291
138
 
292
139
  useEffect(() => {
293
- if (connected && !yaml && !loading) {
294
- load().catch(() => {})
295
- }
296
- }, [connected, yaml, loading, load])
140
+ if (connected && !yaml && !loading) load().catch(() => {});
141
+ }, [connected, yaml, loading, load]);
297
142
 
298
- return useMemo(() => ({
299
- yaml, pluginKeys, loading, error, load, save
300
- }), [yaml, pluginKeys, loading, error, load, save])
143
+ return useMemo(() => ({ yaml, pluginKeys, loading, error, load, save }), [yaml, pluginKeys, loading, error, load, save]);
301
144
  }
302
145
 
303
- // ============================================================================
304
- // 环境变量文件管理 Hook
305
- // ============================================================================
306
-
307
- export function useEnvFiles() {
308
- const wsManager = getWebSocketManager()
309
- const connected = useSelector(selectConfigConnected)
146
+ export function useFiles() {
147
+ const wsManager = getWebSocketManager();
148
+ const [connected, setConnected] = useState(wsManager.isConnected());
149
+ const [tree, setTree] = useState<import("./types").FileTreeNode[]>([]);
150
+ const [loading, setLoading] = useState(false);
151
+ const [error, setError] = useState<string | null>(null);
310
152
 
311
- const [files, setFiles] = useState<Array<{ name: string; exists: boolean }>>([])
312
- const [loading, setLoadingState] = useState(false)
313
- const [error, setErrorState] = useState<string | null>(null)
153
+ useEffect(() => wsManager.onConnectionChange(setConnected), [wsManager]);
314
154
 
315
- const listFiles = useCallback(async () => {
316
- setLoadingState(true)
317
- setErrorState(null)
155
+ const loadTree = useCallback(async () => {
156
+ setLoading(true);
157
+ setError(null);
318
158
  try {
319
- const result = await wsManager.getEnvList()
320
- setFiles(result.files)
321
- return result.files
322
- } catch (err) {
323
- const msg = err instanceof Error ? err.message : 'Unknown error'
324
- setErrorState(msg)
325
- throw err
159
+ const result = await wsManager.getFileTree();
160
+ setTree(result.tree);
161
+ return result.tree;
162
+ } catch (e) {
163
+ setError(e instanceof Error ? e.message : "Unknown error");
164
+ throw e;
326
165
  } finally {
327
- setLoadingState(false)
166
+ setLoading(false);
328
167
  }
329
- }, [wsManager])
168
+ }, [wsManager]);
330
169
 
331
- const getFile = useCallback(async (filename: string) => {
332
- try {
333
- const result = await wsManager.getEnvFile(filename)
334
- return result.content
335
- } catch (err) {
336
- const msg = err instanceof Error ? err.message : 'Unknown error'
337
- setErrorState(msg)
338
- throw err
339
- }
340
- }, [wsManager])
341
-
342
- const saveFile = useCallback(async (filename: string, content: string) => {
343
- setLoadingState(true)
344
- setErrorState(null)
345
- try {
346
- return await wsManager.saveEnvFile(filename, content)
347
- } catch (err) {
348
- const msg = err instanceof Error ? err.message : 'Unknown error'
349
- setErrorState(msg)
350
- throw err
351
- } finally {
352
- setLoadingState(false)
353
- }
354
- }, [wsManager])
170
+ const readFile = useCallback(async (filePath: string) => (await wsManager.readFile(filePath)).content, [wsManager]);
171
+ const saveFile = useCallback(
172
+ async (filePath: string, content: string) => wsManager.saveFile(filePath, content),
173
+ [wsManager],
174
+ );
355
175
 
356
176
  useEffect(() => {
357
- if (connected && files.length === 0 && !loading) {
358
- listFiles().catch(() => {})
359
- }
360
- }, [connected, files.length, loading, listFiles])
177
+ if (connected && tree.length === 0 && !loading) loadTree().catch(() => {});
178
+ }, [connected, tree.length, loading, loadTree]);
361
179
 
362
- return useMemo(() => ({
363
- files, loading, error, listFiles, getFile, saveFile
364
- }), [files, loading, error, listFiles, getFile, saveFile])
180
+ return useMemo(() => ({ tree, loading, error, loadTree, readFile, saveFile }), [tree, loading, error, loadTree, readFile, saveFile]);
365
181
  }
366
182
 
367
- // ============================================================================
368
- // 文件管理 Hook
369
- // ============================================================================
370
-
371
- export function useFiles() {
372
- const wsManager = getWebSocketManager()
373
- const connected = useSelector(selectConfigConnected)
183
+ export function useEnvFiles() {
184
+ const wsManager = getWebSocketManager();
185
+ const [connected, setConnected] = useState(wsManager.isConnected());
186
+ const [files, setFiles] = useState<Array<{ name: string; exists: boolean }>>([]);
187
+ const [loading, setLoading] = useState(false);
188
+ const [error, setError] = useState<string | null>(null);
374
189
 
375
- const [tree, setTree] = useState<FileTreeNode[]>([])
376
- const [loading, setLoadingState] = useState(false)
377
- const [error, setErrorState] = useState<string | null>(null)
190
+ useEffect(() => wsManager.onConnectionChange(setConnected), [wsManager]);
378
191
 
379
- const loadTree = useCallback(async () => {
380
- setLoadingState(true)
381
- setErrorState(null)
192
+ const listFiles = useCallback(async () => {
193
+ setLoading(true);
194
+ setError(null);
382
195
  try {
383
- const result = await wsManager.getFileTree()
384
- setTree(result.tree)
385
- return result.tree
386
- } catch (err) {
387
- const msg = err instanceof Error ? err.message : 'Unknown error'
388
- setErrorState(msg)
389
- throw err
196
+ const result = await wsManager.getEnvList();
197
+ setFiles(result.files);
198
+ return result.files;
199
+ } catch (e) {
200
+ setError(e instanceof Error ? e.message : "Unknown error");
201
+ throw e;
390
202
  } finally {
391
- setLoadingState(false)
203
+ setLoading(false);
392
204
  }
393
- }, [wsManager])
205
+ }, [wsManager]);
394
206
 
395
- const readFile = useCallback(async (filePath: string) => {
396
- try {
397
- const result = await wsManager.readFile(filePath)
398
- return result.content
399
- } catch (err) {
400
- const msg = err instanceof Error ? err.message : 'Unknown error'
401
- setErrorState(msg)
402
- throw err
403
- }
404
- }, [wsManager])
207
+ const getFile = useCallback(
208
+ async (filename: string) => {
209
+ const result = await wsManager.getEnvFile(filename);
210
+ return result.content;
211
+ },
212
+ [wsManager],
213
+ );
405
214
 
406
- const saveFile = useCallback(async (filePath: string, content: string) => {
407
- setLoadingState(true)
408
- setErrorState(null)
409
- try {
410
- return await wsManager.saveFile(filePath, content)
411
- } catch (err) {
412
- const msg = err instanceof Error ? err.message : 'Unknown error'
413
- setErrorState(msg)
414
- throw err
415
- } finally {
416
- setLoadingState(false)
417
- }
418
- }, [wsManager])
215
+ const saveFile = useCallback(
216
+ async (filename: string, content: string) => wsManager.saveEnvFile(filename, content),
217
+ [wsManager],
218
+ );
419
219
 
420
220
  useEffect(() => {
421
- if (connected && tree.length === 0 && !loading) {
422
- loadTree().catch(() => {})
423
- }
424
- }, [connected, tree.length, loading, loadTree])
221
+ if (connected && files.length === 0 && !loading) listFiles().catch(() => {});
222
+ }, [connected, files.length, loading, listFiles]);
425
223
 
426
- return useMemo(() => ({
427
- tree, loading, error, loadTree, readFile, saveFile
428
- }), [tree, loading, error, loadTree, readFile, saveFile])
224
+ return useMemo(
225
+ () => ({ files, loading, error, listFiles, getFile, saveFile }),
226
+ [files, loading, error, listFiles, getFile, saveFile],
227
+ );
429
228
  }
430
229
 
431
- // ============================================================================
432
- // 数据库管理 Hook
433
- // ============================================================================
434
-
435
230
  export function useDatabase() {
436
- const wsManager = getWebSocketManager()
437
- const connected = useSelector(selectConfigConnected)
231
+ const wsManager = getWebSocketManager();
232
+ const [connected, setConnected] = useState(wsManager.isConnected());
233
+ const [info, setInfo] = useState<import("./types").DatabaseInfo | null>(null);
234
+ const [tables, setTables] = useState<import("./types").TableInfo[]>([]);
235
+ const [loading, setLoading] = useState(false);
236
+ const [error, setError] = useState<string | null>(null);
438
237
 
439
- const [info, setInfo] = useState<DatabaseInfo | null>(null)
440
- const [tables, setTables] = useState<TableInfo[]>([])
441
- const [loading, setLoadingState] = useState(false)
442
- const [error, setErrorState] = useState<string | null>(null)
238
+ useEffect(() => wsManager.onConnectionChange(setConnected), [wsManager]);
443
239
 
444
240
  const loadInfo = useCallback(async () => {
445
- setLoadingState(true)
446
- setErrorState(null)
241
+ setLoading(true);
447
242
  try {
448
- const result = await wsManager.getDbInfo()
449
- setInfo(result)
450
- return result
451
- } catch (err) {
452
- const msg = err instanceof Error ? err.message : 'Unknown error'
453
- setErrorState(msg)
454
- throw err
243
+ const result = await wsManager.getDbInfo();
244
+ setInfo(result);
245
+ return result;
246
+ } catch (e) {
247
+ setError(e instanceof Error ? e.message : "Unknown error");
248
+ throw e;
455
249
  } finally {
456
- setLoadingState(false)
250
+ setLoading(false);
457
251
  }
458
- }, [wsManager])
252
+ }, [wsManager]);
459
253
 
460
254
  const loadTables = useCallback(async () => {
461
- setLoadingState(true)
462
- setErrorState(null)
255
+ setLoading(true);
463
256
  try {
464
- const result = await wsManager.getDbTables()
465
- setTables(result.tables)
466
- return result.tables
467
- } catch (err) {
468
- const msg = err instanceof Error ? err.message : 'Unknown error'
469
- setErrorState(msg)
470
- throw err
257
+ const result = await wsManager.getDbTables();
258
+ setTables(result.tables);
259
+ return result.tables;
260
+ } catch (e) {
261
+ setError(e instanceof Error ? e.message : "Unknown error");
262
+ throw e;
471
263
  } finally {
472
- setLoadingState(false)
473
- }
474
- }, [wsManager])
475
-
476
- const select = useCallback(async (table: string, page?: number, pageSize?: number, where?: any) => {
477
- try {
478
- return await wsManager.dbSelect(table, page, pageSize, where)
479
- } catch (err) {
480
- const msg = err instanceof Error ? err.message : 'Unknown error'
481
- setErrorState(msg)
482
- throw err
264
+ setLoading(false);
483
265
  }
484
- }, [wsManager])
266
+ }, [wsManager]);
485
267
 
486
- const insert = useCallback(async (table: string, row: any) => {
487
- try {
488
- return await wsManager.dbInsert(table, row)
489
- } catch (err) {
490
- const msg = err instanceof Error ? err.message : 'Unknown error'
491
- setErrorState(msg)
492
- throw err
493
- }
494
- }, [wsManager])
495
-
496
- const update = useCallback(async (table: string, row: any, where: any) => {
497
- try {
498
- return await wsManager.dbUpdate(table, row, where)
499
- } catch (err) {
500
- const msg = err instanceof Error ? err.message : 'Unknown error'
501
- setErrorState(msg)
502
- throw err
503
- }
504
- }, [wsManager])
505
-
506
- const remove = useCallback(async (table: string, where: any) => {
507
- try {
508
- return await wsManager.dbDelete(table, where)
509
- } catch (err) {
510
- const msg = err instanceof Error ? err.message : 'Unknown error'
511
- setErrorState(msg)
512
- throw err
513
- }
514
- }, [wsManager])
515
-
516
- const dropTable = useCallback(async (table: string) => {
517
- try {
518
- const result = await wsManager.dbDropTable(table)
519
- await loadTables()
520
- return result
521
- } catch (err) {
522
- const msg = err instanceof Error ? err.message : 'Unknown error'
523
- setErrorState(msg)
524
- throw err
525
- }
526
- }, [wsManager, loadTables])
527
-
528
- const kvGet = useCallback(async (table: string, key: string) => {
529
- try {
530
- return await wsManager.kvGet(table, key)
531
- } catch (err) {
532
- const msg = err instanceof Error ? err.message : 'Unknown error'
533
- setErrorState(msg)
534
- throw err
535
- }
536
- }, [wsManager])
537
-
538
- const kvSet = useCallback(async (table: string, key: string, value: any, ttl?: number) => {
539
- try {
540
- return await wsManager.kvSet(table, key, value, ttl)
541
- } catch (err) {
542
- const msg = err instanceof Error ? err.message : 'Unknown error'
543
- setErrorState(msg)
544
- throw err
545
- }
546
- }, [wsManager])
547
-
548
- const kvDelete = useCallback(async (table: string, key: string) => {
549
- try {
550
- return await wsManager.kvDelete(table, key)
551
- } catch (err) {
552
- const msg = err instanceof Error ? err.message : 'Unknown error'
553
- setErrorState(msg)
554
- throw err
555
- }
556
- }, [wsManager])
557
-
558
- const kvEntries = useCallback(async (table: string) => {
559
- try {
560
- return await wsManager.kvGetEntries(table)
561
- } catch (err) {
562
- const msg = err instanceof Error ? err.message : 'Unknown error'
563
- setErrorState(msg)
564
- throw err
565
- }
566
- }, [wsManager])
268
+ const select = useCallback(async (table: string, page?: number, pageSize?: number, where?: unknown) => wsManager.dbSelect(table, page, pageSize, where), [wsManager]);
269
+ const insert = useCallback(async (table: string, row: unknown) => wsManager.dbInsert(table, row), [wsManager]);
270
+ const update = useCallback(async (table: string, row: unknown, where: unknown) => wsManager.dbUpdate(table, row, where), [wsManager]);
271
+ const remove = useCallback(async (table: string, where: unknown) => wsManager.dbDelete(table, where), [wsManager]);
272
+ const dropTable = useCallback(async (table: string) => { const r = await wsManager.dbDropTable(table); await loadTables(); return r; }, [wsManager, loadTables]);
273
+ const kvGet = useCallback(async (table: string, key: string) => wsManager.kvGet(table, key), [wsManager]);
274
+ const kvSet = useCallback(async (table: string, key: string, value: unknown, ttl?: number) => wsManager.kvSet(table, key, value, ttl), [wsManager]);
275
+ const kvDelete = useCallback(async (table: string, key: string) => wsManager.kvDelete(table, key), [wsManager]);
276
+ const kvEntries = useCallback(async (table: string) => wsManager.kvGetEntries(table), [wsManager]);
567
277
 
568
278
  useEffect(() => {
569
279
  if (connected && !info && !loading) {
570
- loadInfo().catch(() => {})
571
- loadTables().catch(() => {})
280
+ loadInfo().catch(() => {});
281
+ loadTables().catch(() => {});
572
282
  }
573
- }, [connected, info, loading, loadInfo, loadTables])
574
-
575
- return useMemo(() => ({
576
- info, tables, loading, error,
577
- loadInfo, loadTables, dropTable,
578
- select, insert, update, remove,
579
- kvGet, kvSet, kvDelete, kvEntries,
580
- }), [info, tables, loading, error, loadInfo, loadTables, dropTable, select, insert, update, remove, kvGet, kvSet, kvDelete, kvEntries])
283
+ }, [connected, info, loading, loadInfo, loadTables]);
284
+
285
+ return useMemo(
286
+ () => ({ info, tables, loading, error, loadInfo, loadTables, dropTable, select, insert, update, remove, kvGet, kvSet, kvDelete, kvEntries }),
287
+ [info, tables, loading, error, loadInfo, loadTables, dropTable, select, insert, update, remove, kvGet, kvSet, kvDelete, kvEntries],
288
+ );
581
289
  }