start-command 0.10.0 → 0.13.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.
@@ -122,6 +122,58 @@ jobs:
122
122
  - name: Run tests
123
123
  run: bun test
124
124
 
125
+ # Test both execution modes (default and command-stream)
126
+ - name: Test default execution mode
127
+ run: |
128
+ bun run src/bin/cli.js echo "Testing default mode"
129
+ echo "Default mode test passed"
130
+
131
+ - name: Test command-stream execution mode
132
+ run: |
133
+ bun run src/bin/cli.js --use-command-stream echo "Testing command-stream mode"
134
+ echo "Command-stream mode test passed"
135
+
136
+ - name: Test command-stream via env variable
137
+ env:
138
+ START_USE_COMMAND_STREAM: '1'
139
+ run: |
140
+ bun run src/bin/cli.js echo "Testing env var mode"
141
+ echo "Env var mode test passed"
142
+
143
+ # SSH Integration Tests - Linux only (most reliable for SSH testing)
144
+ - name: Setup SSH server for integration tests (Linux)
145
+ if: runner.os == 'Linux'
146
+ run: |
147
+ # Install openssh-server if not present
148
+ sudo apt-get install -y openssh-server
149
+
150
+ # Start SSH service
151
+ sudo systemctl start ssh
152
+
153
+ # Generate SSH key without passphrase for testing
154
+ ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N "" -C "ci-test-key"
155
+
156
+ # Add the public key to authorized_keys for passwordless login
157
+ cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys
158
+ chmod 600 ~/.ssh/authorized_keys
159
+
160
+ # Configure SSH to accept localhost connections without prompts
161
+ mkdir -p ~/.ssh
162
+ cat >> ~/.ssh/config << 'EOF'
163
+ Host localhost
164
+ StrictHostKeyChecking no
165
+ UserKnownHostsFile /dev/null
166
+ LogLevel ERROR
167
+ EOF
168
+ chmod 600 ~/.ssh/config
169
+
170
+ # Test SSH connectivity
171
+ ssh localhost "echo 'SSH connection successful'"
172
+
173
+ - name: Run SSH integration tests (Linux)
174
+ if: runner.os == 'Linux'
175
+ run: bun test test/ssh-integration.test.js
176
+
125
177
  # Release - only runs on main after tests pass (for push events)
126
178
  release:
127
179
  name: Release
package/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # start-command
2
2
 
3
+ ## 0.13.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 7763ae1: Use command-stream library for command execution in CLI
8
+
9
+ This update integrates the command-stream library to handle command execution, replacing direct usage of execSync and spawnSync in the main CLI flow. The change provides a more consistent API for running shell commands and better output handling.
10
+
11
+ Key changes:
12
+ - Added command-stream as a dependency
13
+ - Created a wrapper module for async command execution utilities
14
+ - Refactored printVersion(), runDirect(), and detectRepository() to use command-stream
15
+ - Converted main CLI flow to async for proper integration
16
+
17
+ ## 0.11.0
18
+
19
+ ### Minor Changes
20
+
21
+ - 1240a29: Add SSH isolation support for remote command execution.
22
+ - Implements SSH backend for executing commands on remote servers via SSH, similar to screen/tmux/docker isolation
23
+ - Uses `--endpoint` option to specify SSH target (e.g., `--endpoint user@remote.server`)
24
+ - Supports both attached (interactive) and detached (background) modes
25
+ - Includes comprehensive SSH integration tests in CI with a local SSH server
26
+
3
27
  ## 0.10.0
4
28
 
5
29
  ### Minor Changes
package/README.md CHANGED
@@ -136,7 +136,7 @@ Issue created: https://github.com/owner/some-npm-tool/issues/42
136
136
 
137
137
  ### Process Isolation
138
138
 
139
- Run commands in isolated environments using terminal multiplexers or containers:
139
+ Run commands in isolated environments using terminal multiplexers, containers, or remote servers:
140
140
 
141
141
  ```bash
142
142
  # Run in tmux (attached by default)
@@ -148,6 +148,9 @@ $ --isolated screen --detached -- bun start
148
148
  # Run in docker container
149
149
  $ --isolated docker --image oven/bun:latest -- bun install
150
150
 
151
+ # Run on remote server via SSH
152
+ $ --isolated ssh --endpoint user@remote.server -- npm test
153
+
151
154
  # Short form with custom session name
152
155
  $ -i tmux -s my-session -d bun start
153
156
  ```
