@j-o-r/sh 0.0.3 → 1.0.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
@@ -4,9 +4,7 @@ Execute shell commands from JavaScript.
4
4
 
5
5
  ## Introduction
6
6
 
7
- BETA
8
-
9
- This Node.js module, `@j-o-r/sh`, simplifies the execution of shell commands within JavaScript applications. It provides a range of utilities to handle shell scripts and manage their output efficiently.
7
+ `@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.
10
8
 
11
9
  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.
12
10
 
@@ -27,7 +25,7 @@ To execute a shell command, use the `SH` function:
27
25
  ```javascript
28
26
  import { SH, cd, within, sleep, retry, expBackoff } from '@j-o-r/sh';
29
27
 
30
- SH`your_shell_command`
28
+ SH`your_shell_command`.run()
31
29
  .then(output => {
32
30
  console.log('Output:', output);
33
31
  })
@@ -36,27 +34,28 @@ SH`your_shell_command`
36
34
  });
37
35
  ```
38
36
 
39
- ```javascript
37
+ ### Advanced Usage
40
38
 
41
- const res = await SH`ls -FLa`.pipe(SH`grep package.json`);
42
- console.log(res.toString());
39
+ ```javascript
40
+ const res = await SH`ls -FLa | grep package.json | wc -l`.run();
41
+ console.log(res);
43
42
 
44
43
  const ar = within(async () => {
45
- const res = await Promise.all([
46
- SH`sleep 1; echo 1`,
47
- SH`sleep 2; echo 2`,
48
- sleep(2),
49
- SH`sleep 3; echo 3`
50
- ]);
44
+ const res = await Promise.all([
45
+ SH`sleep 1; echo 1`.run(),
46
+ SH`sleep 2; echo 2`.run(),
47
+ sleep(2),
48
+ SH`sleep 3; echo 3`.run()
49
+ ]);
51
50
  });
52
-
53
51
  ```
54
52
 
