xsh 1.1.6 → 1.1.7

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
@@ -28,8 +28,6 @@ const xsh = require("xsh");
28
28
  xsh.exec("echo hello");
29
29
  ```
30
30
 
31
- The shell commands under `xsh.$` come from [shelljs](https://www.npmjs.com/package/shelljs).
32
-
33
31
  ## API
34
32
 
35
33
  ### `Promise`
@@ -63,7 +61,10 @@ Both return the string `"echo hello"`.
63
61
  xsh.exec(shellCommand, [options], [callback] );
64
62
  ```
65
63
 
66
- Use [shelljs `exec`] to execute `shellCommand` in `async` mode.
64
+ Execute `shellCommand` asynchronously with Node.js
65
+ [`child_process.exec`](https://nodejs.org/api/child_process.html#child_processexeccommand-options-callback).
66
+ `xsh.exec` adds flexible command fragments, a callback/error shape, and a thenable result that
67
+ also exposes the child process and its output streams.
67
68
 
68
69
  #### Arguments
69
70
 
@@ -72,8 +73,9 @@ Use [shelljs `exec`] to execute `shellCommand` in `async` mode.
72
73
  - `options` - optional `options`
73
74
 
74
75
  - If it's either `true` or `false`, it sets `silent` flag for output to console.
75
- - It can also be an object that's passed to [NodeJS exec](https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback).
76
- - For example, it can be `{silent: true}`
76
+ - It can also be an object with `silent` and any option accepted by
77
+ [Node.js `exec`](https://nodejs.org/api/child_process.html#child_processexeccommand-options-callback).
78
+ - `maxBuffer` defaults to 20 MiB.
77
79
  - This can be the first, last, or second to last (if last is the callback) argument.
78
80
 
79
81
  - `callback` - optional, if provided, it will be called as follows:
@@ -161,25 +163,20 @@ If `path` doesn't exist in `process.env.PATH` then it's added to the end.
161
163
 
162
164
  If you don't want to operate on `process.env` you can pass in a second argument that's either an object or a string that's the path to change.
163
165
 
164
- ### [`$`](#)
165
-
166
- An instance of [shelljs].
166
+ ### [pushd](#pushd) / [popd](#popd)
167
167
 
168
168
  ```js
169
- const xsh = require("xsh");
170
- xsh.$.cd("/tmp");
169
+ xsh.pushd(dir);
170
+ // ...
171
+ xsh.popd();
171
172
  ```
172
173
 
173
- [shelljs `exec`]: http://documentup.com/shelljs/shelljs#execcommand--options--callback
174
-
175
- [shelljs]: https://github.com/shelljs/shelljs
176
-
177
-
174
+ `pushd` saves `process.cwd()` on a stack, then `chdir`s into `dir`, returning the new cwd.
175
+ `popd` `chdir`s back to the directory most recently saved by `pushd`, returning it. `popd`
176
+ throws if the stack is empty.
178
177
 
179
178
  [npm-image]: https://badge.fury.io/js/xsh.svg
180
179
 
181
180
  [npm-url]: https://npmjs.org/package/xsh
182
181
 
183
182
 
184
-
185
-
package/dist/exec.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ChildProcess } from "node:child_process";
1
+ import { type ChildProcess } from "node:child_process";
2
2
  export interface ExecOutput {
3
3
  stdout: string;
4
4
  stderr: string;
@@ -9,7 +9,7 @@ export interface ExecError extends Error {
9
9
  }
10
10
  export type ExecCallback = (err: ExecError | null, output: ExecOutput) => void;
11
11
  /**
12
- * Options passed through to shelljs `exec` (`async: true` is always set).
12
+ * Options passed through to Node.js `child_process.exec`.
13
13
  * A plain boolean is shorthand for `{ silent: boolean }`.
14
14
  */
15
15
  export interface ExecOptions {
@@ -31,13 +31,13 @@ export interface ExecResult {
31
31
  stderr: ChildProcess["stderr"];
32
32
  }
33
33
  /**
34
- * Execute a shell command with shelljs `exec` in async mode.
34
+ * Execute a shell command with Node.js `child_process.exec`.
35
35
  *
36
36
  * Arguments can be any mix of command fragments (strings / arrays of strings,
37
37
  * joined with `" "`), one options object or boolean (silent shorthand) as the
38
38
  * first, last, or second to last argument, and a callback as the last argument.
39
39
  *
40
- * Returns the shelljs child process when a callback is given, else an
40
+ * Returns the child process when a callback is given, else an
41
41
  * {@link ExecResult} thenable.
42
42
  */
43
43
  export declare function exec(...args: Array<ExecFragment | ExecOptions | boolean>): ExecResult;
package/dist/exec.js CHANGED
@@ -1,6 +1,7 @@
1
- import shell from "shelljs";
2
1
  import assert from "node:assert";
2
+ import { exec as childExec } from "node:child_process";
3
3
  import { util } from "./util.js";
4
+ const DEFAULT_MAX_BUFFER = 20 * 1024 * 1024;
4
5
  export function exec(...args) {
5
6
  const error = (cmd, code, output) => {
6
7
  const err = new Error(`shell cmd '${cmd}' exit code ${code}`);
@@ -53,11 +54,27 @@ export function exec(...args) {
53
54
  s = " ";
54
55
  return a;
55
56
  }, "");
56
- const doExec = (xcb) => shell.exec(cmd, Object.assign({ async: true }, options), (code, stdout, stderr) => {
57
- const output = { stdout, stderr };
58
- const err = code === 0 ? null : error(cmd, code, output);
59
- xcb(err, output);
60
- });
57
+ const doExec = (xcb) => {
58
+ const { silent = false, async: _async, fatal: _fatal, ...execOptions } = options;
59
+ const child = childExec(cmd, Object.assign({
60
+ cwd: process.cwd(),
61
+ env: process.env,
62
+ maxBuffer: DEFAULT_MAX_BUFFER,
63
+ encoding: "utf8"
64
+ }, execOptions), (execErr, stdout, stderr) => {
65
+ const output = { stdout, stderr };
66
+ const code = execErr ? execErr.code : 0;
67
+ /* v8 ignore next -- @preserve Node execution errors normally provide a code. */
68
+ const exitCode = code === undefined ? 1 : code;
69
+ const err = exitCode === 0 ? null : error(cmd, exitCode, output);
70
+ xcb(err, output);
71
+ });
72
+ if (!silent) {
73
+ child.stdout?.pipe(process.stdout);
74
+ child.stderr?.pipe(process.stderr);
75
+ }
76
+ return child;
77
+ };
61
78
  if (cb) {
62
79
  return doExec(cb);
63
80
  }
package/dist/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
- import shell from "shelljs";
2
1
  import { exec } from "./exec.ts";
3
2
  import { env } from "./env.ts";
4
3
  import { envPath } from "./env-path.ts";
5
4
  import { mkCmd } from "./mkcmd.ts";
6
5
  import { pathCwd } from "./path-cwd.ts";
7
6
  import { pathCwdNm } from "./path-cwd-nm.ts";
7
+ import { pushd, popd } from "./pushd.ts";
8
8
  export type { ExecOutput, ExecError, ExecCallback, ExecOptions, ExecFragment, ExecArg, ExecResult } from "./exec.ts";
9
9
  export type { EnvContainer } from "./env-path.ts";
10
10
  export interface Xsh {
@@ -14,13 +14,12 @@ export interface Xsh {
14
14
  mkCmd: typeof mkCmd;
15
15
  pathCwd: typeof pathCwd;
16
16
  pathCwdNm: typeof pathCwdNm;
17
- /** the shelljs instance xsh uses */
18
- $: typeof shell;
17
+ pushd: typeof pushd;
18
+ popd: typeof popd;
19
19
  /** Promise implementation used by exec - set to null to restore native Promise */
20
20
  Promise: PromiseConstructor;
21
21
  }
22
22
  declare const xsh: Xsh;
23
- export { exec, env, envPath, mkCmd, pathCwd, pathCwdNm };
24
- export declare const $: typeof shell;
23
+ export { exec, env, envPath, mkCmd, pathCwd, pathCwdNm, pushd, popd };
25
24
  export default xsh;
26
25
  export { xsh as "module.exports" };
package/dist/index.js CHANGED
@@ -1,4 +1,3 @@
1
- import shell from "shelljs";
2
1
  import { util } from "./util.js";
3
2
  import { exec } from "./exec.js";
4
3
  import { env } from "./env.js";
@@ -6,6 +5,7 @@ import { envPath } from "./env-path.js";
6
5
  import { mkCmd } from "./mkcmd.js";
7
6
  import { pathCwd } from "./path-cwd.js";
8
7
  import { pathCwdNm } from "./path-cwd-nm.js";
8
+ import { pushd, popd } from "./pushd.js";
9
9
  const xsh = {
10
10
  exec,
11
11
  env,
@@ -13,7 +13,8 @@ const xsh = {
13
13
  mkCmd,
14
14
  pathCwd,
15
15
  pathCwdNm,
16
- $: shell
16
+ pushd,
17
+ popd
17
18
  };
18
19
  Object.defineProperty(xsh, "Promise", {
19
20
  set: p => {
@@ -21,8 +22,7 @@ Object.defineProperty(xsh, "Promise", {
21
22
  },
22
23
  get: () => util.Promise
23
24
  });
24
- export { exec, env, envPath, mkCmd, pathCwd, pathCwdNm };
25
- export const $ = shell;
25
+ export { exec, env, envPath, mkCmd, pathCwd, pathCwdNm, pushd, popd };
26
26
  export default xsh;
27
27
  // make `require("xsh")` in CJS consumers (node >=22.12 require(esm)) return the
28
28
  // xsh object itself - same shape as the historical module.exports - instead of
@@ -0,0 +1,4 @@
1
+ /** Save the current working directory on a stack, then `chdir` into `dir`. */
2
+ export declare function pushd(dir: string): string;
3
+ /** `chdir` back to the directory most recently saved by {@link pushd}. */
4
+ export declare function popd(): string;
package/dist/pushd.js ADDED
@@ -0,0 +1,15 @@
1
+ import assert from "node:assert";
2
+ const stack = [];
3
+ /** Save the current working directory on a stack, then `chdir` into `dir`. */
4
+ export function pushd(dir) {
5
+ stack.push(process.cwd());
6
+ process.chdir(dir);
7
+ return process.cwd();
8
+ }
9
+ /** `chdir` back to the directory most recently saved by {@link pushd}. */
10
+ export function popd() {
11
+ const dir = stack.pop();
12
+ assert(dir !== undefined, "xsh.popd: directory stack is empty");
13
+ process.chdir(dir);
14
+ return dir;
15
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xsh",
3
- "version": "1.1.6",
3
+ "version": "1.1.7",
4
4
  "description": "Some random NodeJS helper functions for shell execution",
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.ts",
@@ -39,22 +39,17 @@
39
39
  "keywords": [
40
40
  "shell",
41
41
  "exec",
42
- "shelljs",
43
42
  "env",
44
43
  "PATH"
45
44
  ],
46
45
  "author": "Joel Chen",
47
46
  "license": "Apache-2.0",
48
- "dependencies": {
49
- "shelljs": "^0.10.0"
50
- },
51
47
  "devDependencies": {
52
48
  "@types/node": "^26.4.1",
53
- "@types/shelljs": "^0.10.0",
54
49
  "@vitest/coverage-v8": "^5.0.0",
55
- "aveazul": "^2.1.6",
56
- "publish-util": "^3.1.5",
57
- "run-verify": "^2.1.6",
50
+ "aveazul": "^2.1.7",
51
+ "publish-util": "^3.1.6",
52
+ "run-verify": "^2.1.7",
58
53
  "typescript": "^7.0.2",
59
54
  "vite": "^8.2.2",
60
55
  "vitest": "^5.0.0"