@j-o-r/sh 1.0.3 → 1.0.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.
package/README.md CHANGED
@@ -59,7 +59,7 @@ The `SH` method accepts a template literal string enclosed in backticks as its a
59
59
  ### Additional Utilities
60
60
 
61
61
  The module also provides additional utilities for common tasks:
62
-
62
+ - `args(command)`: Parsing a command from a string into an arguments array
63
63
  - `cd(dir)`: Change the working directory.
64
64
  - `sleep(duration)`: Pause execution for a specified duration.
65
65
  - `retry(count, interval, callback)`: Retry a command a specified number of times with an optional interval.
@@ -92,6 +92,13 @@ This class is returned by the `SH` function. Here's a summary of its methods and
92
92
  console.log(res);
93
93
  ```
94
94
 
95
+ - Create a command from a string
96
+ ```javascript
97
+ const command = args("uname -r");
98
+ const content = await SH`${command}`.run();
99
+ console.log(content);
100
+ ```
101
+
95
102
  - Async context with multiple commands and sleep:
96
103
  ```javascript
97
104
  within(async () => {
package/lib/SH.js CHANGED
@@ -113,7 +113,48 @@ const SH = new Proxy(function(pieces, ...args) {
113
113
  }
114
114
  return new SHDispatch(cmd);
115
115
  }, {});
116
+ /**
117
+ * Splits a command string into an array of arguments, handling quoted strings.
118
+ * This fixes a problem when a command is like this: SH`${command}`
119
+ *
120
+ * @param {string} command - The command string to split.
121
+ * @returns {string[]} - The array of command arguments.
122
+ */
123
+ const args = (command) => {
124
+ const args = [];
125
+ let currentArg = '';
126
+ let insideQuotes = false;
127
+ let quoteChar = null;
128
+
129
+ for (let i = 0; i < command.length; i++) {
130
+ const char = command[i];
116
131
 
132
+ if (char === '"' || char === "'") {
133
+ if (insideQuotes && quoteChar === char && command[i - 1] !== '\\') {
134
+ insideQuotes = false;
135
+ quoteChar = null;
136
+ } else if (!insideQuotes) {
137
+ insideQuotes = true;
138
+ quoteChar = char;
139
+ } else {
140
+ currentArg += char;
141
+ }
142
+ } else if (char === ' ' && !insideQuotes) {
143
+ if (currentArg.length > 0) {
144
+ args.push(currentArg);
145
+ currentArg = '';
146
+ }
147
+ } else {
148
+ currentArg += char;
149
+ }
150
+ }
151
+
152
+ if (currentArg.length > 0) {
153
+ args.push(currentArg);
154
+ }
155
+
156
+ return args.map(arg => arg.replace(/\\(['"])/g, '$1'));
157
+ }
117
158
  /**
118
159
  * Create a async context in an sync block
119
160
  * @param {function} callback - async function
@@ -245,6 +286,7 @@ function* expBackoff(max = '60s', rand = '100ms') {
245
286
  }
246
287
  export {
247
288
  SH,
289
+ args,
248
290
  cd,
249
291
  sleep,
250
292
  retry,
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.0.3",
5
+ "version": "1.0.4",
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",
@@ -13,7 +13,7 @@
13
13
  "test": "test/sh.js",
14
14
  "publish": "npm run release && npm publish --access public",
15
15
  "release": "npm pack --pack-destination=release",
16
- "types": "tsc lib/*.js --module nodenext --moduleResolution nodenext --declaration --allowJs --emitDeclarationOnly --outDir types/",
16
+ "types": "tsc",
17
17
  "clear:types": "rm types/*.d.ts"
18
18
  },
19
19
  "repository": {
@@ -22,10 +22,7 @@
22
22
  },
23
23
  "license": "Apache License, Version 2.0",
24
24
  "dependencies": {},
25
- "devDependencies": {
26
- "@types/node": "^20.8.10",
27
- "uvu": "^0.5.6"
28
- },
25
+ "devDependencies": {},
29
26
  "bugs": {
30
27
  "url": "https://codeberg.org/duin/sh/issues"
31
28
  },
@@ -49,4 +46,4 @@
49
46
  "process-promise",
50
47
  "process-output"
51
48
  ]
52
- }
49
+ }
package/types/SH.d.ts CHANGED
@@ -6,6 +6,14 @@ export type Shell = Function;
6
6
  export const SH: Shell & {
7
7
  (pieces: TemplateStringsArray, ...args: any): SHDispatch;
8
8
  };
9
+ /**
10
+ * Splits a command string into an array of arguments, handling quoted strings.
11
+ * This fixes a problem when a command is like this: SH`${command}`
12
+ *
13
+ * @param {string} command - The command string to split.
14
+ * @returns {string[]} - The array of command arguments.
15
+ */
16
+ export function args(command: string): string[];
9
17
  /**
10
18
  * Change working directory
11
19
  * @param {string} dir
@@ -39,7 +47,7 @@ export function sleep(duration: string | number): Promise<any>;
39
47
  * // Retry a command 3 times with irregular intervals using exponential backoff
40
48
  * const p = await retry(3, expBackoff(), () => SH`curl -s https://flipwrsi`);
41
49
  */
42
- export function retry(count: number, a: string | typeof expBackoff | Function, b?: Function): Promise<any>;
50
+ export function retry(count: number, a: string | typeof expBackoff | Function, b?: Function | undefined): Promise<any>;
43
51
  /**
44
52
  * This function reads the standard input (stdin) from the current process.
45
53
  * @example
@@ -67,5 +75,5 @@ export function within(callback: Function): void;
67
75
  * @param {string} [rand='100ms'] - The maximum random jitter time in a human-readable format (e.g., '100ms' for 100 milliseconds).
68
76
  * @yields {number} The backoff time in milliseconds.
69
77
  */
70
- export function expBackoff(max?: string, rand?: string): Generator<number, void, unknown>;
78
+ export function expBackoff(max?: string | undefined, rand?: string | undefined): Generator<number, void, unknown>;
71
79
  import SHDispatch from './SHDispatch.js';
@@ -32,29 +32,29 @@ export type SHOptions = {
32
32
  /**
33
33
  * - The current working directory.
34
34
  */
35
- cwd?: string;
35
+ cwd?: string | undefined;
36
36
  /**
37
37
  * - The environment variables.
38
38
  */
39
- env?: NodeJS.ProcessEnv;
39
+ env?: any;
40
40
  /**
41
41
  * - The shell to use for execution.
42
42
  */
43
- shell?: string;
43
+ shell?: string | undefined;
44
44
  /**
45
45
  * - The prefix commands to ensure a safe execution environment. e.g: prefix: 'set -euo pipefail;/usr/bin/env',
46
46
  */
47
- prefix?: string;
47
+ prefix?: string | undefined;
48
48
  /**
49
49
  * - The stdio configuration.
50
50
  */
51
- stdio?: StdioOptions | StdioOption;
51
+ stdio?: number | "pipe" | "ignore" | "inherit" | StdioOption[] | undefined;
52
52
  /**
53
53
  * - default 20000: a timeout error is triggerd when a process execution time is exceeded, 0 is no timeout
54
54
  */
55
- timeout?: number;
55
+ timeout?: number | undefined;
56
56
  };
57
- export type StdioOption = ('pipe' | 'ignore' | 'inherit' | number);
57
+ export type StdioOption = ("pipe" | "ignore" | "inherit" | number);
58
58
  export type StdioOptions = Array<StdioOption> | StdioOption;
59
59
  declare class SHDispatch {
60
60
  /**
@@ -70,13 +70,13 @@ declare class SHDispatch {
70
70
  * @param {string} [payload]
71
71
  * @returns {Promise<string>}
72
72
  */
73
- run(payload?: string): Promise<string>;
73
+ run(payload?: string | undefined): Promise<string>;
74
74
  /**
75
75
  * Works for screen takeovers like editors
76
76
  * @param {string} [payload]
77
77
  * @returns {SpawnSyncResponse}
78
78
  */
79
- runSync(payload?: string): SpawnSyncResponse;
79
+ runSync(payload?: string | undefined): SpawnSyncResponse;
80
80
  kill(): Promise<void>;
81
81
  #private;
82
82
  }
@@ -1,4 +1,3 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
1
  export default SHExecute;
3
2
  declare class SHExecute {
4
3
  /**
@@ -10,12 +9,12 @@ declare class SHExecute {
10
9
  * @param {string} [payload] - data to write
11
10
  * @retuns {Promise<object>}
12
11
  */
13
- runSync(payload?: string): import("child_process").SpawnSyncReturns<Buffer>;
12
+ runSync(payload?: string | undefined): any;
14
13
  /**
15
14
  * @param {string} [payload] - data to write
16
15
  * @retuns {Promise<string>}
17
16
  */
18
- run(payload?: string): Promise<any>;
17
+ run(payload?: string | undefined): Promise<any>;
19
18
  /**
20
19
  * @returns {Promise<number[]>}
21
20
  */