@j-o-r/sh 1.1.18 → 1.1.20

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.
Files changed (3) hide show
  1. package/lib/SH.js +61 -1
  2. package/package.json +1 -1
  3. package/types/SH.d.ts +15 -1
package/lib/SH.js CHANGED
@@ -27,6 +27,7 @@
27
27
  // Modified by: jorrit.duin+sh[AT]gmail.com
28
28
  /** @type {assert} */
29
29
  import assert from 'node:assert';
30
+ import readline from 'node:readline/promises';
30
31
  import SHDispatch from './SHDispatch.js';
31
32
  import Test from './Test.js'
32
33
  import AsyncTracker from './AsyncTracker.js'
@@ -106,6 +107,7 @@ const SH = new Proxy(function(pieces, ...args) {
106
107
  let s;
107
108
 
108
109
  if (Array.isArray(args[i])) {
110
+ // @ts-ignore
109
111
  s = args[i].map(/** @param {string} x */(x) => {
110
112
  // Trim every element
111
113
  let str = String(x).trim();
@@ -147,7 +149,7 @@ const within = async (callback) => {
147
149
  * This function reads the standard input (stdin) from the current process.
148
150
  * @returns {Promise<string>}
149
151
  * @example
150
- * const content = await stdin();
152
+ * const content = await readIn();
151
153
  */
152
154
  const readIn = async () => {
153
155
  if (process.stdin.isTTY) return ''; // nothing was piped
@@ -159,6 +161,63 @@ const readIn = async () => {
159
161
  return buf;
160
162
  }
161
163
 
164
+
165
+ /**
166
+ * Get user input from the command line (stdin)
167
+ * void when input has been aborted
168
+ * @param {string} prompt - prompt or question
169
+ * @returns {{input: Promise<string|void>, abort: function(): void}}
170
+ * @example
171
+ * const user = userIn('Question: ');
172
+ * const content = await user.input
173
+ * // user.abort()
174
+ */
175
+ const userIn = (prompt) => {
176
+ let resolvePromise;
177
+ const input = new Promise((resolve) => { resolvePromise = resolve; });
178
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
179
+ let buffer = '';
180
+ let timer;
181
+ /** @param {string} chunk */
182
+ const onData = (chunk) => {
183
+ if (chunk.length > 4 && chunk.includes('\n')) {
184
+ clearTimeout(timer);
185
+ timer = setTimeout(resolveFunc, 50);
186
+ }
187
+ };
188
+
189
+ const resolveFunc = () => {
190
+ let fullText = buffer;
191
+ if (rl.line) fullText += rl.line;
192
+ cleanup();
193
+ resolvePromise(fullText);
194
+ };
195
+
196
+ const cleanup = () => {
197
+ process.stdin.removeListener('data', onData);
198
+ rl.removeAllListeners('line');
199
+ clearTimeout(timer);
200
+ rl.close();
201
+ };
202
+
203
+ rl.on('line', (line) => {
204
+ buffer += line + '\n';
205
+ clearTimeout(timer);
206
+ timer = setTimeout(resolveFunc, 50);
207
+ });
208
+ process.stdin.on('data', onData);
209
+
210
+ rl.setPrompt(prompt);
211
+ rl.prompt();
212
+
213
+ return {
214
+ input,
215
+ abort: () => {
216
+ cleanup();
217
+ resolvePromise();
218
+ }
219
+ };
220
+ };
162
221
  /**
163
222
  * Retries a given asynchronous function a specified number of times with optional delays between attempts.
164
223
  *
@@ -308,6 +367,7 @@ export {
308
367
  sleep,
309
368
  retry,
310
369
  readIn,
370
+ userIn,
311
371
  within,
312
372
  expBackoff,
313
373
  parseArgs,
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@j-o-r/sh",
3
3
  "author": "Jorrit Duin <j-o-r@duin.work>",
4
4
  "type": "module",
5
- "version": "1.1.18",
5
+ "version": "1.1.20",
6
6
  "description": "Execute shell commands on Linux-based systems from javascript",
7
7
  "main": "lib/SH.js",
8
8
  "types": "types/SH.d.ts",
package/types/SH.d.ts CHANGED
@@ -57,10 +57,24 @@ export function retry(count: number, a: string | number | typeof expBackoff | Fu
57
57
  * This function reads the standard input (stdin) from the current process.
58
58
  * @returns {Promise<string>}
59
59
  * @example
60
- * const content = await stdin();
60
+ * const content = await readIn();
61
61
  */
62
62
  export function readIn(): Promise<string>;
63
63
  /**
64
+ * Get user input from the command line (stdin)
65
+ * void when input has been aborted
66
+ * @param {string} prompt - prompt or question
67
+ * @returns {{input: Promise<string|void>, abort: function(): void}}
68
+ * @example
69
+ * const user = userIn('Question: ');
70
+ * const content = await user.input
71
+ * // user.abort()
72
+ */
73
+ export function userIn(prompt: string): {
74
+ input: Promise<string | void>;
75
+ abort: () => void;
76
+ };
77
+ /**
64
78
  * Create a async/sync context in new execution callstack
65
79
  * @param {function} callback - async/sync function
66
80
  * @example