@lcap/wave-sandbox-sdk 0.0.4 → 0.0.6
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/client.js +15 -5
- package/dist/modules/agent.d.ts +6 -8
- package/dist/modules/agent.js +5 -3
- package/dist/modules/file-system.d.ts +2 -1
- package/dist/modules/file-system.js +8 -6
- package/dist/modules/project.d.ts +2 -1
- package/dist/modules/project.js +5 -3
- package/dist/types/index.d.ts +5 -0
- package/dist/utils/fetch-auth.d.ts +4 -0
- package/dist/utils/fetch-auth.js +11 -0
- package/package.json +12 -11
- package/src/client.ts +15 -5
- package/src/modules/agent.ts +10 -11
- package/src/modules/file-system.ts +8 -6
- package/src/modules/project.ts +5 -3
- package/src/types/index.ts +5 -0
- package/src/utils/fetch-auth.ts +11 -0
package/dist/client.js
CHANGED
|
@@ -13,14 +13,14 @@ export class WaveSandboxClient {
|
|
|
13
13
|
return this.fileSystem;
|
|
14
14
|
}
|
|
15
15
|
constructor(options) {
|
|
16
|
-
const { url, projectId, options: socketOptions } = options;
|
|
16
|
+
const { url, projectId, authToken, options: socketOptions } = options;
|
|
17
17
|
const uri = new URL(url);
|
|
18
18
|
let pathname = uri.pathname;
|
|
19
19
|
if (pathname.endsWith('/')) {
|
|
20
20
|
pathname = pathname.slice(0, pathname.length - 1);
|
|
21
21
|
}
|
|
22
22
|
pathname = pathname + '/socket.io/';
|
|
23
|
-
// 构建 Socket.IO
|
|
23
|
+
// 构建 Socket.IO 连接选项(Authorization 供服务端 auth 中间件校验)
|
|
24
24
|
const connectOptions = {
|
|
25
25
|
autoConnect: socketOptions?.autoConnect ?? true,
|
|
26
26
|
reconnection: socketOptions?.reconnection ?? true,
|
|
@@ -28,15 +28,25 @@ export class WaveSandboxClient {
|
|
|
28
28
|
reconnectionAttempts: socketOptions?.reconnectionAttempts ?? 5,
|
|
29
29
|
query: projectId ? { projectId } : undefined,
|
|
30
30
|
path: pathname,
|
|
31
|
+
...(authToken
|
|
32
|
+
? {
|
|
33
|
+
extraHeaders: { Authorization: authToken },
|
|
34
|
+
transportOptions: {
|
|
35
|
+
polling: {
|
|
36
|
+
extraHeaders: { Authorization: authToken },
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
}
|
|
40
|
+
: {}),
|
|
31
41
|
};
|
|
32
42
|
// 创建 Socket.IO 连接
|
|
33
43
|
this.socket = io(uri.host, connectOptions);
|
|
34
44
|
// 初始化各个模块
|
|
35
45
|
this.exec = new ExecModule(this.socket);
|
|
36
|
-
this.fileSystem = new FileSystemModule(this.socket, url, projectId);
|
|
46
|
+
this.fileSystem = new FileSystemModule(this.socket, url, projectId, authToken);
|
|
37
47
|
this.port = new PortModule(this.socket);
|
|
38
|
-
this.project = new ProjectModule(this.socket, url, projectId);
|
|
39
|
-
this.agent = new AgentModule(this.socket, url, projectId);
|
|
48
|
+
this.project = new ProjectModule(this.socket, url, projectId, authToken);
|
|
49
|
+
this.agent = new AgentModule(this.socket, url, projectId, authToken);
|
|
40
50
|
}
|
|
41
51
|
/**
|
|
42
52
|
* 连接到服务器
|
package/dist/modules/agent.d.ts
CHANGED
|
@@ -253,13 +253,6 @@ export interface AskUserQuestion {
|
|
|
253
253
|
options: AskUserQuestionOption[];
|
|
254
254
|
multiSelect?: boolean;
|
|
255
255
|
}
|
|
256
|
-
/**
|
|
257
|
-
* 询问用户问题事件数据
|
|
258
|
-
*/
|
|
259
|
-
export interface AskUserQuestionEvent {
|
|
260
|
-
questionId: string;
|
|
261
|
-
questions: AskUserQuestion[];
|
|
262
|
-
}
|
|
263
256
|
/**
|
|
264
257
|
* Ask 信息状态
|
|
265
258
|
*/
|
|
@@ -271,6 +264,10 @@ export interface AskInfo {
|
|
|
271
264
|
answered: boolean;
|
|
272
265
|
answer?: string;
|
|
273
266
|
}
|
|
267
|
+
/**
|
|
268
|
+
* 询问用户问题事件数据(与 AskInfo 相同)
|
|
269
|
+
*/
|
|
270
|
+
export type AskUserQuestionEvent = AskInfo;
|
|
274
271
|
/**
|
|
275
272
|
* 客户端回调选项
|
|
276
273
|
*/
|
|
@@ -317,7 +314,8 @@ export declare class AgentModule {
|
|
|
317
314
|
private socket;
|
|
318
315
|
private baseUrl;
|
|
319
316
|
private projectId?;
|
|
320
|
-
|
|
317
|
+
private authToken?;
|
|
318
|
+
constructor(socket: Socket, baseUrl: string, projectId?: string | undefined, authToken?: string | undefined);
|
|
321
319
|
/**
|
|
322
320
|
* 获取查询参数
|
|
323
321
|
*/
|
package/dist/modules/agent.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { createSocketHandler, onSocketEvent } from '../utils/socket.js';
|
|
2
|
+
import { fetchWithAuth } from '../utils/fetch-auth.js';
|
|
2
3
|
/**
|
|
3
4
|
* Agent 模块
|
|
4
5
|
*/
|
|
5
6
|
export class AgentModule {
|
|
6
|
-
constructor(socket, baseUrl, projectId) {
|
|
7
|
+
constructor(socket, baseUrl, projectId, authToken) {
|
|
7
8
|
this.socket = socket;
|
|
8
9
|
this.baseUrl = baseUrl;
|
|
9
10
|
this.projectId = projectId;
|
|
11
|
+
this.authToken = authToken;
|
|
10
12
|
}
|
|
11
13
|
/**
|
|
12
14
|
* 获取查询参数
|
|
@@ -61,7 +63,7 @@ export class AgentModule {
|
|
|
61
63
|
async getCurrentState() {
|
|
62
64
|
const queryParams = this.getQueryParams();
|
|
63
65
|
const url = `${this.baseUrl}/api/agent/currentState${queryParams ? `?${queryParams}` : ''}`;
|
|
64
|
-
const response = await
|
|
66
|
+
const response = await fetchWithAuth(url, this.authToken);
|
|
65
67
|
const result = await response.json();
|
|
66
68
|
if (result.status === 'error') {
|
|
67
69
|
throw new Error(result.message);
|
|
@@ -78,7 +80,7 @@ export class AgentModule {
|
|
|
78
80
|
const sessionIdParam = `sessionId=${encodeURIComponent(sessionId)}`;
|
|
79
81
|
const params = queryParams ? `${queryParams}&${sessionIdParam}` : sessionIdParam;
|
|
80
82
|
const url = `${this.baseUrl}/api/agent/askInfo?${params}`;
|
|
81
|
-
const response = await
|
|
83
|
+
const response = await fetchWithAuth(url, this.authToken);
|
|
82
84
|
const result = await response.json();
|
|
83
85
|
if (result.status === 'error') {
|
|
84
86
|
throw new Error(result.message);
|
|
@@ -7,7 +7,8 @@ export declare class FileSystemModule {
|
|
|
7
7
|
private socket;
|
|
8
8
|
private baseUrl;
|
|
9
9
|
private projectId?;
|
|
10
|
-
|
|
10
|
+
private authToken?;
|
|
11
|
+
constructor(socket: Socket, baseUrl: string, projectId?: string | undefined, authToken?: string | undefined);
|
|
11
12
|
/**
|
|
12
13
|
* 获取查询参数
|
|
13
14
|
*/
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { createSocketHandler, onSocketEvent } from '../utils/socket.js';
|
|
2
|
+
import { fetchWithAuth } from '../utils/fetch-auth.js';
|
|
2
3
|
/**
|
|
3
4
|
* 文件系统模块
|
|
4
5
|
*/
|
|
5
6
|
export class FileSystemModule {
|
|
6
|
-
constructor(socket, baseUrl, projectId) {
|
|
7
|
+
constructor(socket, baseUrl, projectId, authToken) {
|
|
7
8
|
this.socket = socket;
|
|
8
9
|
this.baseUrl = baseUrl;
|
|
9
10
|
this.projectId = projectId;
|
|
11
|
+
this.authToken = authToken;
|
|
10
12
|
}
|
|
11
13
|
/**
|
|
12
14
|
* 获取查询参数
|
|
@@ -33,7 +35,7 @@ export class FileSystemModule {
|
|
|
33
35
|
*/
|
|
34
36
|
async stat(filePath) {
|
|
35
37
|
const url = `${this.baseUrl}/api/fs/stat?${this.getQueryParams(filePath)}`;
|
|
36
|
-
const response = await
|
|
38
|
+
const response = await fetchWithAuth(url, this.authToken);
|
|
37
39
|
const result = await response.json();
|
|
38
40
|
if (result.status === 'error') {
|
|
39
41
|
throw new Error(result.message);
|
|
@@ -44,7 +46,7 @@ export class FileSystemModule {
|
|
|
44
46
|
if (asText) {
|
|
45
47
|
// 使用 readFile 端点获取文本内容
|
|
46
48
|
const url = `${this.baseUrl}/api/fs/readFile?${this.getQueryParams(filePath)}`;
|
|
47
|
-
const response = await
|
|
49
|
+
const response = await fetchWithAuth(url, this.authToken);
|
|
48
50
|
const result = await response.json();
|
|
49
51
|
if (result.status === 'error') {
|
|
50
52
|
throw new Error(result.message);
|
|
@@ -54,7 +56,7 @@ export class FileSystemModule {
|
|
|
54
56
|
else {
|
|
55
57
|
// 使用 read 端点获取原始文件(支持二进制)
|
|
56
58
|
const url = `${this.baseUrl}/api/fs/read?${this.getQueryParams(filePath)}`;
|
|
57
|
-
const response = await
|
|
59
|
+
const response = await fetchWithAuth(url, this.authToken);
|
|
58
60
|
if (!response.ok) {
|
|
59
61
|
throw new Error(`Failed to read file: ${response.statusText}`);
|
|
60
62
|
}
|
|
@@ -74,7 +76,7 @@ export class FileSystemModule {
|
|
|
74
76
|
*/
|
|
75
77
|
async readdir(filePath) {
|
|
76
78
|
const url = `${this.baseUrl}/api/fs/readdir?${this.getQueryParams(filePath)}`;
|
|
77
|
-
const response = await
|
|
79
|
+
const response = await fetchWithAuth(url, this.authToken);
|
|
78
80
|
const result = await response.json();
|
|
79
81
|
if (result.status === 'error') {
|
|
80
82
|
throw new Error(result.message);
|
|
@@ -88,7 +90,7 @@ export class FileSystemModule {
|
|
|
88
90
|
*/
|
|
89
91
|
async files(dirPath) {
|
|
90
92
|
const url = `${this.baseUrl}/api/fs/files?${this.getDirQueryParams(dirPath)}`;
|
|
91
|
-
const response = await
|
|
93
|
+
const response = await fetchWithAuth(url, this.authToken);
|
|
92
94
|
const result = await response.json();
|
|
93
95
|
if (result.status === 'error') {
|
|
94
96
|
throw new Error(result.message);
|
|
@@ -7,7 +7,8 @@ export declare class ProjectModule {
|
|
|
7
7
|
private socket;
|
|
8
8
|
private baseUrl;
|
|
9
9
|
private projectId?;
|
|
10
|
-
|
|
10
|
+
private authToken?;
|
|
11
|
+
constructor(socket: Socket, baseUrl: string, projectId?: string | undefined, authToken?: string | undefined);
|
|
11
12
|
/**
|
|
12
13
|
* 获取查询参数
|
|
13
14
|
*/
|
package/dist/modules/project.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { createSocketHandler, onSocketEvent } from '../utils/socket.js';
|
|
2
|
+
import { fetchWithAuth } from '../utils/fetch-auth.js';
|
|
2
3
|
/**
|
|
3
4
|
* 项目模块
|
|
4
5
|
*/
|
|
5
6
|
export class ProjectModule {
|
|
6
|
-
constructor(socket, baseUrl, projectId) {
|
|
7
|
+
constructor(socket, baseUrl, projectId, authToken) {
|
|
7
8
|
this.socket = socket;
|
|
8
9
|
this.baseUrl = baseUrl;
|
|
9
10
|
this.projectId = projectId;
|
|
11
|
+
this.authToken = authToken;
|
|
10
12
|
}
|
|
11
13
|
/**
|
|
12
14
|
* 获取查询参数
|
|
@@ -22,7 +24,7 @@ export class ProjectModule {
|
|
|
22
24
|
*/
|
|
23
25
|
async getInfo() {
|
|
24
26
|
const url = `${this.baseUrl}/project/info${this.projectId ? `?${this.getQueryParams()}` : ''}`;
|
|
25
|
-
const response = await
|
|
27
|
+
const response = await fetchWithAuth(url, this.authToken);
|
|
26
28
|
const result = await response.json();
|
|
27
29
|
if (result.status === 'error') {
|
|
28
30
|
throw new Error(result.message);
|
|
@@ -34,7 +36,7 @@ export class ProjectModule {
|
|
|
34
36
|
*/
|
|
35
37
|
async getFiles() {
|
|
36
38
|
const url = `${this.baseUrl}/project/files${this.projectId ? `?${this.getQueryParams()}` : ''}`;
|
|
37
|
-
const response = await
|
|
39
|
+
const response = await fetchWithAuth(url, this.authToken);
|
|
38
40
|
const result = await response.json();
|
|
39
41
|
if (result.status === 'error') {
|
|
40
42
|
throw new Error(result.message);
|
package/dist/types/index.d.ts
CHANGED
|
@@ -99,6 +99,11 @@ export interface SDKOptions {
|
|
|
99
99
|
url: string;
|
|
100
100
|
/** 项目 ID(可选,用于工作空间模式) */
|
|
101
101
|
projectId?: string;
|
|
102
|
+
/**
|
|
103
|
+
* 与服务器 `authToken` 一致时启用;HTTP 与 Socket 握手会携带 `Authorization` 头
|
|
104
|
+
*(例如 spec-server:`[naslStorageAppId, SBX_SANDBOX_ID].join('|')`)
|
|
105
|
+
*/
|
|
106
|
+
authToken?: string;
|
|
102
107
|
/** 连接选项 */
|
|
103
108
|
options?: {
|
|
104
109
|
/** 自动连接 */
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 带可选 Authorization 的 fetch,与 wave-sandbox-server 的 authToken 鉴权一致
|
|
3
|
+
*/
|
|
4
|
+
export function fetchWithAuth(url, authToken, init) {
|
|
5
|
+
if (!authToken) {
|
|
6
|
+
return fetch(url, init);
|
|
7
|
+
}
|
|
8
|
+
const headers = new Headers(init?.headers);
|
|
9
|
+
headers.set('Authorization', authToken);
|
|
10
|
+
return fetch(url, { ...init, headers });
|
|
11
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lcap/wave-sandbox-sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "SDK for Wave Sandbox Client",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -10,6 +10,15 @@
|
|
|
10
10
|
"src",
|
|
11
11
|
"README.md"
|
|
12
12
|
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "rimraf dist && tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
|
|
15
|
+
"type-check": "tsc --noEmit",
|
|
16
|
+
"dev": "tsc -p tsconfig.build.json --watch & tsc-alias -p tsconfig.build.json --watch",
|
|
17
|
+
"test": "vitest run",
|
|
18
|
+
"lint": "eslint --cache",
|
|
19
|
+
"format": "prettier --write .",
|
|
20
|
+
"prepublishOnly": "pnpm run build"
|
|
21
|
+
},
|
|
13
22
|
"dependencies": {
|
|
14
23
|
"socket.io-client": "^4.8.3"
|
|
15
24
|
},
|
|
@@ -22,13 +31,5 @@
|
|
|
22
31
|
"engines": {
|
|
23
32
|
"node": ">=16.0.0"
|
|
24
33
|
},
|
|
25
|
-
"license": "MIT"
|
|
26
|
-
|
|
27
|
-
"build": "rimraf dist && tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
|
|
28
|
-
"type-check": "tsc --noEmit",
|
|
29
|
-
"dev": "tsc -p tsconfig.build.json --watch & tsc-alias -p tsconfig.build.json --watch",
|
|
30
|
-
"test": "vitest run",
|
|
31
|
-
"lint": "eslint --cache",
|
|
32
|
-
"format": "prettier --write ."
|
|
33
|
-
}
|
|
34
|
-
}
|
|
34
|
+
"license": "MIT"
|
|
35
|
+
}
|
package/src/client.ts
CHANGED
|
@@ -22,7 +22,7 @@ export class WaveSandboxClient {
|
|
|
22
22
|
public readonly agent: AgentModule;
|
|
23
23
|
|
|
24
24
|
constructor(options: SDKOptions) {
|
|
25
|
-
const { url, projectId, options: socketOptions } = options;
|
|
25
|
+
const { url, projectId, authToken, options: socketOptions } = options;
|
|
26
26
|
|
|
27
27
|
const uri = new URL(url);
|
|
28
28
|
let pathname = uri.pathname;
|
|
@@ -33,7 +33,7 @@ export class WaveSandboxClient {
|
|
|
33
33
|
|
|
34
34
|
pathname = pathname + '/socket.io/';
|
|
35
35
|
|
|
36
|
-
// 构建 Socket.IO
|
|
36
|
+
// 构建 Socket.IO 连接选项(Authorization 供服务端 auth 中间件校验)
|
|
37
37
|
const connectOptions = {
|
|
38
38
|
autoConnect: socketOptions?.autoConnect ?? true,
|
|
39
39
|
reconnection: socketOptions?.reconnection ?? true,
|
|
@@ -41,6 +41,16 @@ export class WaveSandboxClient {
|
|
|
41
41
|
reconnectionAttempts: socketOptions?.reconnectionAttempts ?? 5,
|
|
42
42
|
query: projectId ? { projectId } : undefined,
|
|
43
43
|
path: pathname,
|
|
44
|
+
...(authToken
|
|
45
|
+
? {
|
|
46
|
+
extraHeaders: { Authorization: authToken },
|
|
47
|
+
transportOptions: {
|
|
48
|
+
polling: {
|
|
49
|
+
extraHeaders: { Authorization: authToken },
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
}
|
|
53
|
+
: {}),
|
|
44
54
|
};
|
|
45
55
|
|
|
46
56
|
// 创建 Socket.IO 连接
|
|
@@ -48,10 +58,10 @@ export class WaveSandboxClient {
|
|
|
48
58
|
|
|
49
59
|
// 初始化各个模块
|
|
50
60
|
this.exec = new ExecModule(this.socket);
|
|
51
|
-
this.fileSystem = new FileSystemModule(this.socket, url, projectId);
|
|
61
|
+
this.fileSystem = new FileSystemModule(this.socket, url, projectId, authToken);
|
|
52
62
|
this.port = new PortModule(this.socket);
|
|
53
|
-
this.project = new ProjectModule(this.socket, url, projectId);
|
|
54
|
-
this.agent = new AgentModule(this.socket, url, projectId);
|
|
63
|
+
this.project = new ProjectModule(this.socket, url, projectId, authToken);
|
|
64
|
+
this.agent = new AgentModule(this.socket, url, projectId, authToken);
|
|
55
65
|
}
|
|
56
66
|
|
|
57
67
|
/**
|
package/src/modules/agent.ts
CHANGED
|
@@ -9,6 +9,7 @@ import type {
|
|
|
9
9
|
} from '../types/agent-types.js';
|
|
10
10
|
import type { HttpResponse } from '../types/index.js';
|
|
11
11
|
import { createSocketHandler, onSocketEvent } from '../utils/socket.js';
|
|
12
|
+
import { fetchWithAuth } from '../utils/fetch-auth.js';
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* 附件接口
|
|
@@ -289,14 +290,6 @@ export interface AskUserQuestion {
|
|
|
289
290
|
multiSelect?: boolean;
|
|
290
291
|
}
|
|
291
292
|
|
|
292
|
-
/**
|
|
293
|
-
* 询问用户问题事件数据
|
|
294
|
-
*/
|
|
295
|
-
export interface AskUserQuestionEvent {
|
|
296
|
-
questionId: string;
|
|
297
|
-
questions: AskUserQuestion[];
|
|
298
|
-
}
|
|
299
|
-
|
|
300
293
|
/**
|
|
301
294
|
* Ask 信息状态
|
|
302
295
|
*/
|
|
@@ -309,6 +302,11 @@ export interface AskInfo {
|
|
|
309
302
|
answer?: string;
|
|
310
303
|
}
|
|
311
304
|
|
|
305
|
+
/**
|
|
306
|
+
* 询问用户问题事件数据(与 AskInfo 相同)
|
|
307
|
+
*/
|
|
308
|
+
export type AskUserQuestionEvent = AskInfo;
|
|
309
|
+
|
|
312
310
|
/**
|
|
313
311
|
* 客户端回调选项
|
|
314
312
|
*/
|
|
@@ -358,7 +356,8 @@ export class AgentModule {
|
|
|
358
356
|
constructor(
|
|
359
357
|
private socket: Socket,
|
|
360
358
|
private baseUrl: string,
|
|
361
|
-
private projectId?: string
|
|
359
|
+
private projectId?: string,
|
|
360
|
+
private authToken?: string
|
|
362
361
|
) {}
|
|
363
362
|
|
|
364
363
|
/**
|
|
@@ -427,7 +426,7 @@ export class AgentModule {
|
|
|
427
426
|
async getCurrentState(): Promise<MessageQueueChangedEvent | null> {
|
|
428
427
|
const queryParams = this.getQueryParams();
|
|
429
428
|
const url = `${this.baseUrl}/api/agent/currentState${queryParams ? `?${queryParams}` : ''}`;
|
|
430
|
-
const response = await
|
|
429
|
+
const response = await fetchWithAuth(url, this.authToken);
|
|
431
430
|
const result: HttpResponse<MessageQueueChangedEvent | null> = await response.json();
|
|
432
431
|
|
|
433
432
|
if (result.status === 'error') {
|
|
@@ -447,7 +446,7 @@ export class AgentModule {
|
|
|
447
446
|
const sessionIdParam = `sessionId=${encodeURIComponent(sessionId)}`;
|
|
448
447
|
const params = queryParams ? `${queryParams}&${sessionIdParam}` : sessionIdParam;
|
|
449
448
|
const url = `${this.baseUrl}/api/agent/askInfo?${params}`;
|
|
450
|
-
const response = await
|
|
449
|
+
const response = await fetchWithAuth(url, this.authToken);
|
|
451
450
|
const result: HttpResponse<AskInfo | null> = await response.json();
|
|
452
451
|
|
|
453
452
|
if (result.status === 'error') {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Socket } from 'socket.io-client';
|
|
2
2
|
import { createSocketHandler, onSocketEvent } from '../utils/socket.js';
|
|
3
|
+
import { fetchWithAuth } from '../utils/fetch-auth.js';
|
|
3
4
|
import type { FileStat, DirectoryItem, FileChangeEvent, HttpResponse, ProjectFile } from '../types/index.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -9,7 +10,8 @@ export class FileSystemModule {
|
|
|
9
10
|
constructor(
|
|
10
11
|
private socket: Socket,
|
|
11
12
|
private baseUrl: string,
|
|
12
|
-
private projectId?: string
|
|
13
|
+
private projectId?: string,
|
|
14
|
+
private authToken?: string
|
|
13
15
|
) {}
|
|
14
16
|
|
|
15
17
|
/**
|
|
@@ -39,7 +41,7 @@ export class FileSystemModule {
|
|
|
39
41
|
*/
|
|
40
42
|
async stat(filePath: string): Promise<FileStat> {
|
|
41
43
|
const url = `${this.baseUrl}/api/fs/stat?${this.getQueryParams(filePath)}`;
|
|
42
|
-
const response = await
|
|
44
|
+
const response = await fetchWithAuth(url, this.authToken);
|
|
43
45
|
const result: HttpResponse<FileStat> = await response.json();
|
|
44
46
|
|
|
45
47
|
if (result.status === 'error') {
|
|
@@ -61,7 +63,7 @@ export class FileSystemModule {
|
|
|
61
63
|
if (asText) {
|
|
62
64
|
// 使用 readFile 端点获取文本内容
|
|
63
65
|
const url = `${this.baseUrl}/api/fs/readFile?${this.getQueryParams(filePath)}`;
|
|
64
|
-
const response = await
|
|
66
|
+
const response = await fetchWithAuth(url, this.authToken);
|
|
65
67
|
const result: HttpResponse<string> = await response.json();
|
|
66
68
|
|
|
67
69
|
if (result.status === 'error') {
|
|
@@ -72,7 +74,7 @@ export class FileSystemModule {
|
|
|
72
74
|
} else {
|
|
73
75
|
// 使用 read 端点获取原始文件(支持二进制)
|
|
74
76
|
const url = `${this.baseUrl}/api/fs/read?${this.getQueryParams(filePath)}`;
|
|
75
|
-
const response = await
|
|
77
|
+
const response = await fetchWithAuth(url, this.authToken);
|
|
76
78
|
if (!response.ok) {
|
|
77
79
|
throw new Error(`Failed to read file: ${response.statusText}`);
|
|
78
80
|
}
|
|
@@ -94,7 +96,7 @@ export class FileSystemModule {
|
|
|
94
96
|
*/
|
|
95
97
|
async readdir(filePath: string): Promise<DirectoryItem[]> {
|
|
96
98
|
const url = `${this.baseUrl}/api/fs/readdir?${this.getQueryParams(filePath)}`;
|
|
97
|
-
const response = await
|
|
99
|
+
const response = await fetchWithAuth(url, this.authToken);
|
|
98
100
|
const result: HttpResponse<DirectoryItem[]> = await response.json();
|
|
99
101
|
|
|
100
102
|
if (result.status === 'error') {
|
|
@@ -111,7 +113,7 @@ export class FileSystemModule {
|
|
|
111
113
|
*/
|
|
112
114
|
async files(dirPath: string): Promise<Record<string, ProjectFile>> {
|
|
113
115
|
const url = `${this.baseUrl}/api/fs/files?${this.getDirQueryParams(dirPath)}`;
|
|
114
|
-
const response = await
|
|
116
|
+
const response = await fetchWithAuth(url, this.authToken);
|
|
115
117
|
const result: HttpResponse<Record<string, ProjectFile>> = await response.json();
|
|
116
118
|
|
|
117
119
|
if (result.status === 'error') {
|
package/src/modules/project.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Socket } from 'socket.io-client';
|
|
2
2
|
import { createSocketHandler, onSocketEvent } from '../utils/socket.js';
|
|
3
|
+
import { fetchWithAuth } from '../utils/fetch-auth.js';
|
|
3
4
|
import type { ProjectInfo, ProjectFile, HttpResponse, FileChangeEvent } from '../types/index.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -9,7 +10,8 @@ export class ProjectModule {
|
|
|
9
10
|
constructor(
|
|
10
11
|
private socket: Socket,
|
|
11
12
|
private baseUrl: string,
|
|
12
|
-
private projectId?: string
|
|
13
|
+
private projectId?: string,
|
|
14
|
+
private authToken?: string
|
|
13
15
|
) {}
|
|
14
16
|
|
|
15
17
|
/**
|
|
@@ -27,7 +29,7 @@ export class ProjectModule {
|
|
|
27
29
|
*/
|
|
28
30
|
async getInfo(): Promise<ProjectInfo> {
|
|
29
31
|
const url = `${this.baseUrl}/project/info${this.projectId ? `?${this.getQueryParams()}` : ''}`;
|
|
30
|
-
const response = await
|
|
32
|
+
const response = await fetchWithAuth(url, this.authToken);
|
|
31
33
|
const result: HttpResponse<ProjectInfo> = await response.json();
|
|
32
34
|
|
|
33
35
|
if (result.status === 'error') {
|
|
@@ -42,7 +44,7 @@ export class ProjectModule {
|
|
|
42
44
|
*/
|
|
43
45
|
async getFiles(): Promise<ProjectFile[]> {
|
|
44
46
|
const url = `${this.baseUrl}/project/files${this.projectId ? `?${this.getQueryParams()}` : ''}`;
|
|
45
|
-
const response = await
|
|
47
|
+
const response = await fetchWithAuth(url, this.authToken);
|
|
46
48
|
const result: HttpResponse<{ files: ProjectFile[] }> = await response.json();
|
|
47
49
|
|
|
48
50
|
if (result.status === 'error') {
|
package/src/types/index.ts
CHANGED
|
@@ -114,6 +114,11 @@ export interface SDKOptions {
|
|
|
114
114
|
url: string;
|
|
115
115
|
/** 项目 ID(可选,用于工作空间模式) */
|
|
116
116
|
projectId?: string;
|
|
117
|
+
/**
|
|
118
|
+
* 与服务器 `authToken` 一致时启用;HTTP 与 Socket 握手会携带 `Authorization` 头
|
|
119
|
+
*(例如 spec-server:`[naslStorageAppId, SBX_SANDBOX_ID].join('|')`)
|
|
120
|
+
*/
|
|
121
|
+
authToken?: string;
|
|
117
122
|
/** 连接选项 */
|
|
118
123
|
options?: {
|
|
119
124
|
/** 自动连接 */
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 带可选 Authorization 的 fetch,与 wave-sandbox-server 的 authToken 鉴权一致
|
|
3
|
+
*/
|
|
4
|
+
export function fetchWithAuth(url: string | URL, authToken: string | undefined, init?: RequestInit): Promise<Response> {
|
|
5
|
+
if (!authToken) {
|
|
6
|
+
return fetch(url, init);
|
|
7
|
+
}
|
|
8
|
+
const headers = new Headers(init?.headers);
|
|
9
|
+
headers.set('Authorization', authToken);
|
|
10
|
+
return fetch(url, { ...init, headers });
|
|
11
|
+
}
|