@@ -192,21 +195,23 @@ This is useful for:
192
195
 
193
196
  #### Supported Backends
194
197
 
195
- | Backend | Description | Installation |
196
- | -------- | -------------------------------------- | ---------------------------------------------------------- |
197
- | `screen` | GNU Screen terminal multiplexer | `apt install screen` / `brew install screen` |
198
- | `tmux` | Modern terminal multiplexer | `apt install tmux` / `brew install tmux` |
199
- | `docker` | Container isolation (requires --image) | [Docker Installation](https://docs.docker.com/get-docker/) |
198
+ | Backend | Description | Installation |
199
+ | -------- | ---------------------------------------------- | ---------------------------------------------------------- |
200
+ | `screen` | GNU Screen terminal multiplexer | `apt install screen` / `brew install screen` |
201
+ | `tmux` | Modern terminal multiplexer | `apt install tmux` / `brew install tmux` |
202
+ | `docker` | Container isolation (requires --image) | [Docker Installation](https://docs.docker.com/get-docker/) |
203
+ | `ssh` | Remote execution via SSH (requires --endpoint) | `apt install openssh-client` / `brew install openssh` |
200
204
 
201
205
  #### Isolation Options
202
206
 
203
207
  | Option | Description |
204
208
  | -------------------------------- | --------------------------------------------------------- |
205
- | `--isolated, -i` | Isolation backend (screen, tmux, docker) |
209
+ | `--isolated, -i` | Isolation backend (screen, tmux, docker, ssh) |
206
210
  | `--attached, -a` | Run in attached/foreground mode (default) |
207
211
  | `--detached, -d` | Run in detached/background mode |
208
212
  | `--session, -s` | Custom session/container name |
209
213
  | `--image` | Docker image (required for docker isolation) |
214
+ | `--endpoint` | SSH endpoint (required for ssh, e.g., user@host) |
210
215
  | `--isolated-user, -u [name]` | Create isolated user with same permissions (screen/tmux) |
211
216
  | `--keep-user` | Keep isolated user after command completes (don't delete) |
212
217
  | `--keep-alive, -k` | Keep session alive after command completes |
package/bun.lock CHANGED
@@ -4,6 +4,9 @@
4
4
  "workspaces": {
5
5
  "": {
6
6
  "name": "start-command",
7
+ "dependencies": {
8
+ "command-stream": "^0.8.3",
9
+ },
7
10
  "devDependencies": {
8
11
  "@changesets/cli": "^2.29.7",
9
12
  "eslint": "^9.38.0",
@@ -142,6 +145,8 @@
142
145
 
143
146
  "colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="],
144
147
 
148
+ "command-stream": ["command-stream@0.8.3", "", {}, "sha512-vwNf5AWLhD4awaYSIyjHEu7JrAMTu8BaJg1LIpE4HqTXFYtgzSTN/j1VnwHDTNz8sAG7zvZgtKYm9lmi4+0Z7Q=="],
149
+
145
150
  "commander": ["commander@14.0.2", "", {}, "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ=="],
146
151
 
147
152
  "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env bun
2
+ /* global console */
3
+ /**
4
+ * Experiment: Test command-stream with CommonJS require
5
+ */
6
+
7
+ (async () => {
8
+ console.log(
9
+ '=== Testing command-stream with dynamic import in CommonJS ===\n'
10
+ );
11
+
12
+ // Need to use dynamic import since command-stream is ESM
13
+ const { $ } = await import('command-stream');
14
+
15
+ // Test 1: Basic sync command
16
+ console.log('Test 1: Basic sync command');
17
+ const result1 = $`echo "Hello from CJS"`.sync();
18
+ console.log('stdout:', result1.stdout);
19
+ console.log('exit code:', result1.code);
20
+ console.log('');
21
+
22
+ // Test 2: which command
23
+ console.log('Test 2: which command');
24
+ const result2 = $`which echo`.sync();
25
+ console.log('stdout:', result2.stdout.trim());
26
+ console.log('exit code:', result2.code);
27
+ console.log('');
28
+
29
+ console.log('=== All tests completed ===');
30
+ })();
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Experiment: Test command-stream wrapper module
4
+ */
5
+
6
+ const {
7
+ execCommand,
8
+ execCommandAsync,
9
+ commandExists,
10
+ getCommandPath,
11
+ getToolVersion,
12
+ } = require('../src/lib/command-stream');
13
+
14
+ (async () => {
15
+ console.log('=== Testing command-stream wrapper ===\n');
16
+
17
+ // Test 1: Basic sync command
18
+ console.log('Test 1: execCommand (sync-like via promise)');
19
+ const result1 = await execCommand('echo "Hello from wrapper"');
20
+ console.log('stdout:', result1.stdout);
21
+ console.log('code:', result1.code);
22
+ console.log('');
23
+
24
+ // Test 2: Check if command exists
25
+ console.log('Test 2: commandExists');
26
+ const hasScreen = await commandExists('screen');
27
+ const hasFakeCmd = await commandExists('nonexistent-command-xyz');
28
+ console.log('screen exists:', hasScreen);
29
+ console.log('nonexistent-command-xyz exists:', hasFakeCmd);
30
+ console.log('');
31
+
32
+ // Test 3: Get command path
33
+ console.log('Test 3: getCommandPath');
34
+ const echoPath = await getCommandPath('echo');
35
+ console.log('echo path:', echoPath);
36
+ console.log('');
37
+
38
+ // Test 4: Get tool version
39
+ console.log('Test 4: getToolVersion');
40
+ const screenVersion = await getToolVersion('screen', '-v', true);
41
+ console.log('screen version:', screenVersion);
42
+ const tmuxVersion = await getToolVersion('tmux', '-V', true);
43
+ console.log('tmux version:', tmuxVersion);
44
+ console.log('');
45
+
46
+ // Test 5: Async command
47
+ console.log('Test 5: execCommandAsync');
48
+ const result5 = await execCommandAsync('uname -r');
49
+ console.log('stdout:', result5.stdout);
50
+ console.log('code:', result5.code);
51
+ console.log('');
52
+
53
+ console.log('=== All tests completed ===');
54
+ })();
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Experiment: Test command-stream basic usage
4
+ */
5
+
6
+ import { $ } from 'command-stream';
7
+
8
+ console.log('=== Testing command-stream ===\n');
9
+
10
+ // Test 1: Basic async command
11
+ console.log('Test 1: Basic async command');
12
+ const result1 = await $`echo "Hello from command-stream"`;
13
+ console.log('stdout:', result1.stdout);
14
+ console.log('exit code:', result1.code);
15
+ console.log('');
16
+
17
+ // Test 2: Sync command
18
+ console.log('Test 2: Sync command');
19
+ const result2 = $`echo "Sync hello"`.sync();
20
+ console.log('stdout:', result2.stdout);
21
+ console.log('exit code:', result2.code);
22
+ console.log('');
23
+
24
+ // Test 3: Command that uses system tools
25
+ console.log('Test 3: which command');
26
+ try {
27
+ const result3 = $`which echo`.sync();
28
+ console.log('stdout:', result3.stdout);
29
+ console.log('exit code:', result3.code);
30
+ } catch (e) {
31
+ console.log('Error:', e.message);
32
+ }
33
+ console.log('');
34
+
35
+ // Test 4: Get OS version on Linux
36
+ console.log('Test 4: uname command');
37
+ const result4 = $`uname -r`.sync();
38
+ console.log('stdout:', result4.stdout.trim());
39
+ console.log('exit code:', result4.code);
40
+ console.log('');
41
+
42
+ // Test 5: Silent mode (no mirror)
43
+ console.log('Test 5: Silent mode with $({ mirror: false })');
44
+ const $silent = $({ mirror: false, capture: true });
45
+ const result5 = await $silent`echo "This should be silent"`;
46
+ console.log('stdout:', result5.stdout);
47
+ console.log('');
48
+
49
+ // Test 6: Check if command exists
50
+ console.log('Test 6: Check if screen exists');
51
+ const result6 = $`which screen`.sync();
52
+ console.log('screen exists:', result6.code === 0);
53
+ console.log('screen path:', result6.stdout.trim());
54
+ console.log('');
55
+
56
+ console.log('=== All tests completed ===');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "start-command",
3
- "version": "0.10.0",
3
+ "version": "0.13.0",
4
4
  "description": "Gamification of coding, execute any command with ability to auto-report issues on GitHub",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -59,5 +59,8 @@
59
59
  "prettier --write",
60
60
  "prettier --check"
61
61
  ]
62
+ },
63
+ "dependencies": {
64
+ "command-stream": "^0.8.3"
62
65
  }
63
66
  }