@team-work/sandbox-client 0.1.2-beta.0 → 0.2.0-beta.0

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 CHANGED
@@ -8,6 +8,9 @@ team-work 平台的 sandbox CLI 客户端。全局命令 `tw`,在用户机器
8
8
  npm i -g @team-work/sandbox-client
9
9
  ```
10
10
 
11
+ 支持 macOS / Linux / Windows 的 x64 和 arm64。PTY 使用 `@lydell/node-pty` 的平台预编译二进制,
12
+ 安装时请保留 npm 的 optional dependencies(默认行为;不要加 `--omit=optional`)。
13
+
11
14
  ## 快速开始
12
15
 
13
16
  ```bash
@@ -34,18 +34,19 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.PtySession = void 0;
37
- const pty = __importStar(require("node-pty"));
37
+ const node_os_1 = require("node:os");
38
+ const pty = __importStar(require("@lydell/node-pty"));
38
39
  class PtySession {
39
40
  term;
40
41
  logger;
41
42
  constructor(sessionId, cols, rows, cb, logger) {
42
43
  this.logger = logger.child({ sessionId });
43
- const shell = process.env.SHELL || (process.platform === 'win32' ? 'powershell.exe' : 'bash');
44
+ const shell = getDefaultShell();
44
45
  this.term = pty.spawn(shell, [], {
45
46
  name: 'xterm-256color',
46
47
  cols: Math.max(1, cols),
47
48
  rows: Math.max(1, rows),
48
- cwd: process.env.HOME || process.cwd(),
49
+ cwd: process.env.HOME || process.env.USERPROFILE || (0, node_os_1.homedir)(),
49
50
  env: process.env,
50
51
  });
51
52
  this.term.onData((data) => cb.onData(data));
@@ -73,4 +74,10 @@ class PtySession {
73
74
  }
74
75
  }
75
76
  exports.PtySession = PtySession;
77
+ function getDefaultShell() {
78
+ if (process.platform === 'win32') {
79
+ return process.env.ComSpec || 'powershell.exe';
80
+ }
81
+ return process.env.SHELL || (process.platform === 'darwin' ? '/bin/zsh' : '/bin/bash');
82
+ }
76
83
  //# sourceMappingURL=pty-session.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pty-session.js","sourceRoot":"","sources":["../../../src/handlers/terminal/pty-session.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,8CAAgC;AAchC,MAAa,UAAU;IACb,IAAI,CAAW;IACf,MAAM,CAAS;IAEvB,YACE,SAAiB,EACjB,IAAY,EACZ,IAAY,EACZ,EAAgB,EAChB,MAAc;QAEd,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;QAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QAC9F,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE;YAC/B,IAAI,EAAE,gBAAgB;YACtB,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC;YACvB,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC;YACvB,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE;YACtC,GAAG,EAAE,OAAO,CAAC,GAA6B;SAC3C,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QACxD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,aAAa,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,IAAY;QAChB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAED,MAAM,CAAC,IAAY,EAAE,IAAY;QAC/B,IAAI,CAAC;YACH,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;QACzD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,mBAAmB,CAAC,CAAC;QACnG,CAAC;IACH,CAAC;IAED,IAAI;QACF,IAAI,CAAC;YACH,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACnB,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;IACH,CAAC;CACF;AA5CD,gCA4CC"}
1
+ {"version":3,"file":"pty-session.js","sourceRoot":"","sources":["../../../src/handlers/terminal/pty-session.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,qCAAkC;AAElC,sDAAwC;AAcxC,MAAa,UAAU;IACb,IAAI,CAAW;IACf,MAAM,CAAS;IAEvB,YACE,SAAiB,EACjB,IAAY,EACZ,IAAY,EACZ,EAAgB,EAChB,MAAc;QAEd,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;QAC1C,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;QAChC,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE;YAC/B,IAAI,EAAE,gBAAgB;YACtB,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC;YACvB,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC;YACvB,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,IAAA,iBAAO,GAAE;YAC7D,GAAG,EAAE,OAAO,CAAC,GAA6B;SAC3C,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QACxD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,aAAa,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,IAAY;QAChB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAED,MAAM,CAAC,IAAY,EAAE,IAAY;QAC/B,IAAI,CAAC;YACH,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;QACzD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,mBAAmB,CAAC,CAAC;QACnG,CAAC;IACH,CAAC;IAED,IAAI;QACF,IAAI,CAAC;YACH,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACnB,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;IACH,CAAC;CACF;AA5CD,gCA4CC;AAED,SAAS,eAAe;IACtB,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,OAAO,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,gBAAgB,CAAC;IACjD,CAAC;IACD,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;AACzF,CAAC"}
@@ -10,8 +10,14 @@ const info_js_1 = require("../utils/info.js");
10
10
  function selfUpdate() {
11
11
  const { name } = (0, info_js_1.getPkgInfo)();
12
12
  const current = (0, info_js_1.getPkgInfo)().version;
13
+ // Windows 下 npm 是 npm.cmd。spawnSync 需要走 shell 才能从 PATH 解析它。
14
+ const npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm';
15
+ const npmSpawnOptions = { shell: process.platform === 'win32' };
13
16
  // npm view <name> version(取最新发布版本)
14
- const view = (0, node_child_process_1.spawnSync)('npm', ['view', name, 'version'], { encoding: 'utf8' });
17
+ const view = (0, node_child_process_1.spawnSync)(npmCommand, ['view', name, 'version'], {
18
+ encoding: 'utf8',
19
+ ...npmSpawnOptions,
20
+ });
15
21
  if (view.status !== 0) {
16
22
  return {
17
23
  changed: false,
@@ -26,9 +32,10 @@ function selfUpdate() {
26
32
  return { changed: false, message: `已是最新版本 ${current}` };
27
33
  }
28
34
  // npm i -g <name>@latest
29
- const install = (0, node_child_process_1.spawnSync)('npm', ['i', '-g', `${name}@latest`], {
35
+ const install = (0, node_child_process_1.spawnSync)(npmCommand, ['i', '-g', `${name}@latest`], {
30
36
  encoding: 'utf8',
31
37
  stdio: 'inherit',
38
+ ...npmSpawnOptions,
32
39
  });
33
40
  if (install.status !== 0) {
34
41
  return { changed: false, message: `更新失败(npm 退出码 ${install.status})` };
@@ -1 +1 @@
1
- {"version":3,"file":"self-update.js","sourceRoot":"","sources":["../../src/update/self-update.ts"],"names":[],"mappings":";;AAQA,gCAiCC;AAzCD,2DAA+C;AAE/C,8CAA8C;AAE9C;;;GAGG;AACH,SAAgB,UAAU;IACxB,MAAM,EAAE,IAAI,EAAE,GAAG,IAAA,oBAAU,GAAE,CAAC;IAC9B,MAAM,OAAO,GAAG,IAAA,oBAAU,GAAE,CAAC,OAAO,CAAC;IAErC,mCAAmC;IACnC,MAAM,IAAI,GAAG,IAAA,8BAAS,EAAC,KAAK,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/E,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO;YACL,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,aAAa,EAAE;SAClF,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAClC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;IAClD,CAAC;IAED,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;QACvB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,OAAO,EAAE,EAAE,CAAC;IAC1D,CAAC;IAED,yBAAyB;IACzB,MAAM,OAAO,GAAG,IAAA,8BAAS,EAAC,KAAK,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,IAAI,SAAS,CAAC,EAAE;QAC9D,QAAQ,EAAE,MAAM;QAChB,KAAK,EAAE,SAAS;KACjB,CAAC,CAAC;IACH,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,gBAAgB,OAAO,CAAC,MAAM,GAAG,EAAE,CAAC;IACxE,CAAC;IACD,OAAO;QACL,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,OAAO,OAAO,MAAM,MAAM,qBAAqB;KACzD,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"self-update.js","sourceRoot":"","sources":["../../src/update/self-update.ts"],"names":[],"mappings":";;AAQA,gCAwCC;AAhDD,2DAA+C;AAE/C,8CAA8C;AAE9C;;;GAGG;AACH,SAAgB,UAAU;IACxB,MAAM,EAAE,IAAI,EAAE,GAAG,IAAA,oBAAU,GAAE,CAAC;IAC9B,MAAM,OAAO,GAAG,IAAA,oBAAU,GAAE,CAAC,OAAO,CAAC;IACrC,4DAA4D;IAC5D,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC;IACpE,MAAM,eAAe,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;IAEhE,mCAAmC;IACnC,MAAM,IAAI,GAAG,IAAA,8BAAS,EAAC,UAAU,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,EAAE;QAC5D,QAAQ,EAAE,MAAM;QAChB,GAAG,eAAe;KACnB,CAAC,CAAC;IACH,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO;YACL,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,aAAa,EAAE;SAClF,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAClC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;IAClD,CAAC;IAED,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;QACvB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,OAAO,EAAE,EAAE,CAAC;IAC1D,CAAC;IAED,yBAAyB;IACzB,MAAM,OAAO,GAAG,IAAA,8BAAS,EAAC,UAAU,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,IAAI,SAAS,CAAC,EAAE;QACnE,QAAQ,EAAE,MAAM;QAChB,KAAK,EAAE,SAAS;QAChB,GAAG,eAAe;KACnB,CAAC,CAAC;IACH,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,gBAAgB,OAAO,CAAC,MAAM,GAAG,EAAE,CAAC;IACxE,CAAC;IACD,OAAO;QACL,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,OAAO,OAAO,MAAM,MAAM,qBAAqB;KACzD,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@team-work/sandbox-client",
3
- "version": "0.1.2-beta.0",
3
+ "version": "0.2.0-beta.0",
4
4
  "description": "team-work sandbox CLI client — connect to sandbox WS server and accept remote shell / pty / file operations",
5
5
  "bin": {
6
6
  "tw": "dist/cli/index.js"
@@ -31,8 +31,8 @@
31
31
  ],
32
32
  "license": "MIT",
33
33
  "dependencies": {
34
+ "@lydell/node-pty": "1.2.0-beta.15",
34
35
  "commander": "^12.1.0",
35
- "node-pty": "^1.0.0",
36
36
  "pino": "^9.5.0",
37
37
  "ws": "^8.18.0"
38
38
  },
@@ -40,5 +40,9 @@
40
40
  "@types/node": "^20.14.0",
41
41
  "@types/ws": "^8.5.12",
42
42
  "typescript": "^5.5.4"
43
+ },
44
+ "publishConfig": {
45
+ "registry": "https://registry.npmjs.org/",
46
+ "access": "public"
43
47
  }
44
48
  }
@@ -1,30 +1,50 @@
1
- // node-pty 预编译二进制(prebuilds/<arch>/spawn-helper)经 npm 解包后常丢失可执行位,
1
+ // node-pty 预编译二进制(prebuilds/<platform>-<arch>/spawn-helper)经 npm 解包后常丢失可执行位,
2
2
  // 导致 pty.spawn 同步抛 `posix_spawnp failed.`(EACCES),CLI 守护进程一开终端就崩。
3
3
  // postinstall 时补回 +x,保证各平台 prebuild 都可执行。
4
4
  const { chmodSync, existsSync, readdirSync, statSync } = require('node:fs');
5
5
  const { join } = require('node:path');
6
6
 
7
- const prebuildDir = join(__dirname, '..', 'node_modules', 'node-pty', 'prebuilds');
8
- if (!existsSync(prebuildDir)) {
9
- // 无预编译包(从源码编译的场景)——跳过
10
- process.exit(0);
7
+ // npm 可能把依赖提升到全局/上层 node_modules,不能只看当前包自己的 node_modules。
8
+ let scopeDir;
9
+ for (const parent of require.resolve.paths('@lydell/node-pty') || []) {
10
+ const candidate = join(parent, '@lydell');
11
+ if (existsSync(candidate)) {
12
+ scopeDir = candidate;
13
+ break;
14
+ }
11
15
  }
16
+ if (!scopeDir) process.exit(0);
12
17
 
13
18
  let touched = 0;
14
- for (const arch of readdirSync(prebuildDir)) {
15
- const dir = join(prebuildDir, arch);
16
- if (!statSync(dir).isDirectory()) continue;
17
- for (const bin of readdirSync(dir)) {
18
- // spawn-helper 是 posix_spawn 拉起的可执行;pty.node 是 .node 动态库(也顺带补位,无害)
19
- if (bin === 'spawn-helper' || bin.endsWith('.node')) {
20
- const p = join(dir, bin);
21
- try {
22
- chmodSync(p, 0o755);
23
- touched++;
24
- } catch (err) {
25
- console.warn(`[fix-pty-perms] chmod failed: ${p} (${err.message})`);
19
+ let foundPlatformPackage = false;
20
+ const platformPackage = `node-pty-${process.platform}-${process.arch}`;
21
+ for (const pkg of readdirSync(scopeDir)) {
22
+ if (!pkg.startsWith('node-pty-')) continue;
23
+ if (pkg === platformPackage) foundPlatformPackage = true;
24
+ const prebuildDir = join(scopeDir, pkg, 'prebuilds');
25
+ if (!existsSync(prebuildDir)) continue;
26
+
27
+ for (const platformArch of readdirSync(prebuildDir)) {
28
+ const dir = join(prebuildDir, platformArch);
29
+ if (!statSync(dir).isDirectory()) continue;
30
+ for (const bin of readdirSync(dir)) {
31
+ // spawn-helper 是 posix_spawn 拉起的可执行;pty.node 是 .node 动态库(也顺带补位,无害)
32
+ if (bin === 'spawn-helper' || bin.endsWith('.node')) {
33
+ const p = join(dir, bin);
34
+ try {
35
+ chmodSync(p, 0o755);
36
+ touched++;
37
+ } catch (err) {
38
+ console.warn(`[fix-pty-perms] chmod failed: ${p} (${err.message})`);
39
+ }
26
40
  }
27
41
  }
28
42
  }
29
43
  }
30
- console.log(`[fix-pty-perms] ensured executable bit on ${touched} file(s) under node-pty/prebuilds`);
44
+
45
+ if (!foundPlatformPackage) {
46
+ console.error(`[fix-pty-perms] missing @lydell/node-pty-${platformPackage}. Do not install with --omit=optional.`);
47
+ process.exit(1);
48
+ }
49
+
50
+ console.log(`[fix-pty-perms] ensured executable bit on ${touched} file(s) under @lydell/node-pty-*`);