@j-o-r/sh 1.1.25 → 1.1.27
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/lib/SH.js +57 -14
- package/lib/SHDispatch.js +14 -16
- package/module.md +150 -72
- package/package.json +1 -1
- package/types/SH.d.ts +23 -1
- package/types/SHDispatch.d.ts +20 -3
package/lib/SH.js
CHANGED
|
@@ -103,22 +103,62 @@ const parseDuration = (d) => {
|
|
|
103
103
|
}
|
|
104
104
|
throw new Error(`Unknown duration: "${d}".`);
|
|
105
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* bash escape a string suitable as an argument on the commandline
|
|
108
|
+
* for javascript code
|
|
109
|
+
* @param {string} x
|
|
110
|
+
* @returns {string}
|
|
111
|
+
*/
|
|
112
|
+
const bashEscape = (x) => {
|
|
113
|
+
let str = String(x).trim();
|
|
114
|
+
// the trick is to double escape escape vars first
|
|
115
|
+
str = str.replace(/\\/g, '\\\\');
|
|
116
|
+
// then add escaping for oddities
|
|
117
|
+
// Replace literal escape sequences like \n, \t, \r in quoted strings
|
|
118
|
+
str = str.replace(/(['"])\\(.)\1/g, '$1\\\\$2$1');
|
|
119
|
+
// escape $ (is a BASH var)
|
|
120
|
+
str = str.replace(/\$/g, '\\$');
|
|
121
|
+
// Escape backticks
|
|
122
|
+
str = str.replace(/`/g, '\\`');
|
|
123
|
+
// Escape quotes
|
|
124
|
+
str = str.replace(/"/g, '\\"');
|
|
125
|
+
return str;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
/** @type {import('./SHDispatch.js').SHOptions} */
|
|
130
|
+
const defaultOptions = {
|
|
131
|
+
cwd: process.cwd(),
|
|
132
|
+
env: process.env,
|
|
133
|
+
shell: 'bash',
|
|
134
|
+
stdio: ['inherit', 'pipe', 'pipe'],
|
|
135
|
+
timeout: 0, // when 0 there is no timeout
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const setHandler = {
|
|
139
|
+
set(target, prop, value) {
|
|
140
|
+
defaultOptions[prop] = value; // Allow setting on target
|
|
141
|
+
// console.log(`Set ${String(prop)} = ${value}`);
|
|
142
|
+
// console.log(defaultOptions);
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
106
147
|
/**
|
|
107
148
|
* A template-tag that returns an SHDispatch.
|
|
108
149
|
* @typedef {(pieces: TemplateStringsArray, ...args: unknown[]) => SHDispatch} SHTag
|
|
109
150
|
*/
|
|
110
151
|
/**
|
|
111
|
-
*
|
|
152
|
+
* SH template tag
|
|
153
|
+
*
|
|
154
|
+
* Interpolation rules:
|
|
155
|
+
* - Arrays: each element is String(x).trim(), with newlines/carriage returns/tabs escaped; if an element contains shell metacharacters or spaces, it is wrapped in single-quotes and internal single-quotes are escaped as '\''.
|
|
156
|
+
* - Non-array values: currently coerced with String(value) and inserted as-is (NOT shell-escaped). Be careful when interpolating untrusted input.
|
|
157
|
+
*
|
|
158
|
+
* @type {Shell & SHTag & defaultOptions}
|
|
159
|
+
* Returns an SHDispatch that can be configured via .options() and executed with .run() / .runSync().
|
|
160
|
+
* @returns {SHDispatch}
|
|
112
161
|
*/
|
|
113
|
-
/**
|
|
114
|
-
* SH template tag
|
|
115
|
-
*
|
|
116
|
-
* Interpolation rules:
|
|
117
|
-
* - Arrays: each element is String(x).trim(), with newlines/carriage returns/tabs escaped; if an element contains shell metacharacters or spaces, it is wrapped in single-quotes and internal single-quotes are escaped as '\''.
|
|
118
|
-
* - Non-array values: currently coerced with String(value) and inserted as-is (NOT shell-escaped). Be careful when interpolating untrusted input.
|
|
119
|
-
*
|
|
120
|
-
* Returns an SHDispatch that can be configured via .options() and executed with .run() / .runSync().
|
|
121
|
-
*/
|
|
122
162
|
const SH = new Proxy(function(pieces, ...args) {
|
|
123
163
|
if (pieces.some((p) => p == undefined)) {
|
|
124
164
|
throw new Error(`Malformed command ${pieces}`);
|
|
@@ -145,8 +185,9 @@ const SH = new Proxy(function(pieces, ...args) {
|
|
|
145
185
|
}
|
|
146
186
|
cmd += s + pieces[++i];
|
|
147
187
|
}
|
|
148
|
-
return new SHDispatch(cmd);
|
|
149
|
-
},
|
|
188
|
+
return new SHDispatch(cmd, defaultOptions);
|
|
189
|
+
}, setHandler);
|
|
190
|
+
|
|
150
191
|
|
|
151
192
|
/**
|
|
152
193
|
* Create a async/sync context in new execution callstack
|
|
@@ -220,11 +261,12 @@ const userIn = (prompt) => {
|
|
|
220
261
|
|
|
221
262
|
const cleanup = () => {
|
|
222
263
|
process.stdin.removeListener('data', onData);
|
|
264
|
+
// @ts-ignore
|
|
223
265
|
rl.removeAllListeners('line');
|
|
224
266
|
clearTimeout(timer);
|
|
225
267
|
rl.close();
|
|
226
268
|
};
|
|
227
|
-
|
|
269
|
+
// @ts-ignore
|
|
228
270
|
rl.on('line', (line) => {
|
|
229
271
|
buffer += line + '\n';
|
|
230
272
|
clearTimeout(timer);
|
|
@@ -415,5 +457,6 @@ export {
|
|
|
415
457
|
hasProp,
|
|
416
458
|
Test,
|
|
417
459
|
assert,
|
|
418
|
-
AsyncTracker
|
|
460
|
+
AsyncTracker,
|
|
461
|
+
bashEscape
|
|
419
462
|
}
|
package/lib/SHDispatch.js
CHANGED
|
@@ -48,7 +48,7 @@ import SHExec from './SHExecute.js';
|
|
|
48
48
|
/**
|
|
49
49
|
* Merge property values while maintaining the fixed set of props from the predefined object
|
|
50
50
|
* @param {SHOptions} predefined - options
|
|
51
|
-
* @param {
|
|
51
|
+
* @param {SHOptions} options
|
|
52
52
|
* @returns {SHOptions}
|
|
53
53
|
*/
|
|
54
54
|
const mergeOptions = (predefined, options) => {
|
|
@@ -63,7 +63,6 @@ const mergeOptions = (predefined, options) => {
|
|
|
63
63
|
return mergedObj;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
/** @type {SHOptions} */
|
|
67
66
|
/**
|
|
68
67
|
* SHOptions — effective defaults and semantics used by SHDispatch/SHExecute
|
|
69
68
|
*
|
|
@@ -79,19 +78,12 @@ const mergeOptions = (predefined, options) => {
|
|
|
79
78
|
* - The prefix (see options(prefix)) is only applied when a shell is used; it is ignored in no-shell mode.
|
|
80
79
|
* - Each call to options() resets to the defaults and merges the provided options; it does not accumulate from prior calls.
|
|
81
80
|
*/
|
|
82
|
-
const defaultOptions = {
|
|
83
|
-
cwd: process.cwd(),
|
|
84
|
-
env: process.env,
|
|
85
|
-
shell: 'bash',
|
|
86
|
-
stdio: ['inherit', 'pipe', 'pipe'],
|
|
87
|
-
timeout: 0 // when 0 there is no timeout
|
|
88
|
-
};
|
|
89
|
-
|
|
90
81
|
|
|
91
82
|
|
|
92
83
|
class SHDispatch {
|
|
93
84
|
// #prefix = 'set -euo pipefail;/usr/bin/env'
|
|
94
|
-
#prefix = 'set -euo pipefail'
|
|
85
|
+
// #prefix = 'set -euo pipefail'
|
|
86
|
+
#prefix = '';
|
|
95
87
|
#cmd = '';
|
|
96
88
|
#options = {};
|
|
97
89
|
/**
|
|
@@ -100,23 +92,29 @@ class SHDispatch {
|
|
|
100
92
|
#proc;
|
|
101
93
|
/**
|
|
102
94
|
* @param {string} cmd - cmd to execute
|
|
95
|
+
* @param {SHOptions} options
|
|
96
|
+
* @param {string} [prefix] - command prefix e.g (default) '/usr/bin/env'
|
|
103
97
|
*/
|
|
104
|
-
constructor(cmd) {
|
|
105
|
-
if (
|
|
98
|
+
constructor(cmd, options, prefix) {
|
|
99
|
+
if (typeof cmd !== 'string' || cmd === '') {
|
|
106
100
|
throw new Error('Undefined command');
|
|
107
101
|
}
|
|
108
102
|
this.#cmd = cmd;
|
|
109
|
-
this
|
|
103
|
+
this.options(options, prefix);
|
|
110
104
|
}
|
|
111
105
|
/**
|
|
112
|
-
* @param {
|
|
106
|
+
* @param {SHOptions} [options]
|
|
113
107
|
* @param {string} [prefix] - command prefix e.g (default) '/usr/bin/env'
|
|
114
108
|
* @returns {SHDispatch}
|
|
115
109
|
*/
|
|
116
110
|
options(options, prefix) {
|
|
111
|
+
// this.#options = defaultOptions
|
|
117
112
|
if (typeof prefix === 'string') {
|
|
118
113
|
this.#prefix = prefix;
|
|
119
114
|
}
|
|
115
|
+
if (!options) {
|
|
116
|
+
return this;
|
|
117
|
+
}
|
|
120
118
|
if (options.stdio && typeof options.stdio === 'string') {
|
|
121
119
|
// convert stdio to array
|
|
122
120
|
// This sets the default io values
|
|
@@ -124,7 +122,7 @@ class SHDispatch {
|
|
|
124
122
|
const io = options.stdio;
|
|
125
123
|
options.stdio = Array(3).fill(io);
|
|
126
124
|
}
|
|
127
|
-
this.#options = mergeOptions(
|
|
125
|
+
this.#options = mergeOptions(this.#options, options);
|
|
128
126
|
return this;
|
|
129
127
|
}
|
|
130
128
|
|
package/module.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
## Overview
|
|
4
4
|
|
|
5
5
|
**Name:** @j-o-r/sh
|
|
6
|
-
**Version:** 1.1.
|
|
6
|
+
**Version:** 1.1.26
|
|
7
7
|
**Description:** Execute shell commands on Linux-based systems from javascript.
|
|
8
8
|
|
|
9
9
|
This module simplifies the execution of shell commands within JavaScript applications, providing utilities to handle shell scripts and manage their output efficiently. It is inspired by the zx library and supports features like command execution, retries, user input, and more.
|
|
@@ -33,117 +33,196 @@ Requires Node.js >= 20.0.0.
|
|
|
33
33
|
|
|
34
34
|
### Basic Usage
|
|
35
35
|
|
|
36
|
-
To execute a shell command, use the `SH` function:
|
|
37
|
-
|
|
38
36
|
```javascript
|
|
39
37
|
import { SH } from '@j-o-r/sh';
|
|
40
38
|
|
|
41
|
-
SH`
|
|
42
|
-
|
|
43
|
-
console.log('Output:', output);
|
|
44
|
-
})
|
|
45
|
-
.catch(error => {
|
|
46
|
-
console.error('Error:', error);
|
|
47
|
-
});
|
|
39
|
+
const output = await SH`ls -la`.run();
|
|
40
|
+
console.log(output);
|
|
48
41
|
```
|
|
49
42
|
|
|
50
43
|
### Advanced Usage
|
|
51
44
|
|
|
52
45
|
```javascript
|
|
53
|
-
import { SH, cd, within, sleep, retry, expBackoff } from '@j-o-r/sh';
|
|
46
|
+
import { SH, cd, within, sleep, retry, expBackoff, userIn } from '@j-o-r/sh';
|
|
47
|
+
|
|
48
|
+
cd('/tmp'); // Change directory
|
|
54
49
|
|
|
55
|
-
const res = await SH`
|
|
50
|
+
const res = await SH`echo "Hello World"`.run();
|
|
56
51
|
console.log(res);
|
|
57
52
|
|
|
58
|
-
|
|
59
|
-
|
|
53
|
+
// Retry example
|
|
54
|
+
try {
|
|
55
|
+
const p = await retry(3, expBackoff(), () => SH`curl -s https://unreachable`.run());
|
|
56
|
+
console.log(p);
|
|
57
|
+
} catch (e) {
|
|
58
|
+
console.error('Retry failed:', e);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// User input
|
|
62
|
+
const user = userIn('Enter your name: ');
|
|
63
|
+
const name = await user.input;
|
|
64
|
+
console.log('Hello,', name);
|
|
65
|
+
|
|
66
|
+
// Within async context
|
|
67
|
+
within(async () => {
|
|
68
|
+
const results = await Promise.all([
|
|
60
69
|
SH`sleep 1; echo 1`.run(),
|
|
61
70
|
SH`sleep 2; echo 2`.run(),
|
|
62
71
|
sleep(2),
|
|
63
72
|
SH`sleep 3; echo 3`.run()
|
|
64
73
|
]);
|
|
74
|
+
console.log(results);
|
|
65
75
|
});
|
|
66
|
-
|
|
67
|
-
const p = await retry(3, expBackoff(), () => SH`curl -s https://unreachable`.run());
|
|
68
76
|
```
|
|
69
77
|
|
|
70
|
-
###
|
|
78
|
+
### Test Framework Example
|
|
79
|
+
|
|
80
|
+
```javascript
|
|
81
|
+
import { Test, assert, jsType } from '@j-o-r/sh';
|
|
82
|
+
|
|
83
|
+
const test = new Test();
|
|
84
|
+
test.add('Test type', () => {
|
|
85
|
+
assert.strictEqual(jsType('string'), 'String');
|
|
86
|
+
});
|
|
87
|
+
const report = await test.run();
|
|
88
|
+
if (report.errors > 0) {
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
```
|
|
71
92
|
|
|
72
|
-
|
|
73
|
-
```javascript
|
|
74
|
-
const user = userIn('Enter your name: ');
|
|
75
|
-
const name = await user.input;
|
|
76
|
-
console.log('Hello,', name);
|
|
77
|
-
```
|
|
93
|
+
### AsyncTracker Example
|
|
78
94
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
import { assert, jsType, Test } from '@j-o-r/sh';
|
|
95
|
+
```javascript
|
|
96
|
+
import { AsyncTracker } from '@j-o-r/sh';
|
|
82
97
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
98
|
+
const tracker = new AsyncTracker();
|
|
99
|
+
tracker.enable();
|
|
100
|
+
setTimeout(() => {
|
|
101
|
+
tracker.report(true); // Verbose report
|
|
102
|
+
}, 1000);
|
|
103
|
+
```
|
|
89
104
|
|
|
90
105
|
## Full API Reference
|
|
91
106
|
|
|
92
107
|
### Main Exports
|
|
93
108
|
|
|
94
|
-
- **SH**:
|
|
95
|
-
-
|
|
96
|
-
-
|
|
97
|
-
|
|
98
|
-
- **
|
|
99
|
-
-
|
|
100
|
-
|
|
101
|
-
- **
|
|
102
|
-
-
|
|
103
|
-
|
|
104
|
-
- **
|
|
105
|
-
-
|
|
106
|
-
|
|
107
|
-
- **
|
|
109
|
+
- **SH**: `(pieces: TemplateStringsArray, ...args: unknown[]) => SHDispatch`
|
|
110
|
+
- Template tag for creating shell commands. Returns SHDispatch.
|
|
111
|
+
- Interpolation: Arrays elements trimmed/escaped; non-arrays String(value) as-is (no escape, careful with untrusted input).
|
|
112
|
+
|
|
113
|
+
- **cd(dir: string)**: `void`
|
|
114
|
+
- Changes the working directory.
|
|
115
|
+
|
|
116
|
+
- **sleep(duration: string | number)**: `Promise<any>`
|
|
117
|
+
- Pauses execution for duration (e.g., '5s', 5000 ms).
|
|
118
|
+
|
|
119
|
+
- **retry(count: number, a: string | number | typeof expBackoff | Function, b?: Function)**: `Promise<any>`
|
|
120
|
+
- Retries callback up to `count` times. `a` can be delay, backoff generator, or callback (then `b` is callback).
|
|
121
|
+
|
|
122
|
+
- **readIn()**: `Promise<string>`
|
|
123
|
+
- Reads stdin as UTF-8, empty if TTY.
|
|
124
|
+
|
|
125
|
+
- **userIn(prompt: string)**: `{input: Promise<string | void>, abort: () => void}`
|
|
126
|
+
- Prompts user for input.
|
|
127
|
+
|
|
128
|
+
- **within(callback: Function)**: `Promise<any>`
|
|
129
|
+
- Executes callback in a new execution context.
|
|
130
|
+
|
|
131
|
+
- **expBackoff(max?: string, rand?: string)**: `Generator<number>`
|
|
132
|
+
- Yields exponential backoff intervals with jitter (max default '60s', rand '100ms').
|
|
133
|
+
|
|
134
|
+
- **parseArgs(args?: string[])**: `ArgsObject`
|
|
135
|
+
- Parses args: --key value, -k value; duplicates error; no =value or grouped shorts; _ for unnamed.
|
|
136
|
+
|
|
137
|
+
- **jsType(any: any)**: `string`
|
|
138
|
+
- Returns real JS type name (e.g., 'Array' for []).
|
|
139
|
+
|
|
140
|
+
- **hasProp(o: any, p: string)**: `boolean`
|
|
141
|
+
- Safely checks if `o` has own property `p` (handles null/undefined).
|
|
142
|
+
|
|
143
|
+
- **assert**: `typeof import('node:assert')`
|
|
144
|
+
- Node.js assert module.
|
|
145
|
+
|
|
146
|
+
- **Test**: Class - Minimal sync/async test framework (see below).
|
|
147
|
+
|
|
148
|
+
- **AsyncTracker**: Class - Tracks async operations using Node async_hooks (see below).
|
|
108
149
|
|
|
109
150
|
### SHDispatch Class
|
|
110
151
|
|
|
111
|
-
|
|
152
|
+
`new SHDispatch(cmd: string, options: SHOptions, prefix?: string)`
|
|
153
|
+
|
|
154
|
+
- **options(options?: SHOptions, prefix?: string)**: `SHDispatch`
|
|
155
|
+
- Configures execution options, merges with defaults (resets each call).
|
|
156
|
+
|
|
157
|
+
- **run(payload?: string)**: `Promise<string>`
|
|
158
|
+
- Executes command asynchronously, returns stdout. Rejects on error/timeout/kill.
|
|
112
159
|
|
|
113
|
-
- **
|
|
114
|
-
-
|
|
115
|
-
|
|
116
|
-
- **kill(signal?: string)**:
|
|
160
|
+
- **runSync(payload?: string)**: `import('child_process').SpawnSyncReturns<any>`
|
|
161
|
+
- Executes synchronously.
|
|
162
|
+
|
|
163
|
+
- **kill(signal?: string)**: `Promise<number[]>`
|
|
164
|
+
- Kills the process (and children if possible).
|
|
165
|
+
|
|
166
|
+
**Defaults/Semantics:**
|
|
167
|
+
- cwd: `process.cwd()`
|
|
168
|
+
- env: `process.env`
|
|
169
|
+
- shell: `'bash'` (use shell if string/true; no shell if false/undefined, uses /usr/bin/env -S)
|
|
170
|
+
- stdio: `['inherit', 'pipe', 'pipe']`
|
|
171
|
+
- timeout: `0` (no timeout)
|
|
172
|
+
- Prefix (e.g., 'set -euo pipefail') applied only with shell.
|
|
173
|
+
- Buffering: Up to 40MiB per stream, truncates with marker.
|
|
174
|
+
- Payload: Writes to stdin (forces pipe).
|
|
117
175
|
|
|
118
176
|
### Test Class
|
|
119
177
|
|
|
120
|
-
|
|
178
|
+
`new Test(quiet?: boolean)` - quiet: no auto-report.
|
|
179
|
+
|
|
180
|
+
- **syncTimeout(timeout: number)**: `void` - Timeout for sync tests (default 50ms, for async in sync).
|
|
181
|
+
|
|
182
|
+
- **add(description: string, callback: Function | AsyncFunction)**: `Test`
|
|
183
|
+
- Adds sync or async test. Throws if conditions fail.
|
|
184
|
+
|
|
185
|
+
- **run(execute?: number[])**: `Promise<Report>`
|
|
186
|
+
- Runs all or specified tests (by index).
|
|
121
187
|
|
|
122
|
-
- **
|
|
123
|
-
|
|
124
|
-
- **
|
|
125
|
-
|
|
126
|
-
|
|
188
|
+
- **unresolved()**: `void` - Checks/handles unresolved (internal?).
|
|
189
|
+
|
|
190
|
+
- **reset()**: `void` - Clears tests.
|
|
191
|
+
|
|
192
|
+
**Types:**
|
|
193
|
+
- `AsyncFunction = () => Promise<any>`
|
|
194
|
+
- `testDefinition = {description: string, callback: Function | AsyncFunction}`
|
|
195
|
+
- `testReport = {description: string, duration: number, executed: boolean}`
|
|
196
|
+
- `Report = {tests: number, duration: number, errors: number, executed: number}`
|
|
127
197
|
|
|
128
198
|
### AsyncTracker Class
|
|
129
199
|
|
|
130
|
-
|
|
200
|
+
`new AsyncTracker()`
|
|
201
|
+
|
|
202
|
+
- **enable(type?: SystemTypes)**: `void` - Starts tracking all or specific type.
|
|
203
|
+
|
|
204
|
+
- **disable()**: `void` - Stops tracking.
|
|
205
|
+
|
|
206
|
+
- **reset()**: `void` - Clears tracked items.
|
|
131
207
|
|
|
132
|
-
- **
|
|
133
|
-
- **disable()**: Disables tracking.
|
|
134
|
-
- **reset()**: Clears tracked items.
|
|
135
|
-
- **report(verbose?: boolean)**: Reports unresolved async operations.
|
|
136
|
-
- **getUnresolved(type?: SystemTypes)**: Gets unresolved items.
|
|
137
|
-
- **getTypeDescription(type: SystemTypes)**: Gets type description.
|
|
138
|
-
- **addCustomType(type: string, description: string)**: Adds custom type.
|
|
208
|
+
- **report(verbose?: boolean)**: `number` - Logs unresolved, returns count.
|
|
139
209
|
|
|
140
|
-
|
|
210
|
+
- **getUnresolved(type?: SystemTypes)**: `AsyncHookItem[]` - Gets unresolved items.
|
|
141
211
|
|
|
142
|
-
- **
|
|
143
|
-
|
|
144
|
-
- **
|
|
145
|
-
|
|
146
|
-
|
|
212
|
+
- **getTypeDescription(type: SystemTypes)**: `string` - Description of type.
|
|
213
|
+
|
|
214
|
+
- **addCustomType(type: string, description: string)**: `void` - Adds custom type desc.
|
|
215
|
+
|
|
216
|
+
**Types:**
|
|
217
|
+
- `AsyncHookItem = {key: number, type: string, triggerAsyncId: number, stack: string, resource: SystemTypes}`
|
|
218
|
+
- `SystemTypes` = "PROMISE" | "TIMEOUT" | ... (full Node async resource types)
|
|
219
|
+
|
|
220
|
+
### Other Types
|
|
221
|
+
|
|
222
|
+
- `ArgsObject = {[x: string]: string}` (with `_`: string[] for unnamed)
|
|
223
|
+
- `SpawnSyncResponse = {status: number|null, signal: string|null, output: (string|Buffer|null)[], pid: number, stdout: string|Buffer|null, stderr: string|Buffer|null}`
|
|
224
|
+
- `SHOptions` extends `SpawnOptions` & `{maxBuffer?: number, input?: string|Uint8Array|Buffer}`
|
|
225
|
+
- `StdioOption = "pipe" | "ignore" | "inherit" | number`
|
|
147
226
|
|
|
148
227
|
## Dependencies
|
|
149
228
|
|
|
@@ -151,4 +230,3 @@ Tracks async operations:
|
|
|
151
230
|
|
|
152
231
|
**Dev Dependencies:**
|
|
153
232
|
- @types/node: ^22.10.10
|
|
154
|
-
|
package/package.json
CHANGED
package/types/SH.d.ts
CHANGED
|
@@ -11,7 +11,22 @@ export type Shell = Function;
|
|
|
11
11
|
* A template-tag that returns an SHDispatch.
|
|
12
12
|
*/
|
|
13
13
|
export type SHTag = (pieces: TemplateStringsArray, ...args: unknown[]) => SHDispatch;
|
|
14
|
-
|
|
14
|
+
/**
|
|
15
|
+
* A template-tag that returns an SHDispatch.
|
|
16
|
+
* @typedef {(pieces: TemplateStringsArray, ...args: unknown[]) => SHDispatch} SHTag
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* SH template tag
|
|
20
|
+
*
|
|
21
|
+
* Interpolation rules:
|
|
22
|
+
* - Arrays: each element is String(x).trim(), with newlines/carriage returns/tabs escaped; if an element contains shell metacharacters or spaces, it is wrapped in single-quotes and internal single-quotes are escaped as '\''.
|
|
23
|
+
* - Non-array values: currently coerced with String(value) and inserted as-is (NOT shell-escaped). Be careful when interpolating untrusted input.
|
|
24
|
+
*
|
|
25
|
+
* @type {Shell & SHTag & defaultOptions}
|
|
26
|
+
* Returns an SHDispatch that can be configured via .options() and executed with .run() / .runSync().
|
|
27
|
+
* @returns {SHDispatch}
|
|
28
|
+
*/
|
|
29
|
+
export const SH: Shell & SHTag & import("./SHDispatch.js").SHOptions;
|
|
15
30
|
/**
|
|
16
31
|
* Change working directory
|
|
17
32
|
* @param {string} dir
|
|
@@ -172,5 +187,12 @@ export function hasProp(o: any, p: string): boolean;
|
|
|
172
187
|
import Test from './Test.js';
|
|
173
188
|
import assert from 'node:assert';
|
|
174
189
|
import AsyncTracker from './AsyncTracker.js';
|
|
190
|
+
/**
|
|
191
|
+
* bash escape a string suitable as an argument on the commandline
|
|
192
|
+
* for javascript code
|
|
193
|
+
* @param {string} x
|
|
194
|
+
* @returns {string}
|
|
195
|
+
*/
|
|
196
|
+
export function bashEscape(x: string): string;
|
|
175
197
|
import SHDispatch from './SHDispatch.js';
|
|
176
198
|
export { Test, assert, AsyncTracker };
|
package/types/SHDispatch.d.ts
CHANGED
|
@@ -69,17 +69,34 @@ export type SHOptions = {
|
|
|
69
69
|
};
|
|
70
70
|
export type StdioOption = ("pipe" | "ignore" | "inherit" | number);
|
|
71
71
|
export type StdioOptions = Array<StdioOption> | StdioOption;
|
|
72
|
+
/**
|
|
73
|
+
* SHOptions — effective defaults and semantics used by SHDispatch/SHExecute
|
|
74
|
+
*
|
|
75
|
+
* Defaults:
|
|
76
|
+
* - cwd: process.cwd()
|
|
77
|
+
* - env: process.env
|
|
78
|
+
* - shell: 'bash' (string). If a string, that shell is used. If true, 'bash' is used. If false/undefined, no shell is used.
|
|
79
|
+
* - stdio: ['inherit', 'pipe', 'pipe'] — inherit stdin, capture stdout/stderr
|
|
80
|
+
* - timeout: 0 — no timeout
|
|
81
|
+
* - maxBuffer?: number — optional (bytes per stream). Passed through to SHExecute.
|
|
82
|
+
*
|
|
83
|
+
* Notes:
|
|
84
|
+
* - The prefix (see options(prefix)) is only applied when a shell is used; it is ignored in no-shell mode.
|
|
85
|
+
* - Each call to options() resets to the defaults and merges the provided options; it does not accumulate from prior calls.
|
|
86
|
+
*/
|
|
72
87
|
declare class SHDispatch {
|
|
73
88
|
/**
|
|
74
89
|
* @param {string} cmd - cmd to execute
|
|
90
|
+
* @param {SHOptions} options
|
|
91
|
+
* @param {string} [prefix] - command prefix e.g (default) '/usr/bin/env'
|
|
75
92
|
*/
|
|
76
|
-
constructor(cmd: string);
|
|
93
|
+
constructor(cmd: string, options: SHOptions, prefix?: string);
|
|
77
94
|
/**
|
|
78
|
-
* @param {
|
|
95
|
+
* @param {SHOptions} [options]
|
|
79
96
|
* @param {string} [prefix] - command prefix e.g (default) '/usr/bin/env'
|
|
80
97
|
* @returns {SHDispatch}
|
|
81
98
|
*/
|
|
82
|
-
options(options
|
|
99
|
+
options(options?: SHOptions, prefix?: string): SHDispatch;
|
|
83
100
|
/**
|
|
84
101
|
* @param {string} [payload]
|
|
85
102
|
* @returns {Promise<string>}
|