55
53
  ```javascript
56
- const p = await retry(3, expBackoff(), () => SH`curl -s https://unreachable:`);
54
+ const p = await retry(3, expBackoff(), () => SH`curl -s https://unreachable`.run());
57
55
  ```
58
56
 
59
- The `SH` method accepts a template literal string enclosed in backticks as its argument. It returns a `ProcessPromise`. Once this promise is resolved, it yields a `ProcessOutput` object.
57
+ The `SH` method accepts a template literal string enclosed in backticks as its argument. It returns an `SHDispatch` object.
58
+
60
59
  ### Additional Utilities
61
60
 
62
61
  The module also provides additional utilities for common tasks:
@@ -64,64 +63,57 @@ The module also provides additional utilities for common tasks:
64
63
  - `cd(dir)`: Change the working directory.
65
64
  - `sleep(duration)`: Pause execution for a specified duration.
66
65
  - `retry(count, interval, callback)`: Retry a command a specified number of times with an optional interval.
67
- - `stdin()`: Read from standard input.
66
+ - `readIn()`: Read from standard input.
68
67
  - `within(callback)`: Create an async context in a sync block.
69
68
  - `expBackoff(max, rand)`: Generate intervals for exponential backoff.
70
69
 
70
+ ## SHDispatch
71
71
 
72
- ## ProcessPromise
73
-
74
- This class is returned by the shell command. Here's a summary of its methods and properties:
72
+ This class is returned by the `SH` function. Here's a summary of its methods and properties:
75
73
 
76
74
  ### Methods
77
75
 
78
- - **pipe(dest)**: Pipes the output of this process to the input of another `ProcessPromise`
79
- - **kill(signal = 'SIGTERM')**: Sends a kill signal to the child process.
80
- - **stdio(stdin, stdout, stderr)**: Sets the standard input/output/error streams for the child process.
81
- - **nothrow()**: Configures the promise not to throw an error when the command execution fails.
82
- - **quiet()**: Suppresses log output.
83
- - **verbose()**: Enables verbose log output.
84
- - **timeout(d, signal = 'SIGTERM')**: Sets a timeout for killing the process.
85
- - **halt()**: Stops the execution of the next step in the process.
86
-
87
- ### Getters
88
-
89
- - **stdin**: Returns the standard input stream of the child process.
90
- - **stdout**: Returns the standard output stream of the child process.
91
- - **stderr**: Returns the standard error stream of the child process.
92
- - **exitCode**: Returns a promise that resolves to the exit code of the child process.
93
-
94
- ### Properties
95
-
96
- - **isHalted**: A getter that returns a boolean indicating whether the promise is halted.
97
-
98
- ## Output
99
-
100
- The `ProcessOutput` class collects output from the `ProcessPromise` shell process. It extends the `Error` class to provide compatibility with error handling mechanisms. Here's a summary of its features:
101
-
102
-
103
- ### Getters
104
-
105
- - **stdout**: Returns the standard output (stdout) of the child process as a string.
106
- - **stderr**: Returns the error output (stderr) of the child process as a string.
107
- - **exitCode**: Returns the exit code of the process as a number.
108
- - **signal**: Returns the signal received by the process, such as 'SIGTERM', as a string.
109
-
110
- ### Methods
111
-
112
- - **toString()**:
113
- - Returns a trimmed string combining `stderr` and `stdout`.
114
- - This method is automatically invoked by various JavaScript methods for output consolidation.
115
- - **[inspect.custom]()**:
116
- - Custom inspection method used for debugging.
117
- - Displays the current state of the object when passed to `console.log`.
76
+ - **options(options)**: Sets options for the command execution.
77
+ - **run(payload?)**: Executes the command and returns a promise that resolves with the command's output.
78
+ - **runSync()**: Executes the command synchronously and returns a `SpawnSyncResponse`.
79
+ - **kill()**: Sends a kill signal to the child process.
118
80
 
119
81
  ### Examples
120
82
 
121
- - Script for setting up a wokspace in [TMUX](./workspace.js)
122
- - Take a look at the [test](./test/sh.js)
83
+ - Elementary usages, piped:
84
+ ```javascript
85
+ const res = await SH`ls -FLa | grep package.json | wc -l`.run();
86
+ console.log(res);
87
+ ```
88
+
89
+ - Feed command with content:
90
+ ```javascript
91
+ const res = await SH`wc -l`.run(`one\ntwo\n`);
92
+ console.log(res);
93
+ ```
94
+
95
+ - Async context with multiple commands and sleep:
96
+ ```javascript
97
+ within(async () => {
98
+ const res = await Promise.all([
99
+ SH`sleep 1; echo 1`.run(),
100
+ SH`sleep 2; echo 2`.run(),
101
+ sleep(2),
102
+ SH`sleep 3; echo 3`.run()
103
+ ]);
104
+ console.log(res);
105
+ });
106
+ ```
107
+
108
+ - Retry with exponential backoff:
109
+ ```javascript
110
+ try {
111
+ const p = await retry(3, expBackoff(), () => SH`curl -s https://flipwrsi`.run());
112
+ } catch (e) {
113
+ console.error('Retry failed:', e);
114
+ }
115
+ ```
123
116
 
124
117
  ## License
125
118
 
126
119
  This project is licensed under the Apache License, Version 2.0.
127
-
package/lib/sh.d.ts CHANGED
@@ -1,44 +1,93 @@
1
+ export type SpawnSyncResponse = {
2
+ /**
3
+ * - The exit code of the child process. A value of `0` indicates success.
4
+ */
5
+ status: number;
6
+ /**
7
+ * - The signal used to terminate the process, if any.
8
+ */
9
+ signal: Buffer | null;
10
+ /**
11
+ * - An array containing the standard output and standard error of the child process.
12
+ */
13
+ output: Array<string | null>;
14
+ /**
15
+ * - The process ID of the child process.
16
+ */
17
+ pid: number;
18
+ /**
19
+ * - The standard output of the child process.
20
+ */
21
+ stdout: Buffer | null;
22
+ /**
23
+ * - The standard error of the child process.
24
+ */
25
+ stderr: Buffer | null;
26
+ };
1
27
  /**
2
- * Creates a new ProcessPromise object that represents a command to be executed.
28
+ * Default options for the execution environment.
3
29
  */
4
- export type Shell = Function;
30
+ export type SHOptions = {
31
+ /**
32
+ * - The current working directory.
33
+ */
34
+ cwd?: string;
35
+ /**
36
+ * - The environment variables.
37
+ */
38
+ env?: NodeJS.ProcessEnv;
39
+ /**
40
+ * - The shell to use for execution.
41
+ */
42
+ shell?: string;
43
+ /**
44
+ * - The prefix commands to ensure a safe execution environment.
45
+ */
46
+ prefix?: string;
47
+ /**
48
+ * - The stdio configuration.
49
+ */
50
+ stdio?: StdioOption | StdioOptions;
51
+ };
52
+ export type StdioOption = ('pipe' | 'ignore' | 'inherit' | number);
53
+ export type StdioOptions = Array<StdioOption> | StdioOption;
5
54
  /**
6
- * Creates a new ProcessPromise object that represents a command to be executed.
7
- *
8
- * @typedef {Function} Shell
9
- * @property {function(Array, ...*): ProcessPromise} execute - The function to execute the command.
10
- * @property {boolean} verbose - A property to control verbosity.
11
- *
12
- * @param {Array} pieces - An array of string literals from a template literal.
13
- * @param {...*} args - The values to be interpolated into the string literals.
14
- * @returns {ProcessPromise} A ProcessPromise object that represents the command.
15
- * @throws {Error} Throws an error if any of the string literals in `pieces` is undefined.
16
- *
17
- * @example
18
- * const command = await SH`echo 'Hello, world!'`;
55
+ * Creates a new SHDispatch object that represents a command to be executed.
19
56
  */
20
- /** @type {Shell & { (pieces: TemplateStringsArray, ...args: any[]): ProcessPromise }} */
21
- export const SH: Function & ((pieces: TemplateStringsArray, ...args: any[]) => ProcessPromise);
57
+ export type Shell = Function;
58
+ /** @type {Shell & { (pieces: TemplateStringsArray, ...args: *): SHDispatch }} */
59
+ export const SH: Shell & {
60
+ (pieces: TemplateStringsArray, ...args: any): SHDispatch;
61
+ };
22
62
  /**
23
63
  * Change working directory
24
64
  * @param {string} dir
25
65
  */
26
66
  export function cd(dir: string): void;
27
67
  /**
28
- * This function pauses or "sleeps" code execution for a specified duration.
29
- * @param {string|number} duration - The duration to pause execution for, e.g., '100ms' or '3s'.
30
- *
68
+ * Generates an exponential backoff time with a random jitter.
69
+ *
70
+ * @generator
71
+ * @param {string} [max='60s'] - The maximum backoff time in a human-readable format (e.g., '60s' for 60 seconds).
72
+ * @param {string} [rand='100ms'] - The maximum random jitter time in a human-readable format (e.g., '100ms' for 100 milliseconds).
73
+ * @yields {number} The backoff time in milliseconds.
74
+ */
75
+ export function expBackoff(max?: string, rand?: string): Generator<number, void, unknown>;
76
+ /**
77
+ * This function reads the standard input (stdin) from the current process.
31
78
  * @example
32
- *
33
- * const res = await Promise.all([
34
- * SH`sleep 2; echo 2`, // Sleep for 2 seconds
35
- * sleep(2), // Sleep for 2 seconds
36
- * SH`sleep 3; echo 3` // Sleep for 3 seconds
37
- * ]);
79
+ * const content = await stdin();
38
80
  */
39
- export function sleep(duration: string | number): Promise<any>;
81
+ export function readIn(): Promise<string>;
40
82
  /**
41
- * This function retries a command a specified number of times.
83
+ * Retries a given asynchronous function a specified number of times with optional delays between attempts.
84
+ *
85
+ * @param {number} count - The number of retry attempts.
86
+ * @param {string|expBackoff|Function} a - Either a delay duration as a string, a delay generator object, or the callback function.
87
+ * @param {Function} [b] - The callback function to retry, required if `a` is not a function.
88
+ * @returns {Promise<*>} - The result of the callback function if it succeeds within the retry attempts.
89
+ * @throws {Error} - The last error encountered if all retry attempts fail.
90
+ *
42
91
  * @example
43
92
  * // Retry a command 3 times
44
93
  * const p = await retry(3, () => SH`curl -s https://flipwrsi`);
