@push.rocks/smartshell 3.2.3 → 3.2.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.
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@push.rocks/smartshell',
6
- version: '3.2.3',
6
+ version: '3.2.4',
7
7
  description: 'A library for executing shell commands using promises.'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx3QkFBd0I7SUFDOUIsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLHdEQUF3RDtDQUN0RSxDQUFBIn0=
@@ -3,7 +3,7 @@
3
3
  * making sure the process doesn't run out of memory
4
4
  */
5
5
  export declare class ShellLog {
6
- logStore: Buffer;
6
+ logStore: Buffer<ArrayBuffer>;
7
7
  /**
8
8
  * log data to console
9
9
  * @param dataArg
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@push.rocks/smartshell",
3
3
  "private": false,
4
- "version": "3.2.3",
4
+ "version": "3.2.4",
5
5
  "description": "A library for executing shell commands using promises.",
6
6
  "main": "dist_ts/index.js",
7
7
  "typings": "dist_ts/index.d.ts",
@@ -28,16 +28,15 @@
28
28
  },
29
29
  "homepage": "https://code.foss.global/push.rocks/smartshell",
30
30
  "devDependencies": {
31
- "@git.zone/tsbuild": "^2.2.0",
31
+ "@git.zone/tsbuild": "^2.6.4",
32
32
  "@git.zone/tsrun": "^1.3.3",
33
- "@git.zone/tstest": "^1.0.90",
34
- "@push.rocks/tapbundle": "^5.5.3",
33
+ "@git.zone/tstest": "^2.3.2",
35
34
  "@types/node": "^22.10.2"
36
35
  },
37
36
  "dependencies": {
38
37
  "@push.rocks/smartdelay": "^3.0.1",
39
38
  "@push.rocks/smartexit": "^1.0.23",
40
- "@push.rocks/smartpromise": "^4.0.4",
39
+ "@push.rocks/smartpromise": "^4.2.3",
41
40
  "@types/which": "^3.0.4",
42
41
  "tree-kill": "^1.2.2",
43
42
  "which": "^5.0.0"
@@ -58,7 +57,7 @@
58
57
  "last 1 chrome versions"
59
58
  ],
60
59
  "scripts": {
61
- "test": "(tstest test/)",
60
+ "test": "(tstest test/ --verbose --logfile --timeout 20)",
62
61
  "build": "(tsbuild tsfolders --web)",
63
62
  "buildDocs": "tsdoc"
64
63
  }
package/readme.md CHANGED
@@ -1,136 +1,799 @@
1
- # @push.rocks/smartshell
2
- shell actions designed as promises
1
+ # @push.rocks/smartshell 🐚
2
+ **Execute shell commands with superpowers in Node.js**
3
3
 
4
- ## Install
4
+ [![npm version](https://img.shields.io/npm/v/@push.rocks/smartshell.svg)](https://www.npmjs.com/package/@push.rocks/smartshell)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
6
 
6
- To install `@push.rocks/smartshell`, use npm:
7
+ ## Why smartshell? 🚀
7
8
 
8
- ```sh
9
+ Tired of wrestling with Node.js child processes? Meet `@push.rocks/smartshell` - your promise-based shell command companion that makes executing system commands feel like a breeze. Whether you're building automation scripts, CI/CD pipelines, or need fine-grained control over shell execution, smartshell has got you covered.
10
+
11
+ ### ✨ Key Features
12
+
13
+ - 🎯 **Promise-based API** - Async/await ready for modern codebases
14
+ - 🔇 **Silent execution modes** - Control output verbosity
15
+ - 📡 **Streaming support** - Real-time output for long-running processes
16
+ - 🎮 **Interactive commands** - Handle user input when needed
17
+ - ⚡ **Smart execution modes** - Strict, silent, or streaming
18
+ - 🔍 **Pattern matching** - Wait for specific output patterns
19
+ - 🌍 **Environment management** - Custom env vars and PATH handling
20
+ - 🛡️ **TypeScript first** - Full type safety and IntelliSense
21
+
22
+ ## Installation 📦
23
+
24
+ ```bash
25
+ # Using npm
9
26
  npm install @push.rocks/smartshell --save
27
+
28
+ # Using yarn
29
+ yarn add @push.rocks/smartshell
30
+
31
+ # Using pnpm (recommended)
32
+ pnpm add @push.rocks/smartshell
10
33
  ```
11
34
 
12
- Or if you prefer using Yarn:
35
+ ## Quick Start 🏃‍♂️
13
36
 
14
- ```sh
15
- yarn add @push.rocks/smartshell
37
+ ```typescript
38
+ import { Smartshell } from '@push.rocks/smartshell';
39
+
40
+ // Create your shell instance
41
+ const shell = new Smartshell({
42
+ executor: 'bash' // or 'sh' for lighter shells
43
+ });
44
+
45
+ // Run a simple command
46
+ const result = await shell.exec('echo "Hello, World!"');
47
+ console.log(result.stdout); // "Hello, World!"
16
48
  ```
17
49
 
18
- Ensure that you have TypeScript and the related dependencies installed as well since `@push.rocks/smartshell` is designed to work with TypeScript.
50
+ ## Core Concepts 💡
19
51
 
20
- ## Usage
52
+ ### The Smartshell Instance
21
53
 
22
- The `@push.rocks/smartshell` package simplifies running shell commands within Node.js applications by wrapping these commands within promises. This approach enhances the readability and maintainability of code that relies on shell execution, making it particularly useful in automation scripts, build processes, and any scenario where interaction with the system shell is required.
54
+ The heart of smartshell is the `Smartshell` class. Each instance maintains its own environment and configuration:
23
55
 
24
- ### Getting Started with `@push.rocks/smartshell`
56
+ ```typescript
57
+ const shell = new Smartshell({
58
+ executor: 'bash', // Choose your shell: 'bash' or 'sh'
59
+ sourceFilePaths: ['/path/to/env.sh'], // Optional: source files on init
60
+ });
61
+ ```
25
62
 
26
- First, ensure that you import `Smartshell` from `@push.rocks/smartshell` using ESM syntax in your TypeScript file:
63
+ ## Execution Modes 🎛️
64
+
65
+ ### Standard Execution
66
+
67
+ Perfect for general commands where you want to see the output:
27
68
 
28
69
  ```typescript
29
- import { Smartshell } from '@push.rocks/smartshell';
70
+ const result = await shell.exec('ls -la');
71
+ console.log(result.stdout); // Directory listing
72
+ console.log(result.exitCode); // 0 for success
30
73
  ```
31
74
 
32
- ### Creating a Smartshell Instance
75
+ ### Silent Execution
33
76
 
34
- Before executing any shell command, you need to create an instance of `Smartshell`. The constructor accepts configuration options such as the shell executor (`bash` or `sh`), and optionally, paths to source files and directories to include in the shell’s environment.
77
+ Run commands without printing to console - ideal for capturing output:
35
78
 
36
79
  ```typescript
37
- const smartShellInstance = new Smartshell({
38
- executor: 'bash', // or 'sh'
80
+ const result = await shell.execSilent('cat /etc/hostname');
81
+ // Output is NOT printed to console but IS captured in result
82
+ console.log(result.stdout); // Access the captured output here
83
+ console.log(result.exitCode); // Check exit code (0 = success)
84
+
85
+ // Example: Process output programmatically
86
+ const files = await shell.execSilent('ls -la');
87
+ const fileList = files.stdout.split('
88
+ ');
89
+ fileList.forEach(file => {
90
+ // Process each file entry
39
91
  });
40
92
  ```
41
93
 
42
- ### Executing Commands
94
+ **Key Point:** Silent methods (`execSilent`, `execStrictSilent`, `execStreamingSilent`) suppress console output but still capture everything in the result object for programmatic access.
43
95
 
44
- #### Basic Execution
96
+ ### Strict Execution
45
97
 
46
- To execute a shell command, use the `exec` method. This method returns a promise that resolves with an execution result object containing `exitCode` and `stdout`.
98
+ Throws an error if the command fails - great for critical operations:
47
99
 
48
100
  ```typescript
49
- (async () => {
50
- const result = await smartShellInstance.exec('echo "Hello, SmartShell"');
51
- console.log(result.stdout); // Outputs: Hello, SmartShell
52
- })();
101
+ try {
102
+ await shell.execStrict('critical-command');
103
+ console.log('✅ Command succeeded!');
104
+ } catch (error) {
105
+ console.error('❌ Command failed:', error);
106
+ }
53
107
  ```
54
108
 
55
- #### Silent Execution
109
+ ### Streaming Execution
56
110
 
57
- If you prefer not to display the output in the console, use `execSilent`:
111
+ For long-running processes or when you need real-time output:
58
112
 
59
113
  ```typescript
60
- (async () => {
61
- const result = await smartShellInstance.execSilent('ls');
62
- console.log(result.stdout); // Outputs the list of files and directories
63
- })();
114
+ const streaming = await shell.execStreaming('npm install');
115
+
116
+ // Access the child process directly
117
+ streaming.childProcess.stdout.on('data', (chunk) => {
118
+ console.log('📦 Installing:', chunk.toString());
119
+ });
120
+
121
+ // Wait for completion
122
+ await streaming.finalPromise;
64
123
  ```
65
124
 
66
- #### Strict Execution
125
+ ### Interactive Execution
67
126
 
68
- For scenarios where an execution error should immediately throw an exception, use `execStrict`:
127
+ When commands need user input:
69
128
 
70
129
  ```typescript
71
- (async () => {
72
- try {
73
- const result = await smartShellInstance.execStrict('exit 1');
74
- } catch (error) {
75
- console.error('Command execution failed');
76
- }
77
- })();
130
+ // This will connect to your terminal for input
131
+ await shell.execInteractive('npm init');
132
+ ```
133
+
134
+ ## Advanced Features 🔥
135
+
136
+ ### Wait for Specific Output
137
+
138
+ Perfect for waiting on services to start:
139
+
140
+ ```typescript
141
+ // Wait for a specific line before continuing
142
+ await shell.execAndWaitForLine(
143
+ 'npm run dev',
144
+ /Server started on port 3000/
145
+ );
146
+ console.log('🚀 Server is ready!');
147
+ ```
148
+
149
+ ### Silent Pattern Waiting
150
+
151
+ Same as above, but without console output:
152
+
153
+ ```typescript
154
+ await shell.execAndWaitForLineSilent(
155
+ 'docker-compose up',
156
+ /database system is ready to accept connections/
157
+ );
158
+ // The command output is suppressed from console but the pattern matching still works
159
+ ```
160
+
161
+ ### Environment Customization
162
+
163
+ Smartshell provides powerful environment management:
164
+
165
+ ```typescript
166
+ // Add custom source files
167
+ shell.shellEnv.addSourceFiles([
168
+ '/home/user/.custom_env',
169
+ './project.env.sh'
170
+ ]);
171
+
172
+ // Modify PATH
173
+ shell.shellEnv.pathDirArray.push('/custom/bin');
174
+ shell.shellEnv.pathDirArray.push('/usr/local/special');
175
+
176
+ // Your custom environment is ready
177
+ const result = await shell.exec('my-custom-command');
78
178
  ```
79
179
 
80
- #### Streaming Output
180
+ ### Smart Execution Utility
181
+
182
+ The `SmartExecution` class enables restartable streaming processes:
183
+
184
+ ```typescript
185
+ import { SmartExecution } from '@push.rocks/smartshell';
186
+
187
+ const execution = new SmartExecution(shell, 'npm run watch');
188
+
189
+ // Restart the process whenever needed
190
+ await execution.restart();
191
+
192
+ // Access the current streaming execution
193
+ if (execution.currentStreamingExecution) {
194
+ execution.currentStreamingExecution.childProcess.stdout.on('data', (data) => {
195
+ console.log(data.toString());
196
+ });
197
+ }
198
+ ```
199
+
200
+ ### Shell Detection
201
+
202
+ Need to check if a command exists? We export the `which` utility:
203
+
204
+ ```typescript
205
+ import { which } from '@push.rocks/smartshell';
206
+
207
+ try {
208
+ const gitPath = await which('git');
209
+ console.log(`Git found at: ${gitPath}`);
210
+ } catch (error) {
211
+ console.log('Git is not installed');
212
+ }
213
+ ```
214
+
215
+ ## Real-World Examples 🌍
216
+
217
+ ### Build Pipeline
218
+
219
+ ```typescript
220
+ const shell = new Smartshell({ executor: 'bash' });
221
+
222
+ // Clean build directory
223
+ await shell.execSilent('rm -rf dist');
224
+
225
+ // Run TypeScript compiler
226
+ const buildResult = await shell.execStrict('tsc');
227
+
228
+ // Run tests
229
+ await shell.execStrict('npm test');
230
+
231
+ // Build succeeded!
232
+ console.log('✅ Build pipeline completed successfully');
233
+ ```
81
234
 
82
- Some commands benefit from streaming output as they execute, especially long-running tasks. For these cases, use `execStreaming`:
235
+ ### Development Server with Auto-Restart
83
236
 
84
237
  ```typescript
85
- (async () => {
86
- const execStreamingResult = await smartShellInstance.execStreaming('tail -f /var/log/system.log');
238
+ const shell = new Smartshell({ executor: 'bash' });
239
+ const devServer = new SmartExecution(shell, 'npm run dev');
240
+
241
+ // Watch for file changes and restart
242
+ fs.watch('./src', async () => {
243
+ console.log('🔄 Changes detected, restarting...');
244
+ await devServer.restart();
245
+ });
246
+ ```
247
+
248
+ ### Docker Compose Helper
249
+
250
+ ```typescript
251
+ const shell = new Smartshell({ executor: 'bash' });
252
+
253
+ // Start services and wait for readiness
254
+ console.log('🐳 Starting Docker services...');
255
+ await shell.execAndWaitForLine(
256
+ 'docker-compose up',
257
+ /All services are ready/,
258
+ { timeout: 60000 }
259
+ );
260
+
261
+ // Run migrations
262
+ await shell.execStrict('docker-compose exec app npm run migrate');
263
+ console.log('✅ Environment ready!');
264
+ ```
265
+
266
+ ### CI/CD Integration
267
+
268
+ ```typescript
269
+ const shell = new Smartshell({ executor: 'bash' });
270
+
271
+ async function runCIPipeline() {
272
+ // Install dependencies
273
+ await shell.execStrict('pnpm install --frozen-lockfile');
274
+
275
+ // Run linting
276
+ const lintResult = await shell.execSilent('npm run lint');
277
+ if (lintResult.exitCode !== 0) {
278
+ throw new Error(`Linting failed:
279
+ ${lintResult.stdout}`);
280
+ }
281
+
282
+ // Run tests with coverage
283
+ const testResult = await shell.exec('npm run test:coverage');
87
284
 
88
- execStreamingResult.childProcess.stdout.on('data', (data) => {
285
+ // Build project
286
+ await shell.execStrict('npm run build');
287
+
288
+ // Deploy if on main branch
289
+ if (process.env.BRANCH === 'main') {
290
+ await shell.execStrict('npm run deploy');
291
+ }
292
+ }
293
+ ```
294
+
295
+ ## API Reference 📚
296
+
297
+ ### Smartshell Class
298
+
299
+ | Method | Description | Returns |
300
+ |--------|-------------|---------|
301
+ | `exec(command)` | Execute command with output | `Promise<IExecResult>` |
302
+ | `execSilent(command)` | Execute without console output | `Promise<IExecResult>` |
303
+ | `execStrict(command)` | Execute, throw on failure | `Promise<IExecResult>` |
304
+ | `execStrictSilent(command)` | Strict + silent execution | `Promise<IExecResult>` |
305
+ | `execStreaming(command)` | Stream output in real-time | `Promise<IExecResultStreaming>` |
306
+ | `execStreamingSilent(command)` | Stream without console output | `Promise<IExecResultStreaming>` |
307
+ | `execInteractive(command)` | Interactive terminal mode | `Promise<void>` |
308
+ | `execAndWaitForLine(command, regex)` | Wait for pattern match | `Promise<void>` |
309
+ | `execAndWaitForLineSilent(command, regex)` | Silent pattern waiting | `Promise<void>` |
310
+
311
+ ### Result Interfaces
312
+
313
+ ```typescript
314
+ interface IExecResult {
315
+ exitCode: number; // Process exit code
316
+ stdout: string; // Standard output
317
+ }
318
+
319
+ interface IExecResultStreaming {
320
+ childProcess: ChildProcess; // Node.js ChildProcess instance
321
+ finalPromise: Promise<void>; // Resolves when process exits
322
+ }
323
+ ```
324
+
325
+ ## Understanding Silent Modes 🤫
326
+
327
+ Silent execution modes are perfect when you need to capture command output for processing without cluttering the console. Here's what you need to know:
328
+
329
+ ### How Silent Modes Work
330
+
331
+ 1. **Output is captured, not lost**: All stdout content is stored in the result object
332
+ 2. **Console stays clean**: Nothing is printed during execution
333
+ 3. **Full programmatic access**: Process the output however you need
334
+
335
+ ### Available Silent Methods
336
+
337
+ ```typescript
338
+ // Basic silent execution
339
+ const result = await shell.execSilent('ls -la');
340
+ console.log(result.stdout); // Access captured output
341
+ console.log(result.exitCode); // Check success/failure
342
+
343
+ // Strict + Silent (throws on error)
344
+ try {
345
+ const result = await shell.execStrictSilent('important-command');
346
+ const output = result.stdout; // Process the output
347
+ } catch (error) {
348
+ // Handle failure
349
+ }
350
+
351
+ // Streaming + Silent
352
+ const streaming = await shell.execStreamingSilent('long-running-process');
353
+ streaming.childProcess.stdout.on('data', (chunk) => {
354
+ // Process chunks as they arrive
355
+ const data = chunk.toString();
356
+ });
357
+
358
+ // Pattern matching + Silent
359
+ await shell.execAndWaitForLineSilent('server-start', /Ready on port/);
360
+ ```
361
+
362
+ ### Common Use Cases for Silent Execution
363
+
364
+ ```typescript
365
+ // Parse JSON output
366
+ const jsonResult = await shell.execSilent('aws s3 ls --output json');
367
+ const buckets = JSON.parse(jsonResult.stdout);
368
+
369
+ // Count lines
370
+ const wcResult = await shell.execSilent('wc -l huge-file.txt');
371
+ const lineCount = parseInt(wcResult.stdout.split(' ')[0]);
372
+
373
+ // Check if command exists
374
+ const whichResult = await shell.execSilent('which docker');
375
+ const dockerPath = whichResult.exitCode === 0 ? whichResult.stdout.trim() : null;
376
+
377
+ // Collect system info
378
+ const unameResult = await shell.execSilent('uname -a');
379
+ const systemInfo = unameResult.stdout.trim();
380
+ ```
381
+
382
+ ## Tips & Best Practices 💎
383
+
384
+ 1. **Choose the right executor**: Use `bash` for full features, `sh` for minimal overhead
385
+ 2. **Use strict mode for critical operations**: Ensures failures don't go unnoticed
386
+ 3. **Stream long-running processes**: Better UX and memory efficiency
387
+ 4. **Leverage silent modes**: When you only need to capture output
388
+ 5. **Handle errors gracefully**: Always wrap strict executions in try-catch
389
+ 6. **Clean up resources**: Streaming processes should be properly terminated
390
+
391
+ ## License and Legal Information
392
+
393
+ This repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository.
394
+
395
+ **Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
396
+
397
+ ### Trademarks
398
+
399
+ This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.
400
+
401
+ ### Company Information
402
+
403
+ Task Venture Capital GmbH
404
+ Registered at District court Bremen HRB 35230 HB, Germany
405
+
406
+ For any legal inquiries or if you require further information, please contact us via email at hello@task.vc.
407
+
408
+ By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.# @push.rocks/smartshell 🐚
409
+ **Execute shell commands with superpowers in Node.js**
410
+
411
+ [![npm version](https://img.shields.io/npm/v/@push.rocks/smartshell.svg)](https://www.npmjs.com/package/@push.rocks/smartshell)
412
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
413
+
414
+ ## Why smartshell? 🚀
415
+
416
+ Tired of wrestling with Node.js child processes? Meet `@push.rocks/smartshell` - your promise-based shell command companion that makes executing system commands feel like a breeze. Whether you're building automation scripts, CI/CD pipelines, or need fine-grained control over shell execution, smartshell has got you covered.
417
+
418
+ ### ✨ Key Features
419
+
420
+ - 🎯 **Promise-based API** - Async/await ready for modern codebases
421
+ - 🔇 **Silent execution modes** - Control output verbosity
422
+ - 📡 **Streaming support** - Real-time output for long-running processes
423
+ - 🎮 **Interactive commands** - Handle user input when needed
424
+ - ⚡ **Smart execution modes** - Strict, silent, or streaming
425
+ - 🔍 **Pattern matching** - Wait for specific output patterns
426
+ - 🌍 **Environment management** - Custom env vars and PATH handling
427
+ - 🛡️ **TypeScript first** - Full type safety and IntelliSense
428
+
429
+ ## Installation 📦
430
+
431
+ ```bash
432
+ # Using npm
433
+ npm install @push.rocks/smartshell --save
434
+
435
+ # Using yarn
436
+ yarn add @push.rocks/smartshell
437
+
438
+ # Using pnpm (recommended)
439
+ pnpm add @push.rocks/smartshell
440
+ ```
441
+
442
+ ## Quick Start 🏃‍♂️
443
+
444
+ ```typescript
445
+ import { Smartshell } from '@push.rocks/smartshell';
446
+
447
+ // Create your shell instance
448
+ const shell = new Smartshell({
449
+ executor: 'bash' // or 'sh' for lighter shells
450
+ });
451
+
452
+ // Run a simple command
453
+ const result = await shell.exec('echo "Hello, World!"');
454
+ console.log(result.stdout); // "Hello, World!"
455
+ ```
456
+
457
+ ## Core Concepts 💡
458
+
459
+ ### The Smartshell Instance
460
+
461
+ The heart of smartshell is the `Smartshell` class. Each instance maintains its own environment and configuration:
462
+
463
+ ```typescript
464
+ const shell = new Smartshell({
465
+ executor: 'bash', // Choose your shell: 'bash' or 'sh'
466
+ sourceFilePaths: ['/path/to/env.sh'], // Optional: source files on init
467
+ });
468
+ ```
469
+
470
+ ## Execution Modes 🎛️
471
+
472
+ ### Standard Execution
473
+
474
+ Perfect for general commands where you want to see the output:
475
+
476
+ ```typescript
477
+ const result = await shell.exec('ls -la');
478
+ console.log(result.stdout); // Directory listing
479
+ console.log(result.exitCode); // 0 for success
480
+ ```
481
+
482
+ ### Silent Execution
483
+
484
+ Run commands without printing to console - ideal for capturing output:
485
+
486
+ ```typescript
487
+ const result = await shell.execSilent('cat /etc/hostname');
488
+ // Output is NOT printed to console but IS captured in result
489
+ console.log(result.stdout); // Access the captured output here
490
+ console.log(result.exitCode); // Check exit code (0 = success)
491
+
492
+ // Example: Process output programmatically
493
+ const files = await shell.execSilent('ls -la');
494
+ const fileList = files.stdout.split('
495
+ ');
496
+ fileList.forEach(file => {
497
+ // Process each file entry
498
+ });
499
+ ```
500
+
501
+ **Key Point:** Silent methods (`execSilent`, `execStrictSilent`, `execStreamingSilent`) suppress console output but still capture everything in the result object for programmatic access.
502
+
503
+ ### Strict Execution
504
+
505
+ Throws an error if the command fails - great for critical operations:
506
+
507
+ ```typescript
508
+ try {
509
+ await shell.execStrict('critical-command');
510
+ console.log('✅ Command succeeded!');
511
+ } catch (error) {
512
+ console.error('❌ Command failed:', error);
513
+ }
514
+ ```
515
+
516
+ ### Streaming Execution
517
+
518
+ For long-running processes or when you need real-time output:
519
+
520
+ ```typescript
521
+ const streaming = await shell.execStreaming('npm install');
522
+
523
+ // Access the child process directly
524
+ streaming.childProcess.stdout.on('data', (chunk) => {
525
+ console.log('📦 Installing:', chunk.toString());
526
+ });
527
+
528
+ // Wait for completion
529
+ await streaming.finalPromise;
530
+ ```
531
+
532
+ ### Interactive Execution
533
+
534
+ When commands need user input:
535
+
536
+ ```typescript
537
+ // This will connect to your terminal for input
538
+ await shell.execInteractive('npm init');
539
+ ```
540
+
541
+ ## Advanced Features 🔥
542
+
543
+ ### Wait for Specific Output
544
+
545
+ Perfect for waiting on services to start:
546
+
547
+ ```typescript
548
+ // Wait for a specific line before continuing
549
+ await shell.execAndWaitForLine(
550
+ 'npm run dev',
551
+ /Server started on port 3000/
552
+ );
553
+ console.log('🚀 Server is ready!');
554
+ ```
555
+
556
+ ### Silent Pattern Waiting
557
+
558
+ Same as above, but without console output:
559
+
560
+ ```typescript
561
+ await shell.execAndWaitForLineSilent(
562
+ 'docker-compose up',
563
+ /database system is ready to accept connections/
564
+ );
565
+ // The command output is suppressed from console but the pattern matching still works
566
+ ```
567
+
568
+ ### Environment Customization
569
+
570
+ Smartshell provides powerful environment management:
571
+
572
+ ```typescript
573
+ // Add custom source files
574
+ shell.shellEnv.addSourceFiles([
575
+ '/home/user/.custom_env',
576
+ './project.env.sh'
577
+ ]);
578
+
579
+ // Modify PATH
580
+ shell.shellEnv.pathDirArray.push('/custom/bin');
581
+ shell.shellEnv.pathDirArray.push('/usr/local/special');
582
+
583
+ // Your custom environment is ready
584
+ const result = await shell.exec('my-custom-command');
585
+ ```
586
+
587
+ ### Smart Execution Utility
588
+
589
+ The `SmartExecution` class enables restartable streaming processes:
590
+
591
+ ```typescript
592
+ import { SmartExecution } from '@push.rocks/smartshell';
593
+
594
+ const execution = new SmartExecution(shell, 'npm run watch');
595
+
596
+ // Restart the process whenever needed
597
+ await execution.restart();
598
+
599
+ // Access the current streaming execution
600
+ if (execution.currentStreamingExecution) {
601
+ execution.currentStreamingExecution.childProcess.stdout.on('data', (data) => {
89
602
  console.log(data.toString());
90
603
  });
604
+ }
605
+ ```
91
606
 
92
- // Remember to handle the process termination as necessary.
93
- })();
607
+ ### Shell Detection
608
+
609
+ Need to check if a command exists? We export the `which` utility:
610
+
611
+ ```typescript
612
+ import { which } from '@push.rocks/smartshell';
613
+
614
+ try {
615
+ const gitPath = await which('git');
616
+ console.log(`Git found at: ${gitPath}`);
617
+ } catch (error) {
618
+ console.log('Git is not installed');
619
+ }
94
620
  ```
95
621
 
96
- ### Advanced Usage
622
+ ## Real-World Examples 🌍
97
623
 
98
- #### Executing With Custom Environment Variables
624
+ ### Build Pipeline
99
625
 
100
- `smartshell` allows for the execution of commands within a modified environment, facilitating the use of custom variables or altered PATH values:
626
+ ```typescript
627
+ const shell = new Smartshell({ executor: 'bash' });
628
+
629
+ // Clean build directory
630
+ await shell.execSilent('rm -rf dist');
631
+
632
+ // Run TypeScript compiler
633
+ const buildResult = await shell.execStrict('tsc');
634
+
635
+ // Run tests
636
+ await shell.execStrict('npm test');
637
+
638
+ // Build succeeded!
639
+ console.log('✅ Build pipeline completed successfully');
640
+ ```
641
+
642
+ ### Development Server with Auto-Restart
101
643
 
102
644
  ```typescript
103
- (async () => {
104
- smartShellInstance.shellEnv.addSourceFiles(['/path/to/envFile']);
105
- smartShellInstance.shellEnv.pathDirArray.push('/custom/bin');
645
+ const shell = new Smartshell({ executor: 'bash' });
646
+ const devServer = new SmartExecution(shell, 'npm run dev');
647
+
648
+ // Watch for file changes and restart
649
+ fs.watch('./src', async () => {
650
+ console.log('🔄 Changes detected, restarting...');
651
+ await devServer.restart();
652
+ });
653
+ ```
654
+
655
+ ### Docker Compose Helper
656
+
657
+ ```typescript
658
+ const shell = new Smartshell({ executor: 'bash' });
659
+
660
+ // Start services and wait for readiness
661
+ console.log('🐳 Starting Docker services...');
662
+ await shell.execAndWaitForLine(
663
+ 'docker-compose up',
664
+ /All services are ready/,
665
+ { timeout: 60000 }
666
+ );
667
+
668
+ // Run migrations
669
+ await shell.execStrict('docker-compose exec app npm run migrate');
670
+ console.log('✅ Environment ready!');
671
+ ```
672
+
673
+ ### CI/CD Integration
674
+
675
+ ```typescript
676
+ const shell = new Smartshell({ executor: 'bash' });
677
+
678
+ async function runCIPipeline() {
679
+ // Install dependencies
680
+ await shell.execStrict('pnpm install --frozen-lockfile');
681
+
682
+ // Run linting
683
+ const lintResult = await shell.execSilent('npm run lint');
684
+ if (lintResult.exitCode !== 0) {
685
+ throw new Error(`Linting failed:
686
+ ${lintResult.stdout}`);
687
+ }
106
688
 
107
- const result = await smartShellInstance.exec('echo $CUSTOM_VAR');
108
- console.log(result.stdout); // Outputs the value of CUSTOM_VAR
109
- })();
689
+ // Run tests with coverage
690
+ const testResult = await shell.exec('npm run test:coverage');
691
+
692
+ // Build project
693
+ await shell.execStrict('npm run build');
694
+
695
+ // Deploy if on main branch
696
+ if (process.env.BRANCH === 'main') {
697
+ await shell.execStrict('npm run deploy');
698
+ }
699
+ }
110
700
  ```
111
701
 
112
- ### Interactive Mode
702
+ ## API Reference 📚
113
703
 
114
- For commands that require interactive terminal input (not typically recommended for automated scripts), you can use `execInteractive`:
704
+ ### Smartshell Class
705
+
706
+ | Method | Description | Returns |
707
+ |--------|-------------|---------|
708
+ | `exec(command)` | Execute command with output | `Promise<IExecResult>` |
709
+ | `execSilent(command)` | Execute without console output | `Promise<IExecResult>` |
710
+ | `execStrict(command)` | Execute, throw on failure | `Promise<IExecResult>` |
711
+ | `execStrictSilent(command)` | Strict + silent execution | `Promise<IExecResult>` |
712
+ | `execStreaming(command)` | Stream output in real-time | `Promise<IExecResultStreaming>` |
713
+ | `execStreamingSilent(command)` | Stream without console output | `Promise<IExecResultStreaming>` |
714
+ | `execInteractive(command)` | Interactive terminal mode | `Promise<void>` |
715
+ | `execAndWaitForLine(command, regex)` | Wait for pattern match | `Promise<void>` |
716
+ | `execAndWaitForLineSilent(command, regex)` | Silent pattern waiting | `Promise<void>` |
717
+
718
+ ### Result Interfaces
115
719
 
116
720
  ```typescript
117
- (async () => {
118
- await smartShellInstance.execInteractive('npm init');
119
- })();
721
+ interface IExecResult {
722
+ exitCode: number; // Process exit code
723
+ stdout: string; // Standard output
724
+ }
725
+
726
+ interface IExecResultStreaming {
727
+ childProcess: ChildProcess; // Node.js ChildProcess instance
728
+ finalPromise: Promise<void>; // Resolves when process exits
729
+ }
120
730
  ```
121
731
 
122
- ### Waiting for Specific Output
732
+ ## Understanding Silent Modes 🤫
733
+
734
+ Silent execution modes are perfect when you need to capture command output for processing without cluttering the console. Here's what you need to know:
735
+
736
+ ### How Silent Modes Work
123
737
 
124
- To wait for a specific line before proceeding, you might use `execAndWaitForLine`. This is useful for waiting on a process to log a certain message:
738
+ 1. **Output is captured, not lost**: All stdout content is stored in the result object
739
+ 2. **Console stays clean**: Nothing is printed during execution
740
+ 3. **Full programmatic access**: Process the output however you need
741
+
742
+ ### Available Silent Methods
125
743
 
126
744
  ```typescript
127
- (async () => {
128
- await smartShellInstance.execAndWaitForLine('npm run watch', /Compilation complete./);
129
- console.log('The watch process has finished compiling.');
130
- })();
745
+ // Basic silent execution
746
+ const result = await shell.execSilent('ls -la');
747
+ console.log(result.stdout); // Access captured output
748
+ console.log(result.exitCode); // Check success/failure
749
+
750
+ // Strict + Silent (throws on error)
751
+ try {
752
+ const result = await shell.execStrictSilent('important-command');
753
+ const output = result.stdout; // Process the output
754
+ } catch (error) {
755
+ // Handle failure
756
+ }
757
+
758
+ // Streaming + Silent
759
+ const streaming = await shell.execStreamingSilent('long-running-process');
760
+ streaming.childProcess.stdout.on('data', (chunk) => {
761
+ // Process chunks as they arrive
762
+ const data = chunk.toString();
763
+ });
764
+
765
+ // Pattern matching + Silent
766
+ await shell.execAndWaitForLineSilent('server-start', /Ready on port/);
131
767
  ```
132
768
 
133
- Given the vast array of features offered by `@push.rocks/smartshell`, integrating shell operations into your TypeScript applications becomes both straightforward and powerful. By harnessing promises and async/await syntax, `smartshell` effectively streamlines shell interactions, making your code cleaner and more intuitive.
769
+ ### Common Use Cases for Silent Execution
770
+
771
+ ```typescript
772
+ // Parse JSON output
773
+ const jsonResult = await shell.execSilent('aws s3 ls --output json');
774
+ const buckets = JSON.parse(jsonResult.stdout);
775
+
776
+ // Count lines
777
+ const wcResult = await shell.execSilent('wc -l huge-file.txt');
778
+ const lineCount = parseInt(wcResult.stdout.split(' ')[0]);
779
+
780
+ // Check if command exists
781
+ const whichResult = await shell.execSilent('which docker');
782
+ const dockerPath = whichResult.exitCode === 0 ? whichResult.stdout.trim() : null;
783
+
784
+ // Collect system info
785
+ const unameResult = await shell.execSilent('uname -a');
786
+ const systemInfo = unameResult.stdout.trim();
787
+ ```
788
+
789
+ ## Tips & Best Practices 💎
790
+
791
+ 1. **Choose the right executor**: Use `bash` for full features, `sh` for minimal overhead
792
+ 2. **Use strict mode for critical operations**: Ensures failures don't go unnoticed
793
+ 3. **Stream long-running processes**: Better UX and memory efficiency
794
+ 4. **Leverage silent modes**: When you only need to capture output
795
+ 5. **Handle errors gracefully**: Always wrap strict executions in try-catch
796
+ 6. **Clean up resources**: Streaming processes should be properly terminated
134
797
 
135
798
  ## License and Legal Information
136
799
 
@@ -149,4 +812,4 @@ Registered at District court Bremen HRB 35230 HB, Germany
149
812
 
150
813
  For any legal inquiries or if you require further information, please contact us via email at hello@task.vc.
151
814
 
152
- By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
815
+ By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@push.rocks/smartshell',
6
- version: '3.2.3',
6
+ version: '3.2.4',
7
7
  description: 'A library for executing shell commands using promises.'
8
8
  }