typescript-virtual-container 1.1.2 → 1.1.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.
Files changed (49) hide show
  1. package/dist/SSHMimic/exec.d.ts.map +1 -1
  2. package/dist/SSHMimic/exec.js +8 -2
  3. package/dist/SSHMimic/index.d.ts +1 -0
  4. package/dist/SSHMimic/index.d.ts.map +1 -1
  5. package/dist/SSHMimic/index.js +9 -3
  6. package/dist/SSHMimic/sftp.d.ts +46 -0
  7. package/dist/SSHMimic/sftp.d.ts.map +1 -0
  8. package/dist/SSHMimic/sftp.js +576 -0
  9. package/dist/VirtualFileSystem/index.d.ts +6 -4
  10. package/dist/VirtualFileSystem/index.d.ts.map +1 -1
  11. package/dist/VirtualFileSystem/index.js +144 -153
  12. package/dist/VirtualShell/index.d.ts +6 -0
  13. package/dist/VirtualShell/index.d.ts.map +1 -1
  14. package/dist/VirtualShell/index.js +16 -4
  15. package/dist/VirtualShell/shell.d.ts.map +1 -1
  16. package/dist/VirtualShell/shell.js +7 -0
  17. package/dist/VirtualUserManager/index.d.ts +8 -0
  18. package/dist/VirtualUserManager/index.d.ts.map +1 -1
  19. package/dist/VirtualUserManager/index.js +30 -0
  20. package/dist/commands/exit.d.ts.map +1 -1
  21. package/dist/commands/exit.js +1 -0
  22. package/dist/commands/index.d.ts.map +1 -1
  23. package/dist/commands/index.js +2 -0
  24. package/dist/commands/passwd.d.ts +3 -0
  25. package/dist/commands/passwd.d.ts.map +1 -0
  26. package/dist/commands/passwd.js +21 -0
  27. package/dist/index.d.ts +2 -2
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +2 -2
  30. package/dist/modules/neofetch.d.ts.map +1 -1
  31. package/dist/modules/neofetch.js +0 -1
  32. package/dist/standalone.js +10 -1
  33. package/package.json +1 -1
  34. package/src/SSHMimic/exec.ts +18 -12
  35. package/src/SSHMimic/index.ts +16 -7
  36. package/src/SSHMimic/sftp.ts +833 -0
  37. package/src/VirtualFileSystem/index.ts +158 -188
  38. package/src/VirtualShell/index.ts +19 -8
  39. package/src/VirtualShell/shell.ts +7 -0
  40. package/src/VirtualUserManager/index.ts +38 -0
  41. package/src/commands/exit.ts +1 -0
  42. package/src/commands/index.ts +2 -0
  43. package/src/commands/passwd.ts +25 -0
  44. package/src/index.ts +2 -1
  45. package/src/modules/neofetch.ts +0 -2
  46. package/src/standalone.ts +11 -1
  47. package/tests/sftp.test.ts +319 -0
  48. package/tests/ssh-exec.test.ts +45 -0
  49. package/tests/users.test.ts +13 -0
@@ -16,6 +16,7 @@ import { lsCommand } from "./ls";
16
16
  import { mkdirCommand } from "./mkdir";
17
17
  import { nanoCommand } from "./nano";
18
18
  import { neofetchCommand } from "./neofetch";
19
+ import { passwdCommand } from "./passwd";
19
20
  import { pwdCommand } from "./pwd";
20
21
  import { rmCommand } from "./rm";
21
22
  import { setCommand } from "./set";