@@ -49,26 +98,50 @@ export function sleep(duration: string | number): Promise<any>;
49
98
  * // Retry a command 3 times with irregular intervals using exponential backoff
50
99
  * const p = await retry(3, expBackoff(), () => SH`curl -s https://flipwrsi`);
51
100
  */
52
- export function retry(count: any, a: any, b: any): Promise<any>;
101
+ export function retry(count: number, a: string | typeof expBackoff | Function, b?: Function): Promise<any>;
53
102
  /**
54
- * This function reads the standard input (stdin) for the current process.
55
- * It is used to get piped content into a script.
103
+ * This function pauses or "sleeps" code execution for a specified duration.
104
+ * @param {string|number} duration - The duration to pause execution for, e.g., '100ms' or '3s'.
105
+ *
56
106
  * @example
57
- * const content = await stdin();
107
+ *
108
+ * const res = await sleep('5s');
58
109
  */
59
- export function stdin(): Promise<string>;
110
+ export function sleep(duration: string | number): Promise<any>;
60
111
  /**
61
112
  * Create a async context in an sync block
62
113
  * @param {function} callback - async function
63
114
  * @example
64
115
  * const p = within(async () => {
65
116
  * const res = await Promise.all([
66
- * SH`sleep 1; echo 1`,
67
- * SH`sleep 2; echo 2`,
117
+ * SH`sleep 1; echo 1`.run(),
118
+ * SH`sleep 2; echo 2`.run(),
68
119
  * sleep(2),
69
- * SH`sleep 3; echo 3`
120
+ * SH`sleep 3; echo 3`.run()
70
121
  * ]);
71
122
  */
72
- export function within(callback: Function): any;
73
- export function expBackoff(max?: string, rand?: string): Generator<number, void, unknown>;
74
- import ProcessPromise from './ProcessPromise.js';
123
+ export function within(callback: Function): void;
124
+ declare class SHDispatch {
125
+ /**
126
+ * @param {string} cmd - cmd to execute
127
+ */
128
+ constructor(cmd: string);
129
+ /**
130
+ * @param {SHOptions} options
131
+ * @returns {SHDispatch}
132
+ */
133
+ options(options: SHOptions): SHDispatch;
134
+ /**
135
+ * @param {string} [payload]
136
+ * @returns {Promise<string>}
137
+ */
138
+ run(payload?: string): Promise<string>;
139
+ /**
140
+ * Works for screen takeovers like editors
141
+ * @returns {SpawnSyncResponse}
142
+ */
143
+ runSync(): SpawnSyncResponse;
144
+ kill(): Promise<void>;
145
+ #private;
146
+ }
147
+ export {};