ssh-agent-workspace 1.0.5 → 1.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/README.md +471 -471
- package/dist/__tests__/SSHManager.test.js +59 -37
- package/dist/__tests__/SSHManager.test.js.map +1 -1
- package/dist/__tests__/SessionManager.test.js +53 -51
- package/dist/__tests__/SessionManager.test.js.map +1 -1
- package/dist/__tests__/StorageManager.test.js +74 -74
- package/dist/__tests__/StorageManager.test.js.map +1 -1
- package/dist/__tests__/ansi.test.js +33 -33
- package/dist/__tests__/ansi.test.js.map +1 -1
- package/dist/__tests__/security.test.js +54 -54
- package/dist/__tests__/security.test.js.map +1 -1
- package/dist/__tests__/validation.test.js +17 -17
- package/dist/__tests__/validation.test.js.map +1 -1
- package/dist/core/HostSecurityManager.d.ts.map +1 -1
- package/dist/core/HostSecurityManager.js +9 -9
- package/dist/core/HostSecurityManager.js.map +1 -1
- package/dist/core/SSHManager.d.ts +1 -1
- package/dist/core/SSHManager.d.ts.map +1 -1
- package/dist/core/SSHManager.js +31 -31
- package/dist/core/SSHManager.js.map +1 -1
- package/dist/core/SessionManager.d.ts +4 -4
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +14 -14
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/core/StorageManager.d.ts.map +1 -1
- package/dist/core/StorageManager.js +11 -11
- package/dist/core/StorageManager.js.map +1 -1
- package/dist/core/TmuxManager.d.ts +3 -3
- package/dist/core/TmuxManager.d.ts.map +1 -1
- package/dist/core/TmuxManager.js +16 -16
- package/dist/core/TmuxManager.js.map +1 -1
- package/dist/core/ToolConfigManager.d.ts.map +1 -1
- package/dist/core/ToolConfigManager.js +10 -10
- package/dist/core/ToolConfigManager.js.map +1 -1
- package/dist/index.js +35 -35
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +4 -4
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +41 -41
- package/dist/server.js.map +1 -1
- package/dist/tools/backup.d.ts +3 -3
- package/dist/tools/backup.d.ts.map +1 -1
- package/dist/tools/backup.js +86 -49
- package/dist/tools/backup.js.map +1 -1
- package/dist/tools/connect.d.ts +4 -4
- package/dist/tools/connect.d.ts.map +1 -1
- package/dist/tools/connect.js +54 -42
- package/dist/tools/connect.js.map +1 -1
- package/dist/tools/connection_status.d.ts +4 -4
- package/dist/tools/connection_status.d.ts.map +1 -1
- package/dist/tools/connection_status.js +23 -16
- package/dist/tools/connection_status.js.map +1 -1
- package/dist/tools/db_query.d.ts +3 -3
- package/dist/tools/db_query.d.ts.map +1 -1
- package/dist/tools/db_query.js +130 -78
- package/dist/tools/db_query.js.map +1 -1
- package/dist/tools/deploy.d.ts +3 -3
- package/dist/tools/deploy.d.ts.map +1 -1
- package/dist/tools/deploy.js +103 -53
- package/dist/tools/deploy.js.map +1 -1
- package/dist/tools/disconnect.d.ts +3 -3
- package/dist/tools/disconnect.d.ts.map +1 -1
- package/dist/tools/disconnect.js +16 -19
- package/dist/tools/disconnect.js.map +1 -1
- package/dist/tools/exec.d.ts +3 -3
- package/dist/tools/exec.d.ts.map +1 -1
- package/dist/tools/exec.js +40 -45
- package/dist/tools/exec.js.map +1 -1
- package/dist/tools/group_exec.d.ts +3 -3
- package/dist/tools/group_exec.d.ts.map +1 -1
- package/dist/tools/group_exec.js +60 -44
- package/dist/tools/group_exec.js.map +1 -1
- package/dist/tools/health_check.d.ts +3 -3
- package/dist/tools/health_check.d.ts.map +1 -1
- package/dist/tools/health_check.js +27 -23
- package/dist/tools/health_check.js.map +1 -1
- package/dist/tools/host_security.d.ts +1 -1
- package/dist/tools/host_security.d.ts.map +1 -1
- package/dist/tools/host_security.js +30 -36
- package/dist/tools/host_security.js.map +1 -1
- package/dist/tools/index.d.ts +23 -23
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +23 -23
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/interrupt.d.ts +3 -3
- package/dist/tools/interrupt.d.ts.map +1 -1
- package/dist/tools/interrupt.js +18 -18
- package/dist/tools/interrupt.js.map +1 -1
- package/dist/tools/list_hosts.d.ts.map +1 -1
- package/dist/tools/list_hosts.js +5 -7
- package/dist/tools/list_hosts.js.map +1 -1
- package/dist/tools/list_sessions.d.ts +1 -1
- package/dist/tools/list_sessions.js +4 -4
- package/dist/tools/list_sessions.js.map +1 -1
- package/dist/tools/read_output.d.ts +3 -3
- package/dist/tools/read_output.d.ts.map +1 -1
- package/dist/tools/read_output.js +17 -17
- package/dist/tools/read_output.js.map +1 -1
- package/dist/tools/reconnect_to_tmux.d.ts +4 -4
- package/dist/tools/reconnect_to_tmux.d.ts.map +1 -1
- package/dist/tools/reconnect_to_tmux.js +44 -37
- package/dist/tools/reconnect_to_tmux.js.map +1 -1
- package/dist/tools/send_input.d.ts +3 -3
- package/dist/tools/send_input.d.ts.map +1 -1
- package/dist/tools/send_input.js +18 -18
- package/dist/tools/send_input.js.map +1 -1
- package/dist/tools/sftp_download.d.ts +3 -3
- package/dist/tools/sftp_download.d.ts.map +1 -1
- package/dist/tools/sftp_download.js +41 -27
- package/dist/tools/sftp_download.js.map +1 -1
- package/dist/tools/sftp_list.d.ts +3 -3
- package/dist/tools/sftp_list.d.ts.map +1 -1
- package/dist/tools/sftp_list.js +35 -26
- package/dist/tools/sftp_list.js.map +1 -1
- package/dist/tools/sftp_upload.d.ts +3 -3
- package/dist/tools/sftp_upload.d.ts.map +1 -1
- package/dist/tools/sftp_upload.js +43 -29
- package/dist/tools/sftp_upload.js.map +1 -1
- package/dist/tools/ssh_tunnel.d.ts +3 -3
- package/dist/tools/ssh_tunnel.d.ts.map +1 -1
- package/dist/tools/ssh_tunnel.js +130 -76
- package/dist/tools/ssh_tunnel.js.map +1 -1
- package/dist/tools/sync.d.ts +3 -3
- package/dist/tools/sync.d.ts.map +1 -1
- package/dist/tools/sync.js +103 -61
- package/dist/tools/sync.js.map +1 -1
- package/dist/tools/tail_log.d.ts +3 -3
- package/dist/tools/tail_log.d.ts.map +1 -1
- package/dist/tools/tail_log.js +38 -26
- package/dist/tools/tail_log.js.map +1 -1
- package/dist/tools/tools_config.d.ts +1 -1
- package/dist/tools/tools_config.d.ts.map +1 -1
- package/dist/tools/tools_config.js +25 -35
- package/dist/tools/tools_config.js.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/ansi.js +1 -1
- package/dist/utils/ansi.js.map +1 -1
- package/dist/utils/logger.d.ts +1 -1
- package/dist/utils/logger.js +2 -2
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/security.d.ts +1 -1
- package/dist/utils/security.js +3 -3
- package/dist/utils/security.js.map +1 -1
- package/dist/utils/ssh.d.ts +2 -2
- package/dist/utils/ssh.js +5 -5
- package/dist/utils/ssh.js.map +1 -1
- package/dist/utils/sshConfig.d.ts +1 -1
- package/dist/utils/sshConfig.d.ts.map +1 -1
- package/dist/utils/sshConfig.js +21 -21
- package/dist/utils/sshConfig.js.map +1 -1
- package/dist/utils/validation.d.ts +1 -1
- package/dist/utils/validation.js +3 -3
- package/dist/utils/validation.js.map +1 -1
- package/docs/SECURITY.md +213 -213
- package/docs/TOOLS.md +425 -425
- package/package.json +59 -48
- package/vitest.config.ts +10 -10
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from
|
|
2
|
-
import { SSHManager } from
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
import { SSHManager } from "../core/SSHManager.js";
|
|
3
3
|
function createMockSftp() {
|
|
4
4
|
return {
|
|
5
5
|
fastPut: vi.fn(),
|
|
@@ -22,112 +22,134 @@ function createMockSsh(sftp) {
|
|
|
22
22
|
removeAllListeners: vi.fn(),
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
|
-
describe(
|
|
25
|
+
describe("SSHManager SFTP", () => {
|
|
26
26
|
let sshManager;
|
|
27
27
|
beforeEach(() => {
|
|
28
28
|
sshManager = new SSHManager();
|
|
29
29
|
});
|
|
30
|
-
describe(
|
|
31
|
-
it(
|
|
30
|
+
describe("sftpUpload", () => {
|
|
31
|
+
it("should upload a file successfully", async () => {
|
|
32
32
|
const sftp = createMockSftp();
|
|
33
33
|
sftp.fastPut.mockImplementation((local, remote, cb) => {
|
|
34
34
|
cb(undefined);
|
|
35
35
|
});
|
|
36
36
|
const ssh = createMockSsh(sftp);
|
|
37
|
-
await expect(sshManager.sftpUpload(ssh,
|
|
38
|
-
expect(sftp.fastPut).toHaveBeenCalledWith(
|
|
37
|
+
await expect(sshManager.sftpUpload(ssh, "/local/file.txt", "/remote/file.txt")).resolves.not.toThrow();
|
|
38
|
+
expect(sftp.fastPut).toHaveBeenCalledWith("/local/file.txt", "/remote/file.txt", expect.any(Function));
|
|
39
39
|
});
|
|
40
|
-
it(
|
|
40
|
+
it("should reject on SFTP error", async () => {
|
|
41
41
|
const sftp = createMockSftp();
|
|
42
42
|
sftp.fastPut.mockImplementation((_l, _r, cb) => {
|
|
43
|
-
cb(new Error(
|
|
43
|
+
cb(new Error("Upload failed"));
|
|
44
44
|
});
|
|
45
45
|
const ssh = createMockSsh(sftp);
|
|
46
|
-
await expect(sshManager.sftpUpload(ssh,
|
|
46
|
+
await expect(sshManager.sftpUpload(ssh, "/local/file.txt", "/remote/file.txt")).rejects.toThrow("Upload failed");
|
|
47
47
|
});
|
|
48
48
|
});
|
|
49
|
-
describe(
|
|
50
|
-
it(
|
|
49
|
+
describe("sftpDownload", () => {
|
|
50
|
+
it("should download a file successfully", async () => {
|
|
51
51
|
const sftp = createMockSftp();
|
|
52
52
|
sftp.fastGet.mockImplementation((remote, local, cb) => {
|
|
53
53
|
cb(undefined);
|
|
54
54
|
});
|
|
55
55
|
const ssh = createMockSsh(sftp);
|
|
56
|
-
await expect(sshManager.sftpDownload(ssh,
|
|
57
|
-
expect(sftp.fastGet).toHaveBeenCalledWith(
|
|
56
|
+
await expect(sshManager.sftpDownload(ssh, "/remote/file.txt", "/local/file.txt")).resolves.not.toThrow();
|
|
57
|
+
expect(sftp.fastGet).toHaveBeenCalledWith("/remote/file.txt", "/local/file.txt", expect.any(Function));
|
|
58
58
|
});
|
|
59
59
|
});
|
|
60
|
-
describe(
|
|
61
|
-
it(
|
|
60
|
+
describe("sftpList", () => {
|
|
61
|
+
it("should list directory entries", async () => {
|
|
62
62
|
const sftp = createMockSftp();
|
|
63
63
|
sftp.readdir.mockImplementation((_path, cb) => {
|
|
64
64
|
cb(undefined, [
|
|
65
|
-
{
|
|
66
|
-
|
|
65
|
+
{
|
|
66
|
+
filename: "file.txt",
|
|
67
|
+
longname: "-rw-r--r-- 1 user group 100 Jan 1 2024 file.txt",
|
|
68
|
+
attrs: {
|
|
69
|
+
mode: 0o100644,
|
|
70
|
+
size: 100,
|
|
71
|
+
uid: 1000,
|
|
72
|
+
gid: 1000,
|
|
73
|
+
atime: 1700000000,
|
|
74
|
+
mtime: 1700000000,
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
filename: "dir",
|
|
79
|
+
longname: "drwxr-xr-x 1 user group 0 Jan 1 2024 dir",
|
|
80
|
+
attrs: { mode: 0o040755, size: 0, uid: 1000, gid: 1000, atime: 1700000000, mtime: 1700000000 },
|
|
81
|
+
},
|
|
67
82
|
]);
|
|
68
83
|
});
|
|
69
84
|
const ssh = createMockSsh(sftp);
|
|
70
|
-
const entries = await sshManager.sftpList(ssh,
|
|
85
|
+
const entries = await sshManager.sftpList(ssh, "/remote");
|
|
71
86
|
expect(entries).toHaveLength(2);
|
|
72
|
-
expect(entries[0].filename).toBe(
|
|
87
|
+
expect(entries[0].filename).toBe("file.txt");
|
|
73
88
|
expect(entries[0].attrs.isFile).toBe(true);
|
|
74
89
|
expect(entries[0].attrs.isDirectory).toBe(false);
|
|
75
|
-
expect(entries[1].filename).toBe(
|
|
90
|
+
expect(entries[1].filename).toBe("dir");
|
|
76
91
|
expect(entries[1].attrs.isDirectory).toBe(true);
|
|
77
92
|
expect(entries[1].attrs.isFile).toBe(false);
|
|
78
93
|
});
|
|
79
94
|
});
|
|
80
|
-
describe(
|
|
81
|
-
it(
|
|
95
|
+
describe("sftpStat", () => {
|
|
96
|
+
it("should return file stats", async () => {
|
|
82
97
|
const sftp = createMockSftp();
|
|
83
98
|
sftp.stat.mockImplementation((_path, cb) => {
|
|
84
|
-
cb(undefined, {
|
|
99
|
+
cb(undefined, {
|
|
100
|
+
mode: 0o100644,
|
|
101
|
+
size: 1024,
|
|
102
|
+
uid: 1000,
|
|
103
|
+
gid: 1000,
|
|
104
|
+
atime: 1700000000,
|
|
105
|
+
mtime: 1700000000,
|
|
106
|
+
});
|
|
85
107
|
});
|
|
86
108
|
const ssh = createMockSsh(sftp);
|
|
87
|
-
const stats = await sshManager.sftpStat(ssh,
|
|
109
|
+
const stats = await sshManager.sftpStat(ssh, "/remote/file.txt");
|
|
88
110
|
expect(stats.size).toBe(1024);
|
|
89
111
|
expect(stats.isFile).toBe(true);
|
|
90
112
|
expect(stats.isDirectory).toBe(false);
|
|
91
113
|
});
|
|
92
114
|
});
|
|
93
|
-
describe(
|
|
94
|
-
it(
|
|
115
|
+
describe("sftpExists", () => {
|
|
116
|
+
it("should return true when file exists", async () => {
|
|
95
117
|
const sftp = createMockSftp();
|
|
96
118
|
sftp.stat.mockImplementation((_path, cb) => {
|
|
97
119
|
cb(undefined, { mode: 0o100644, size: 0, uid: 0, gid: 0, atime: 0, mtime: 0 });
|
|
98
120
|
});
|
|
99
121
|
const ssh = createMockSsh(sftp);
|
|
100
|
-
const exists = await sshManager.sftpExists(ssh,
|
|
122
|
+
const exists = await sshManager.sftpExists(ssh, "/remote/file.txt");
|
|
101
123
|
expect(exists).toBe(true);
|
|
102
124
|
});
|
|
103
|
-
it(
|
|
125
|
+
it("should return false when file does not exist", async () => {
|
|
104
126
|
const sftp = createMockSftp();
|
|
105
127
|
sftp.stat.mockImplementation((_path, cb) => {
|
|
106
|
-
cb(new Error(
|
|
128
|
+
cb(new Error("No such file"), undefined);
|
|
107
129
|
});
|
|
108
130
|
const ssh = createMockSsh(sftp);
|
|
109
|
-
const exists = await sshManager.sftpExists(ssh,
|
|
131
|
+
const exists = await sshManager.sftpExists(ssh, "/remote/nonexistent.txt");
|
|
110
132
|
expect(exists).toBe(false);
|
|
111
133
|
});
|
|
112
134
|
});
|
|
113
|
-
describe(
|
|
114
|
-
it(
|
|
135
|
+
describe("sftpMkdir", () => {
|
|
136
|
+
it("should create directory", async () => {
|
|
115
137
|
const sftp = createMockSftp();
|
|
116
138
|
sftp.mkdir.mockImplementation((_path, _opts, cb) => {
|
|
117
139
|
cb(undefined);
|
|
118
140
|
});
|
|
119
141
|
const ssh = createMockSsh(sftp);
|
|
120
|
-
await expect(sshManager.sftpMkdir(ssh,
|
|
142
|
+
await expect(sshManager.sftpMkdir(ssh, "/remote/newdir")).resolves.not.toThrow();
|
|
121
143
|
});
|
|
122
144
|
});
|
|
123
|
-
describe(
|
|
124
|
-
it(
|
|
145
|
+
describe("sftpUnlink", () => {
|
|
146
|
+
it("should delete file", async () => {
|
|
125
147
|
const sftp = createMockSftp();
|
|
126
148
|
sftp.unlink.mockImplementation((_path, cb) => {
|
|
127
149
|
cb(undefined);
|
|
128
150
|
});
|
|
129
151
|
const ssh = createMockSsh(sftp);
|
|
130
|
-
await expect(sshManager.sftpUnlink(ssh,
|
|
152
|
+
await expect(sshManager.sftpUnlink(ssh, "/remote/file.txt")).resolves.not.toThrow();
|
|
131
153
|
});
|
|
132
154
|
});
|
|
133
155
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SSHManager.test.js","sourceRoot":"","sources":["../../src/__tests__/SSHManager.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAGnD,SAAS,cAAc;
|
|
1
|
+
{"version":3,"file":"SSHManager.test.js","sourceRoot":"","sources":["../../src/__tests__/SSHManager.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach } from
|
|
2
|
-
import { SessionManager } from
|
|
3
|
-
import { StorageManager } from
|
|
1
|
+
import { describe, it, expect, beforeEach } from "vitest";
|
|
2
|
+
import { SessionManager } from "../core/SessionManager.js";
|
|
3
|
+
import { StorageManager } from "../core/StorageManager.js";
|
|
4
4
|
function createMockSsh() {
|
|
5
5
|
const listeners = {};
|
|
6
6
|
return {
|
|
@@ -15,8 +15,8 @@ function createMockSsh() {
|
|
|
15
15
|
}
|
|
16
16
|
},
|
|
17
17
|
destroy: () => {
|
|
18
|
-
if (listeners[
|
|
19
|
-
listeners[
|
|
18
|
+
if (listeners["close"]) {
|
|
19
|
+
listeners["close"].forEach((cb) => cb());
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
22
|
removeAllListeners: (event) => {
|
|
@@ -25,115 +25,117 @@ function createMockSsh() {
|
|
|
25
25
|
listeners,
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
|
-
describe(
|
|
28
|
+
describe("SessionManager", () => {
|
|
29
29
|
let storage;
|
|
30
30
|
let sessionManager;
|
|
31
31
|
beforeEach(() => {
|
|
32
32
|
storage = new StorageManager();
|
|
33
33
|
sessionManager = new SessionManager(storage);
|
|
34
34
|
});
|
|
35
|
-
it(
|
|
35
|
+
it("should create a session with auto-generated ID", () => {
|
|
36
36
|
const ssh = createMockSsh();
|
|
37
|
-
const session = sessionManager.create(
|
|
37
|
+
const session = sessionManager.create("prod", ssh, "mcp_prod_abc", "bash");
|
|
38
38
|
expect(session.id).toMatch(/^sess_[a-f0-9]{32}$/);
|
|
39
|
-
expect(session.host).toBe(
|
|
40
|
-
expect(session.tmuxSession).toBe(
|
|
41
|
-
expect(session.shell).toBe(
|
|
39
|
+
expect(session.host).toBe("prod");
|
|
40
|
+
expect(session.tmuxSession).toBe("mcp_prod_abc");
|
|
41
|
+
expect(session.shell).toBe("bash");
|
|
42
42
|
expect(session.connectedAt).toBeGreaterThan(0);
|
|
43
43
|
expect(session.lastActivity).toBeGreaterThan(0);
|
|
44
44
|
});
|
|
45
|
-
it(
|
|
45
|
+
it("should create a session with existing ID", () => {
|
|
46
46
|
const ssh = createMockSsh();
|
|
47
|
-
const session = sessionManager.create(
|
|
48
|
-
expect(session.id).toBe(
|
|
47
|
+
const session = sessionManager.create("prod", ssh, "mcp_prod_abc", "bash", "sess_existing123");
|
|
48
|
+
expect(session.id).toBe("sess_existing123");
|
|
49
49
|
});
|
|
50
|
-
it(
|
|
50
|
+
it("should get session by ID", () => {
|
|
51
51
|
const ssh = createMockSsh();
|
|
52
|
-
const session = sessionManager.create(
|
|
52
|
+
const session = sessionManager.create("staging", ssh, "mcp_staging_xyz");
|
|
53
53
|
const retrieved = sessionManager.get(session.id);
|
|
54
54
|
expect(retrieved).toBeDefined();
|
|
55
|
-
expect(retrieved.host).toBe(
|
|
56
|
-
expect(retrieved.tmuxSession).toBe(
|
|
55
|
+
expect(retrieved.host).toBe("staging");
|
|
56
|
+
expect(retrieved.tmuxSession).toBe("mcp_staging_xyz");
|
|
57
57
|
});
|
|
58
|
-
it(
|
|
59
|
-
const result = sessionManager.get(
|
|
58
|
+
it("should return undefined for non-existent session", () => {
|
|
59
|
+
const result = sessionManager.get("sess_nonexistent");
|
|
60
60
|
expect(result).toBeUndefined();
|
|
61
61
|
});
|
|
62
|
-
it(
|
|
62
|
+
it("should update lastActivity on get", () => {
|
|
63
63
|
const ssh = createMockSsh();
|
|
64
|
-
const session = sessionManager.create(
|
|
64
|
+
const session = sessionManager.create("prod", ssh, "mcp_prod");
|
|
65
65
|
const before = session.lastActivity;
|
|
66
66
|
// Wait 10ms to ensure timestamp changes
|
|
67
67
|
const retrieved = sessionManager.get(session.id);
|
|
68
68
|
// get() should update lastActivity
|
|
69
69
|
expect(session.lastActivity).toBeGreaterThanOrEqual(before);
|
|
70
70
|
});
|
|
71
|
-
it(
|
|
71
|
+
it("should remove session and destroy SSH", () => {
|
|
72
72
|
const ssh = createMockSsh();
|
|
73
73
|
let destroyed = false;
|
|
74
|
-
ssh.destroy = () => {
|
|
75
|
-
|
|
74
|
+
ssh.destroy = () => {
|
|
75
|
+
destroyed = true;
|
|
76
|
+
};
|
|
77
|
+
const session = sessionManager.create("prod", ssh, "mcp_prod");
|
|
76
78
|
const removed = sessionManager.remove(session.id);
|
|
77
79
|
expect(removed).toBe(true);
|
|
78
80
|
expect(destroyed).toBe(true);
|
|
79
81
|
expect(sessionManager.has(session.id)).toBe(false);
|
|
80
82
|
expect(sessionManager.get(session.id)).toBeUndefined();
|
|
81
83
|
});
|
|
82
|
-
it(
|
|
83
|
-
const result = sessionManager.remove(
|
|
84
|
+
it("should return false when removing non-existent session", () => {
|
|
85
|
+
const result = sessionManager.remove("sess_nonexistent");
|
|
84
86
|
expect(result).toBe(false);
|
|
85
87
|
});
|
|
86
|
-
it(
|
|
88
|
+
it("should auto-remove session when SSH closes", () => {
|
|
87
89
|
const ssh = createMockSsh();
|
|
88
|
-
const session = sessionManager.create(
|
|
90
|
+
const session = sessionManager.create("prod", ssh, "mcp_prod");
|
|
89
91
|
expect(sessionManager.has(session.id)).toBe(true);
|
|
90
92
|
// Simulate SSH close event
|
|
91
|
-
ssh.emit(
|
|
93
|
+
ssh.emit("close");
|
|
92
94
|
expect(sessionManager.has(session.id)).toBe(false);
|
|
93
95
|
});
|
|
94
|
-
it(
|
|
96
|
+
it("should list all sessions", () => {
|
|
95
97
|
const ssh1 = createMockSsh();
|
|
96
98
|
const ssh2 = createMockSsh();
|
|
97
|
-
sessionManager.create(
|
|
98
|
-
sessionManager.create(
|
|
99
|
+
sessionManager.create("prod", ssh1, "mcp_prod_1");
|
|
100
|
+
sessionManager.create("staging", ssh2, "mcp_staging_1");
|
|
99
101
|
const list = sessionManager.list();
|
|
100
102
|
expect(list).toHaveLength(2);
|
|
101
|
-
expect(list[0]).toHaveProperty(
|
|
102
|
-
expect(list[0]).toHaveProperty(
|
|
103
|
-
expect(list[0]).toHaveProperty(
|
|
104
|
-
expect(list[0]).toHaveProperty(
|
|
105
|
-
expect(list[0]).toHaveProperty(
|
|
103
|
+
expect(list[0]).toHaveProperty("id");
|
|
104
|
+
expect(list[0]).toHaveProperty("host");
|
|
105
|
+
expect(list[0]).toHaveProperty("connectedAt");
|
|
106
|
+
expect(list[0]).toHaveProperty("lastActivity");
|
|
107
|
+
expect(list[0]).toHaveProperty("tmuxSession");
|
|
106
108
|
});
|
|
107
|
-
it(
|
|
109
|
+
it("should disconnect all sessions", () => {
|
|
108
110
|
const ssh1 = createMockSsh();
|
|
109
111
|
const ssh2 = createMockSsh();
|
|
110
|
-
sessionManager.create(
|
|
111
|
-
sessionManager.create(
|
|
112
|
+
sessionManager.create("prod", ssh1, "mcp_prod_1");
|
|
113
|
+
sessionManager.create("staging", ssh2, "mcp_staging_1");
|
|
112
114
|
expect(sessionManager.count).toBe(2);
|
|
113
115
|
sessionManager.disconnectAll();
|
|
114
116
|
expect(sessionManager.count).toBe(0);
|
|
115
117
|
});
|
|
116
|
-
it(
|
|
118
|
+
it("should track session count", () => {
|
|
117
119
|
expect(sessionManager.count).toBe(0);
|
|
118
120
|
const ssh1 = createMockSsh();
|
|
119
|
-
sessionManager.create(
|
|
121
|
+
sessionManager.create("prod", ssh1, "mcp_prod_1");
|
|
120
122
|
expect(sessionManager.count).toBe(1);
|
|
121
123
|
const ssh2 = createMockSsh();
|
|
122
|
-
sessionManager.create(
|
|
124
|
+
sessionManager.create("staging", ssh2, "mcp_staging_1");
|
|
123
125
|
expect(sessionManager.count).toBe(2);
|
|
124
126
|
});
|
|
125
|
-
it(
|
|
127
|
+
it("should persist session to storage on create", () => {
|
|
126
128
|
const ssh = createMockSsh();
|
|
127
|
-
const session = sessionManager.create(
|
|
129
|
+
const session = sessionManager.create("prod", ssh, "mcp_prod_abc", "bash");
|
|
128
130
|
const stored = storage.get(session.id);
|
|
129
131
|
expect(stored).toBeDefined();
|
|
130
|
-
expect(stored.host).toBe(
|
|
131
|
-
expect(stored.tmuxSession).toBe(
|
|
132
|
-
expect(stored.shell).toBe(
|
|
132
|
+
expect(stored.host).toBe("prod");
|
|
133
|
+
expect(stored.tmuxSession).toBe("mcp_prod_abc");
|
|
134
|
+
expect(stored.shell).toBe("bash");
|
|
133
135
|
});
|
|
134
|
-
it(
|
|
136
|
+
it("should remove session from storage on remove", () => {
|
|
135
137
|
const ssh = createMockSsh();
|
|
136
|
-
const session = sessionManager.create(
|
|
138
|
+
const session = sessionManager.create("prod", ssh, "mcp_prod_abc");
|
|
137
139
|
sessionManager.remove(session.id);
|
|
138
140
|
expect(storage.get(session.id)).toBeUndefined();
|
|
139
141
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionManager.test.js","sourceRoot":"","sources":["../../src/__tests__/SessionManager.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAG3D,SAAS,aAAa;
|
|
1
|
+
{"version":3,"file":"SessionManager.test.js","sourceRoot":"","sources":["../../src/__tests__/SessionManager.test.ts"],"names":[],"mappings":"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"}
|