@@ -45,6 +46,7 @@ const BASE_COMMANDS = [
45
46
  neofetchCommand,
46
47
  htopCommand,
47
48
  adduserCommand,
49
+ passwdCommand,
48
50
  deluserCommand,
49
51
  sudoCommand,
50
52
  suCommand,
@@ -0,0 +1,3 @@
1
+ import type { ShellModule } from "../types/commands";
2
+ export declare const passwdCommand: ShellModule;
3
+ //# sourceMappingURL=passwd.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"passwd.d.ts","sourceRoot":"","sources":["../../src/commands/passwd.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,eAAO,MAAM,aAAa,EAAE,WAsB3B,CAAC"}
@@ -0,0 +1,21 @@
1
+ export const passwdCommand = {
2
+ name: "passwd",
3
+ params: ["<username> <password>"],
4
+ run: async ({ authUser, args, shell }) => {
5
+ const [username, password] = args;
6
+ if (!username || !password) {
7
+ return {
8
+ stderr: "passwd: usage: passwd <username> <password>",
9
+ exitCode: 1,
10
+ };
11
+ }
12
+ if (authUser !== "root" && authUser !== username) {
13
+ return { stderr: "passwd: permission denied", exitCode: 1 };
14
+ }
15
+ await shell.users.setPassword(username, password);
16
+ return {
17
+ stdout: `passwd: password updated for '${username}'`,
18
+ exitCode: 0,
19
+ };
20
+ },
21
+ };
package/dist/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  import { SshClient } from "./SSHClient";
2
- import { SshMimic } from "./SSHMimic/index";
2
+ import { SftpMimic, SshMimic } from "./SSHMimic/index";
3
3
  import VirtualFileSystem from "./VirtualFileSystem";
4
4
  import { VirtualShell } from "./VirtualShell";
5
5
  import { VirtualUserManager } from "./VirtualUserManager";
6
6
  export type { CommandContext, CommandMode, CommandOutcome, CommandResult, NanoEditorSession, ShellModule, SudoChallenge, } from "./types/commands";
7
7
  export type { ExecStream, ShellStream } from "./types/streams";
8
8
  export type { RemoveOptions, VfsBaseNode, VfsDirectoryNode, VfsFileNode, VfsNodeStats, VfsNodeType, VfsSnapshot, VfsSnapshotBaseNode, VfsSnapshotDirectoryNode, VfsSnapshotFileNode, VfsSnapshotNode, WriteFileOptions, } from "./types/vfs";
9
- export { SshClient, VirtualFileSystem, VirtualShell, SshMimic as VirtualSshServer, VirtualUserManager, };
9
+ export { SshClient, VirtualFileSystem, SftpMimic as VirtualSftpServer, VirtualShell, SshMimic as VirtualSshServer, VirtualUserManager, };
10
10
  export { getArg, getFlag, ifFlag, } from "./commands/command-helpers";
11
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,iBAAiB,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,YAAY,EACX,cAAc,EACd,WAAW,EACX,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,aAAa,GACb,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC/D,YAAY,EACX,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,WAAW,EACX,WAAW,EACX,mBAAmB,EACnB,wBAAwB,EACxB,mBAAmB,EACnB,eAAe,EACf,gBAAgB,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EACN,SAAS,EACT,iBAAiB,EACjB,YAAY,EACZ,QAAQ,IAAI,gBAAgB,EAC5B,kBAAkB,GAClB,CAAC;AAEF,OAAO,EACN,MAAM,EACN,OAAO,EACP,MAAM,GACN,MAAM,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,iBAAiB,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,YAAY,EACX,cAAc,EACd,WAAW,EACX,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,aAAa,GACb,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC/D,YAAY,EACX,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,WAAW,EACX,WAAW,EACX,mBAAmB,EACnB,wBAAwB,EACxB,mBAAmB,EACnB,eAAe,EACf,gBAAgB,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EACN,SAAS,EACT,iBAAiB,EACjB,SAAS,IAAI,iBAAiB,EAC9B,YAAY,EACZ,QAAQ,IAAI,gBAAgB,EAC5B,kBAAkB,GAClB,CAAC;AAEF,OAAO,EACN,MAAM,EACN,OAAO,EACP,MAAM,GACN,MAAM,4BAA4B,CAAC"}
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { SshClient } from "./SSHClient";
2
- import { SshMimic } from "./SSHMimic/index";
2
+ import { SftpMimic, SshMimic } from "./SSHMimic/index";
3
3
  import VirtualFileSystem from "./VirtualFileSystem";
4
4
  import { VirtualShell } from "./VirtualShell";
5
5
  import { VirtualUserManager } from "./VirtualUserManager";
6
- export { SshClient, VirtualFileSystem, VirtualShell, SshMimic as VirtualSshServer, VirtualUserManager, };
6
+ export { SshClient, VirtualFileSystem, SftpMimic as VirtualSftpServer, VirtualShell, SshMimic as VirtualSshServer, VirtualUserManager, };
7
7
  export { getArg, getFlag, ifFlag, } from "./commands/command-helpers";
@@ -1 +1 @@
1
- {"version":3,"file":"neofetch.d.ts","sourceRoot":"","sources":["../../src/modules/neofetch.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAsGvD,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAoKD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CA0E9D"}
1
+ {"version":3,"file":"neofetch.d.ts","sourceRoot":"","sources":["../../src/modules/neofetch.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAsGvD,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAkKD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CA0E9D"}
@@ -193,7 +193,6 @@ function resolveDefaults(info) {
193
193
  if (info.uptimeSeconds === undefined) {
194
194
  info.uptimeSeconds = Math.round(processUptime);
195
195
  }
196
- console.log("Resolving neofetch info with shellProps:", shellProps);
197
196
  return {
198
197
  user: info.user,
199
198
  host: info.host,
@@ -1,4 +1,4 @@
1
- import { VirtualShell, VirtualSshServer } from ".";
1
+ import { VirtualSftpServer, VirtualShell, VirtualSshServer } from ".";
2
2
  const hostname = process.env.SSH_MIMIC_HOSTNAME ?? "typescript-vm";
3
3
  const virtualShell = new VirtualShell(hostname);
4
4
  virtualShell.addCommand("demo", [], () => {
@@ -23,3 +23,12 @@ new VirtualSshServer({
23
23
  console.error("Failed to start SSH Mimic:", error);
24
24
  process.exit(1);
25
25
  });
26
+ new VirtualSftpServer({ port: 2223, hostname, shell: virtualShell })
27
+ .start()
28
+ .then((port) => {
29
+ console.log(`SFTP Mimic initialized. Listening on port ${port}.`);
30
+ })
31
+ .catch((error) => {
32
+ console.error("Failed to start SFTP Mimic:", error);
33
+ process.exit(1);
34
+ });
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
7
- "version": "1.1.2",
7
+ "version": "1.1.4",
8
8
  "license": "MIT",
9
9
  "keywords": [
10
10
  "ssh",
@@ -18,18 +18,24 @@ export function runExec(
18
18
  ): void {
19
19
  Promise.resolve(
20
20
  runCommand(cmd, authUser, hostname, "exec", `/home/${authUser}`, shell),
21
- ).then((result) => {
22
- if (result.stdout) {
23
- stream.write(`${toTtyLines(result.stdout)}\r\n`);
24
- }
21
+ )
22
+ .then((result) => {
23
+ if (result.stdout) {
24
+ stream.write(`${toTtyLines(result.stdout)}\r\n`);
25
+ }
25
26
 
26
- if (result.stderr) {
27
- stream.stderr.write(`${toTtyLines(result.stderr)}\r\n`);
28
- }
27
+ if (result.stderr) {
28
+ stream.stderr.write(`${toTtyLines(result.stderr)}\r\n`);
29
+ }
29
30
 
30
- stream.exit(result.exitCode ?? 0);
31
- console.log(shell.vfs);
32
- void shell.vfs.flushMirror();
33
- stream.end();
34
- });
31
+ stream.exit(result.exitCode ?? 0);
32
+ void shell.vfs.flushMirror();
33
+ stream.end();
34
+ })
35
+ .catch((error) => {
36
+ console.error("Exec error:", error);
37
+ stream.stderr.write(`Error: ${String(error)}\r\n`);
38
+ stream.exit(1);
39
+ stream.end();
40
+ });
35
41
  }
@@ -1,5 +1,6 @@
1
1
  import { Server as SshServer } from "ssh2";
2
2
  import { VirtualShell } from "../VirtualShell";
3
+ import { runExec } from "./exec";
3
4
  import { loadOrCreateHostKey } from "./hostKey";
4
5
 
5
6
  /**
@@ -46,6 +47,9 @@ class SshMimic {
46
47
  const shell = this.shell;
47
48
  const privateKey = loadOrCreateHostKey();
48
49
 
50
+ // Ensure VirtualShell is fully initialized before accepting connections
51
+ await shell.ensureInitialized();
52
+
49
53
  this.server = new SshServer(
50
54
  {
51
55
  hostKeys: [privateKey],
@@ -125,12 +129,16 @@ class SshMimic {
125
129
  });
126
130
 
127
131
  session.on("exec", (acceptExec, _rejectExec, info) => {
128
- const _stream = acceptExec();
129
- shell?.executeCommand(
130
- info.command.trim(),
131
- authUser,
132
- `/home/${authUser}`,
133
- );
132
+ const stream = acceptExec();
133
+ if (stream) {
134
+ runExec(
135
+ stream,
136
+ info.command.trim(),
137
+ authUser,
138
+ shell.hostname,
139
+ shell,
140
+ );
141
+ }
134
142
  });
135
143
  });
136
144
  });
@@ -139,7 +147,7 @@ class SshMimic {
139
147
 
140
148
  return new Promise<number>((resolve, reject) => {
141
149
  this.server?.once("error", (err: unknown) => reject(err));
142
- this.server?.listen(this.port, "127.0.0.1", () => {
150
+ this.server?.listen(this.port, "0.0.0.0", () => {
143
151
  console.log(`SSH Mimic listening on port ${this.port}`);
144
152
  resolve(this.port);
145
153
  });
@@ -158,4 +166,5 @@ class SshMimic {
158
166
  }
159
167
  }
160
168
 
169
+ export { SftpMimic } from "./sftp";
161
170
  export { SshMimic };