@j-o-r/sh
Version:
Execute shell commands on Linux-based systems from javascript
177 lines (142 loc) • 4.72 kB
Markdown
# @j-o-r/sh
Execute shell commands from JavaScript.
## Introduction
`@j-o-r/sh` is a Node.js module that simplifies the execution of shell commands within JavaScript applications. It provides a range of utilities to handle shell scripts and manage their output efficiently.
This project draws inspiration from the exceptional [zx library](https://github.com/google/zx). The core functionality of zx, particularly the shell execution method, has been extracted and forms the foundation of this project.
## Installation
Install the module using npm:
```sh
npm install @j-o-r/sh
```
## Usage
### Basic Usage
To execute a shell command, use the `SH` function:
```javascript
import { SH, cd, within, sleep, retry, expBackoff } from '@j-o-r/sh';
SH`your_shell_command`.run()
.then(output => {
console.log('Output:', output);
})
.catch(error => {
console.error('Error:', error);
});
```
### Advanced Usage
```javascript
const res = await SH`ls -FLa | grep package.json | wc -l`.run();
console.log(res);
const ar = within(async () => {
const res = await Promise.all([
SH`sleep 1; echo 1`.run(),
SH`sleep 2; echo 2`.run(),
sleep(2),
SH`sleep 3; echo 3`.run()
]);
});
```
```javascript
const p = await retry(3, expBackoff(), () => SH`curl -s https://unreachable`.run());
```
The `SH` method accepts a template literal string enclosed in backticks as its argument. It returns an `SHDispatch` object.
### Additional Utilities
The module also provides additional utilities for common tasks:
- `parseArgs(process.args)`: Transform an array of strings into an object
- `cd(dir)`: Change the working directory.
- `sleep(duration)`: Pause execution for a specified duration.
- `retry(count, interval, callback)`: Retry a command a specified number of times with an optional interval.
- `readIn()`: Read from standard input.
- `within(callback)`: Create an async context in a sync block.
- `expBackoff(max, rand)`: Generate intervals for exponential backoff.
- `jsType(any)`: Get the 'real' javascript variable type
- `assert.`: Node assert library
- `new Test()`: A small sync/async minimal test framework
## SHDispatch
This class is returned by the `SH` function. Here's a summary of its methods and properties:
### Methods
- **options(options)**: Sets options for the command execution.
- **run(payload?)**: Executes the command and returns a promise that resolves with the command's output.
- **runSync(payload?)**: Executes the command synchronously and returns a `SpawnSyncResponse`.
- **kill()**: Sends a kill signal to the child process.
### Examples
- Elementary usages, piped:
```javascript
const res = await SH`ls -FLa | grep package.json | wc -l`.run();
console.log(res);
```
- Feed command with content:
```javascript
const res = await SH`wc -l`.run(`one\ntwo\n`);
console.log(res);
```
- Create a command from a string
```javascript
const command = "uname -r";
const content = await SH`${command}`.run();
console.log(content);
```
- Async context with multiple commands and sleep:
```javascript
within(async () => {
const res = await Promise.all([
SH`sleep 1; echo 1`.run(),
SH`sleep 2; echo 2`.run(),
sleep(2),
SH`sleep 3; echo 3`.run()
]);
console.log(res);
});
```
- Retry with exponential backoff:
```javascript
try {
const p = await retry(3, expBackoff(), () => SH`curl -s https://flipwrsi`.run());
} catch (e) {
console.error('Retry failed:', e);
}
```
- Method for copying data to the clipboard:
```javascript
/**
* Copy text to the clipboard
* @param {string} text
* @returns {Promise<string>}
*/
const copyToClipboard = async (text) => {
const prams = [
'-selection',
'clipboard'
]
return SH`xclip ${prams}`.options({stdio: 'inherit'}).run(text);
}
```
- Open the 'vim' editor
```javascript
SH`vim`.options({stdio: 'inherit'}).runSync();
```
- Create and run a test
```javascript
import { assert, jsType, Test} from '@j-o-r/sh';
const test = new Test();
test.add('Test is test in sync', () => {
assert.strictEqual(jsType(test), 'Test');
});
test.add('Test an Array in sync', () => {
assert.strictEqual(jsType([]), 'Array');
});
test.add('Test is test in async', async () => {
assert.strictEqual(jsType(test), 'Test');
});
test.add('Test is test in async, returning a promise', async () => {
return new Promise((resolve, _reject) => {
assert.strictEqual(jsType(test), 'Test');
resolve();
});
});
const report = await test.run();
if (report.errors > 0) {
process.exit(1);
}
// await test.run([0,3]); // only run test 0 and 3
```
## License
This project is licensed under the Apache License, Version 2.0.