dollar-shell 1.1.9 → 1.1.11
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/AGENTS.md +63 -34
- package/CLAUDE.md +3 -0
- package/CONTRIBUTING.md +34 -0
- package/README.md +32 -6
- package/llms-full.txt +6 -2
- package/llms.txt +64 -13
- package/package.json +16 -3
- package/src/bq-shell.js +5 -3
- package/src/bq-spawn.js +5 -3
- package/src/index.js +27 -19
- package/src/shell/unix.js +0 -2
- package/src/shell/windows.js +0 -2
- package/src/spawn/bun.js +20 -14
- package/src/spawn/deno.js +19 -8
- package/src/spawn/node.js +18 -8
- package/src/utils.js +1 -4
package/AGENTS.md
CHANGED
|
@@ -1,12 +1,54 @@
|
|
|
1
|
-
#
|
|
1
|
+
# AGENTS.md — dollar-shell
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> `dollar-shell` is a micro-library for running OS and shell commands from JavaScript/TypeScript using template tag functions. It works on Node, Deno, and Bun with the same API. All streams are web streams. Zero dependencies.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
For detailed usage docs and API references see the [wiki](https://github.com/uhop/dollar-shell/wiki).
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Setup
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
```bash
|
|
10
|
+
git clone --recursive git@github.com:uhop/dollar-shell.git
|
|
11
|
+
cd dollar-shell
|
|
12
|
+
npm install
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The wiki is a git submodule in `wiki/`.
|
|
16
|
+
|
|
17
|
+
## Commands
|
|
18
|
+
|
|
19
|
+
- **Test (Node):** `npm test` (runs `tape6 --flags FO`)
|
|
20
|
+
- **Test (Bun):** `npm run test:bun`
|
|
21
|
+
- **Test (Deno):** `npm run test:deno`
|
|
22
|
+
- **TypeScript check:** `npm run ts-check` (`tsc --noEmit`)
|
|
23
|
+
- **Lint:** `npm run lint` (Prettier check)
|
|
24
|
+
- **Lint fix:** `npm run lint:fix` (Prettier write)
|
|
25
|
+
|
|
26
|
+
## Project structure
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
dollar-shell/
|
|
30
|
+
├── package.json # Package config
|
|
31
|
+
├── tsconfig.json # TypeScript config (noEmit check only)
|
|
32
|
+
├── src/ # Source code
|
|
33
|
+
│ ├── index.js # Main entry point, wires everything together
|
|
34
|
+
│ ├── index.d.ts # TypeScript declarations for the full public API
|
|
35
|
+
│ ├── bq-spawn.js # Template tag factory for spawn-based functions ($, $$)
|
|
36
|
+
│ ├── bq-shell.js # Template tag factory for shell-based functions ($sh, shell)
|
|
37
|
+
│ ├── utils.js # Shared utilities (raw, isWindows, winCmdEscape, etc.)
|
|
38
|
+
│ ├── spawn/ # Runtime-specific Subprocess implementations
|
|
39
|
+
│ │ ├── node.js # Node.js: uses child_process + stream.Writable/Readable
|
|
40
|
+
│ │ ├── deno.js # Deno: uses Deno.Command
|
|
41
|
+
│ │ └── bun.js # Bun: uses Bun.spawn
|
|
42
|
+
│ └── shell/ # Platform-specific shell escaping and command building
|
|
43
|
+
│ ├── unix.js # Unix: single-quote escaping, $SHELL detection
|
|
44
|
+
│ └── windows.js # Windows: cmd.exe and PowerShell escaping
|
|
45
|
+
├── tests/ # Automated tests (tape-six)
|
|
46
|
+
├── tests/manual/ # Manual verification scripts
|
|
47
|
+
├── ts-check/ # TypeScript usage examples (compiled but not executed)
|
|
48
|
+
└── wiki/ # GitHub wiki documentation (git submodule)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Quick reference
|
|
10
52
|
|
|
11
53
|
```js
|
|
12
54
|
import $, {$$, $sh, shell, sh, spawn} from 'dollar-shell';
|
|
@@ -24,45 +66,32 @@ await sp.exited;
|
|
|
24
66
|
await $sh`ls -l . | grep LICENSE | wc`;
|
|
25
67
|
|
|
26
68
|
// Stream pipelines
|
|
27
|
-
$.from`ls -l
|
|
28
|
-
.pipeThrough($.io`grep LIC`)
|
|
29
|
-
.pipeTo($.to({stdout: 'inherit'})`wc`);
|
|
69
|
+
$.from`ls -l .`.pipeThrough($.io`grep LIC`).pipeTo($.to({stdout: 'inherit'})`wc`);
|
|
30
70
|
|
|
31
71
|
// Custom options (returns new tag function with updated defaults)
|
|
32
72
|
const $verbose = $({stdout: 'inherit', stderr: 'inherit'});
|
|
33
73
|
await $verbose`ls -l .`;
|
|
34
74
|
```
|
|
35
75
|
|
|
36
|
-
##
|
|
76
|
+
## Code style
|
|
37
77
|
|
|
38
|
-
-
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
- `src/utils.js` — Shared utilities (`raw`, `isWindows`, `winCmdEscape`, etc.)
|
|
43
|
-
- `src/spawn/node.js`, `src/spawn/deno.js`, `src/spawn/bun.js` — Runtime-specific Subprocess implementations
|
|
44
|
-
- `src/shell/unix.js`, `src/shell/windows.js` — Platform-specific shell escaping and command building
|
|
78
|
+
- **ES modules** throughout (`"type": "module"` in package.json).
|
|
79
|
+
- **No transpilation** — code runs directly in all target runtimes.
|
|
80
|
+
- **Prettier** for formatting — run `npm run lint:fix` before committing.
|
|
81
|
+
- Imports at the top of files, using `import` syntax.
|
|
45
82
|
|
|
46
|
-
##
|
|
83
|
+
## Architecture
|
|
47
84
|
|
|
48
|
-
-
|
|
49
|
-
-
|
|
85
|
+
- `src/index.js` is the main entry point. It dynamically imports the correct `spawn` implementation (Node/Deno/Bun) and the correct `shell` implementation (Unix/Windows) at import time.
|
|
86
|
+
- All tag functions (`$`, `$$`, `$sh`, `shell`) are built by factory functions in `bq-spawn.js` and `bq-shell.js`.
|
|
87
|
+
- **Tag function + options pattern**: calling a tag function with an options object returns a new tag function with updated defaults while preserving `.from`, `.to`, `.io`, `.through` properties.
|
|
88
|
+
- **raw()**: wraps a value to bypass escaping (shell) or argument splitting (spawn).
|
|
50
89
|
- **Platform detection**: `isWindows` boolean is exported. Runtime detection (Node/Deno/Bun) happens at import via dynamic imports.
|
|
51
90
|
|
|
52
|
-
##
|
|
53
|
-
|
|
54
|
-
- Import `$` as the default export for simple command execution.
|
|
55
|
-
- Use `$sh` when you need shell features (pipes, aliases, globbing).
|
|
56
|
-
- Use `$$` or `shell` when you need the full `Subprocess` object (kill, streams, exit code).
|
|
57
|
-
- Use `.from`, `.to`, `.io`/`.through` for stream pipelines with web streams.
|
|
58
|
-
- Always `await` the result of `$` and `$sh` (they return promises).
|
|
59
|
-
- `$$` and `shell` return `Subprocess` synchronously — use `await sp.exited` to wait.
|
|
60
|
-
|
|
61
|
-
## When Modifying This Package
|
|
91
|
+
## Key conventions
|
|
62
92
|
|
|
63
|
-
-
|
|
64
|
-
-
|
|
65
|
-
-
|
|
66
|
-
-
|
|
67
|
-
- Tests are in `tests/` (automated) and `tests/manual/` (manual verification).
|
|
93
|
+
- Do not add dependencies — the library is intentionally zero-dependency.
|
|
94
|
+
- All public API is exported from `src/index.js` and typed in `src/index.d.ts`. Keep them in sync.
|
|
95
|
+
- Wiki documentation lives in the `wiki/` submodule — update it alongside code changes.
|
|
96
|
+
- Tests are in `tests/` (automated, tape-six) and `tests/manual/` (manual verification scripts).
|
|
68
97
|
- TypeScript usage examples are in `ts-check/` — they are compiled but not executed during `npm run ts-check`.
|
package/CLAUDE.md
ADDED
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Contributing to dollar-shell
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing!
|
|
4
|
+
|
|
5
|
+
## Getting started
|
|
6
|
+
|
|
7
|
+
This project uses git submodules. Clone and set up:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
git clone --recursive git@github.com:uhop/dollar-shell.git
|
|
11
|
+
cd dollar-shell
|
|
12
|
+
npm install
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
See the [wiki](https://github.com/uhop/dollar-shell/wiki) for API documentation.
|
|
16
|
+
|
|
17
|
+
## Development workflow
|
|
18
|
+
|
|
19
|
+
1. Make your changes.
|
|
20
|
+
2. Format: `npm run lint:fix`
|
|
21
|
+
3. Test: `npm test`
|
|
22
|
+
4. Type-check: `npm run ts-check`
|
|
23
|
+
|
|
24
|
+
## Code style
|
|
25
|
+
|
|
26
|
+
- ES modules (`import`/`export`), no CommonJS in source.
|
|
27
|
+
- Formatted with Prettier — run `npm run lint:fix` before committing.
|
|
28
|
+
- No dependencies — the library is intentionally zero-dependency.
|
|
29
|
+
- Keep `src/index.js` and `src/index.d.ts` in sync.
|
|
30
|
+
- Update wiki documentation alongside code changes.
|
|
31
|
+
|
|
32
|
+
## AI agents
|
|
33
|
+
|
|
34
|
+
If you are an AI coding agent, see [AGENTS.md](./AGENTS.md) for detailed project conventions, commands, and architecture.
|
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[npm-image]: https://img.shields.io/npm/v/dollar-shell.svg
|
|
4
4
|
[npm-url]: https://npmjs.org/package/dollar-shell
|
|
5
5
|
|
|
6
|
-
`dollar-shell` is a micro-library for running shell commands
|
|
6
|
+
`dollar-shell` is a micro-library for running OS and shell commands from JavaScript/TypeScript using template tag functions. It works in [Node](https://nodejs.org/), [Deno](https://deno.land/), [Bun](https://bun.sh/) with the same API. **Web streams, TypeScript typings, zero dependencies.**
|
|
7
7
|
|
|
8
8
|
The idea is to run OS/shell commands and/or use them in stream pipelines as sources, sinks,
|
|
9
9
|
and transformation steps using [web streams](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API).
|
|
@@ -85,10 +85,32 @@ chain([
|
|
|
85
85
|
npm i --save dollar-shell
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
+
## Project structure
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
dollar-shell/
|
|
92
|
+
├── src/ # Source code
|
|
93
|
+
│ ├── index.js # Main entry point, wires everything together
|
|
94
|
+
│ ├── index.d.ts # TypeScript declarations for the full public API
|
|
95
|
+
│ ├── bq-spawn.js # Template tag factory for spawn-based functions ($, $$)
|
|
96
|
+
│ ├── bq-shell.js # Template tag factory for shell-based functions ($sh, shell)
|
|
97
|
+
│ ├── utils.js # Shared utilities (raw, isWindows, winCmdEscape, etc.)
|
|
98
|
+
│ ├── spawn/ # Runtime-specific Subprocess implementations
|
|
99
|
+
│ └── shell/ # Platform-specific shell escaping and command building
|
|
100
|
+
├── tests/ # Automated tests (tape-six)
|
|
101
|
+
├── tests/manual/ # Manual verification scripts
|
|
102
|
+
├── ts-check/ # TypeScript usage examples (compiled but not executed)
|
|
103
|
+
└── wiki/ # GitHub wiki documentation (git submodule)
|
|
104
|
+
```
|
|
105
|
+
|
|
88
106
|
## Documentation
|
|
89
107
|
|
|
108
|
+
The documentation can be found in the [wiki](https://github.com/uhop/dollar-shell/wiki).
|
|
109
|
+
See how it can be used in [tests/](https://github.com/uhop/dollar-shell/tree/main/tests).
|
|
110
|
+
|
|
111
|
+
For AI assistants: see [llms.txt](https://github.com/uhop/dollar-shell/blob/main/llms.txt) and [llms-full.txt](https://github.com/uhop/dollar-shell/blob/main/llms-full.txt) for LLM-optimized documentation.
|
|
112
|
+
|
|
90
113
|
Below is the documentation for the main components: `spawn()`, `$$`, `$` and `$sh`.
|
|
91
|
-
Additional information can be found in the [wiki](https://github.com/uhop/dollar-shell/wiki).
|
|
92
114
|
|
|
93
115
|
### `spawn()`
|
|
94
116
|
|
|
@@ -200,13 +222,15 @@ The rest is identical to `$`: `$sh`, `$sh.from`, `$sh.to` and `$sh.io`/`$sh.thro
|
|
|
200
222
|
|
|
201
223
|
## For AI Agents
|
|
202
224
|
|
|
203
|
-
This package ships with files to help AI coding agents and LLMs understand and use it:
|
|
225
|
+
This package ships with files to help AI coding agents and LLMs find, understand, and use it:
|
|
204
226
|
|
|
205
|
-
- **[AGENTS.md](./AGENTS.md)** —
|
|
206
|
-
- **[
|
|
227
|
+
- **[AGENTS.md](./AGENTS.md)** — Project conventions, architecture, commands, and coding guidelines for AI agents.
|
|
228
|
+
- **[CLAUDE.md](./CLAUDE.md)** — Claude Code specific instructions (redirects to AGENTS.md).
|
|
229
|
+
- **[CONTRIBUTING.md](./CONTRIBUTING.md)** — Contribution guidelines for humans and AI agents.
|
|
230
|
+
- **[llms.txt](./llms.txt)** — Concise project overview following the [llms.txt standard](https://llmstxt.org/).
|
|
207
231
|
- **[llms-full.txt](./llms-full.txt)** — Self-contained complete API reference (no external links needed).
|
|
208
232
|
|
|
209
|
-
|
|
233
|
+
All files are included in the npm package.
|
|
210
234
|
|
|
211
235
|
## License
|
|
212
236
|
|
|
@@ -214,6 +238,8 @@ BSD-3-Clause
|
|
|
214
238
|
|
|
215
239
|
## Release History
|
|
216
240
|
|
|
241
|
+
- 1.1.11 _Updated dev dependencies._
|
|
242
|
+
- 1.1.10 _Fixed a bug with options chaining for attached functions, fixed Bun spawn on invalid commands, Windows-compatible tests, updated dev dependencies._
|
|
217
243
|
- 1.1.9 _Updated dev dependencies, cleaned up docs, added info for AI agents._
|
|
218
244
|
- 1.1.8 _Updated dev dependencies._
|
|
219
245
|
- 1.1.7 _Updated dev dependencies._
|
package/llms-full.txt
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
# dollar-shell
|
|
2
2
|
|
|
3
|
-
> A micro-library for running shell commands
|
|
3
|
+
> A micro-library for running OS and shell commands from JavaScript/TypeScript using template tag functions. Works in Node, Deno, and Bun with the same API. Web streams, TypeScript typings, zero dependencies.
|
|
4
4
|
|
|
5
5
|
The package provides template-tag functions to spawn OS processes (`$`, `$$`) and shell processes (`$sh`, `shell`/`sh`). Each has variants for stream pipelines: `.from` (stdout as ReadableStream), `.to` (stdin as WritableStream), `.io`/`.through` (duplex). All tag functions accept an options object to customize spawn/shell behavior and return a new tag function with updated defaults.
|
|
6
6
|
|
|
7
|
-
Install
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm i --save dollar-shell
|
|
11
|
+
```
|
|
8
12
|
|
|
9
13
|
## Usage
|
|
10
14
|
|
package/llms.txt
CHANGED
|
@@ -1,18 +1,67 @@
|
|
|
1
1
|
# dollar-shell
|
|
2
2
|
|
|
3
|
-
> A micro-library for running shell commands
|
|
3
|
+
> A micro-library for running OS and shell commands from JavaScript/TypeScript using template tag functions. Works in Node, Deno, and Bun with the same API. Web streams, TypeScript typings, zero dependencies.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Install
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
7
|
+
npm i --save dollar-shell
|
|
8
|
+
|
|
9
|
+
## Quick start
|
|
10
|
+
|
|
11
|
+
```js
|
|
12
|
+
import $ from 'dollar-shell';
|
|
13
|
+
|
|
14
|
+
const result = await $`echo hello`;
|
|
15
|
+
// result: {code: 0, signal: null, killed: false}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Run: `node my-script.js`
|
|
19
|
+
|
|
20
|
+
## API
|
|
21
|
+
|
|
22
|
+
- `$` — run a command, returns `Promise<{code, signal, killed}>`. Default export.
|
|
23
|
+
- `$$` — run a command, returns a `Subprocess` object (full control: kill, streams, exit code).
|
|
24
|
+
- `$sh` — run a shell command, returns `Promise<{code, signal, killed}>`.
|
|
25
|
+
- `shell` / `sh` — run a shell command, returns a `Subprocess` object.
|
|
26
|
+
- `spawn()` — low-level process spawning with full configuration.
|
|
27
|
+
|
|
28
|
+
Stream pipeline helpers (available on `$` and `$sh`):
|
|
29
|
+
- `.from` — stdout as a ReadableStream (source).
|
|
30
|
+
- `.to` — stdin as a WritableStream (sink).
|
|
31
|
+
- `.io` / `.through` — {readable, writable} duplex pair (transform step).
|
|
32
|
+
|
|
33
|
+
All tag functions accept an options object to return a new tag function with updated defaults.
|
|
34
|
+
|
|
35
|
+
Utilities: `raw()`, `winCmdEscape()`, `isWindows`, `cwd()`, `currentExecPath()`, `runFileArgs`, `shellEscape()`, `currentShellPath()`, `buildShellCommand()`.
|
|
36
|
+
|
|
37
|
+
## Common patterns
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
import $, {$$, $sh, raw} from 'dollar-shell';
|
|
41
|
+
|
|
42
|
+
// Simple command
|
|
43
|
+
const result = await $`echo hello`;
|
|
44
|
+
|
|
45
|
+
// Shell command (pipes, aliases, globbing)
|
|
46
|
+
await $sh({stdout: 'inherit'})`ls -l . | grep LICENSE | wc`;
|
|
47
|
+
|
|
48
|
+
// Full Subprocess control
|
|
49
|
+
const sp = $$`sleep 5`;
|
|
50
|
+
sp.kill();
|
|
51
|
+
await sp.exited;
|
|
52
|
+
|
|
53
|
+
// Custom options (returns new tag function)
|
|
54
|
+
const $verbose = $({stdout: 'inherit', stderr: 'inherit'});
|
|
55
|
+
await $verbose`ls -l .`;
|
|
56
|
+
|
|
57
|
+
// Web stream pipeline
|
|
58
|
+
$.from`ls -l .`
|
|
59
|
+
.pipeThrough($.io`grep LIC`)
|
|
60
|
+
.pipeTo($.to({stdout: 'inherit'})`wc`);
|
|
61
|
+
|
|
62
|
+
// Bypass escaping with raw()
|
|
63
|
+
await $sh({stdout: 'inherit'})`echo ${raw('"hello"')}`;
|
|
64
|
+
```
|
|
16
65
|
|
|
17
66
|
## Docs
|
|
18
67
|
|
|
@@ -23,6 +72,8 @@ Key concepts:
|
|
|
23
72
|
- [spawn()](https://github.com/uhop/dollar-shell/wiki/spawn): Low-level process spawning with full configuration
|
|
24
73
|
- [Utilities](https://github.com/uhop/dollar-shell/wiki/Utilities): Helper functions — raw(), winCmdEscape(), isWindows, cwd(), currentExecPath(), runFileArgs, shellEscape(), currentShellPath(), buildShellCommand()
|
|
25
74
|
|
|
26
|
-
##
|
|
75
|
+
## Links
|
|
27
76
|
|
|
28
|
-
-
|
|
77
|
+
- Docs: https://github.com/uhop/dollar-shell/wiki
|
|
78
|
+
- npm: https://www.npmjs.com/package/dollar-shell
|
|
79
|
+
- Full LLM reference: https://github.com/uhop/dollar-shell/blob/main/llms-full.txt
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dollar-shell",
|
|
3
|
-
"description": "Run shell commands and use them in
|
|
4
|
-
"version": "1.1.
|
|
3
|
+
"description": "Run shell commands and use them in stream pipelines with ease in Node, Deno, Bun. Template tag API, web streams, TypeScript typings, zero dependencies.",
|
|
4
|
+
"version": "1.1.11",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
7
7
|
"types": "./src/index.d.ts",
|
|
@@ -28,6 +28,8 @@
|
|
|
28
28
|
"LICENSE",
|
|
29
29
|
"README.md",
|
|
30
30
|
"AGENTS.md",
|
|
31
|
+
"CLAUDE.md",
|
|
32
|
+
"CONTRIBUTING.md",
|
|
31
33
|
"llms.txt",
|
|
32
34
|
"llms-full.txt"
|
|
33
35
|
],
|
|
@@ -39,6 +41,8 @@
|
|
|
39
41
|
"url": "https://github.com/uhop/dollar-shell/issues"
|
|
40
42
|
},
|
|
41
43
|
"homepage": "https://github.com/uhop/dollar-shell#readme",
|
|
44
|
+
"llms": "https://raw.githubusercontent.com/uhop/dollar-shell/main/llms.txt",
|
|
45
|
+
"llmsFull": "https://raw.githubusercontent.com/uhop/dollar-shell/main/llms-full.txt",
|
|
42
46
|
"keywords": [
|
|
43
47
|
"shell",
|
|
44
48
|
"spawn",
|
|
@@ -49,6 +53,14 @@
|
|
|
49
53
|
"exec",
|
|
50
54
|
"command",
|
|
51
55
|
"web-streams",
|
|
56
|
+
"template-tag",
|
|
57
|
+
"pipeline",
|
|
58
|
+
"typescript",
|
|
59
|
+
"esm",
|
|
60
|
+
"es-modules",
|
|
61
|
+
"cross-runtime",
|
|
62
|
+
"zero-dependency",
|
|
63
|
+
"nodejs",
|
|
52
64
|
"deno",
|
|
53
65
|
"bun"
|
|
54
66
|
],
|
|
@@ -59,7 +71,8 @@
|
|
|
59
71
|
},
|
|
60
72
|
"license": "BSD-3-Clause",
|
|
61
73
|
"devDependencies": {
|
|
62
|
-
"
|
|
74
|
+
"prettier": "^3.8.1",
|
|
75
|
+
"tape-six": "^1.7.8",
|
|
63
76
|
"typescript": "^5.9.3"
|
|
64
77
|
},
|
|
65
78
|
"tape6": {
|
package/src/bq-shell.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
1
|
import {isRawValue, getRawValue, verifyStrings} from './utils.js';
|
|
4
2
|
|
|
5
3
|
const impl =
|
|
@@ -28,7 +26,11 @@ const impl =
|
|
|
28
26
|
const bqShell = (shellEscape, shell, options = {}) => {
|
|
29
27
|
const bq = (strings, ...args) => {
|
|
30
28
|
if (verifyStrings(strings)) return impl(shellEscape, shell, options)(strings, ...args);
|
|
31
|
-
|
|
29
|
+
const derived = bqShell(shellEscape, shell, {...options, ...strings});
|
|
30
|
+
for (const [key, value] of Object.entries(bq)) {
|
|
31
|
+
derived[key] = typeof value === 'function' ? value(strings) : value;
|
|
32
|
+
}
|
|
33
|
+
return derived;
|
|
32
34
|
};
|
|
33
35
|
return bq;
|
|
34
36
|
};
|
package/src/bq-spawn.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
1
|
import {verifyStrings, isRawValue, getRawValue} from './utils.js';
|
|
4
2
|
|
|
5
3
|
const appendString = (s, previousSpace, result) => {
|
|
@@ -69,7 +67,11 @@ const impl =
|
|
|
69
67
|
const bqSpawn = (spawn, options = {}) => {
|
|
70
68
|
const bq = (strings, ...args) => {
|
|
71
69
|
if (verifyStrings(strings)) return impl(spawn, options)(strings, ...args);
|
|
72
|
-
|
|
70
|
+
const derived = bqSpawn(spawn, {...options, ...strings});
|
|
71
|
+
for (const [key, value] of Object.entries(bq)) {
|
|
72
|
+
derived[key] = typeof value === 'function' ? value(strings) : value;
|
|
73
|
+
}
|
|
74
|
+
return derived;
|
|
73
75
|
};
|
|
74
76
|
return bq;
|
|
75
77
|
};
|
package/src/index.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
// @ts-self-types="./index.d.ts"
|
|
2
2
|
|
|
3
|
-
'use strict';
|
|
4
|
-
|
|
5
3
|
// load dependencies
|
|
6
4
|
|
|
7
5
|
import {isWindows, raw, winCmdEscape} from './utils.js';
|
|
@@ -39,17 +37,17 @@ export const $ = bqSpawn((command, options) => {
|
|
|
39
37
|
});
|
|
40
38
|
|
|
41
39
|
const fromProcess = bqSpawn((command, options) => {
|
|
42
|
-
const sp = spawn(command,
|
|
40
|
+
const sp = spawn(command, {...options, stdout: 'pipe'});
|
|
43
41
|
return sp.stdout;
|
|
44
42
|
});
|
|
45
43
|
|
|
46
44
|
const toProcess = bqSpawn((command, options) => {
|
|
47
|
-
const sp = spawn(command,
|
|
45
|
+
const sp = spawn(command, {...options, stdin: 'pipe'});
|
|
48
46
|
return sp.stdin;
|
|
49
47
|
});
|
|
50
48
|
|
|
51
49
|
const throughProcess = bqSpawn((command, options) => {
|
|
52
|
-
const sp = spawn(command,
|
|
50
|
+
const sp = spawn(command, {...options, stdin: 'pipe', stdout: 'pipe'});
|
|
53
51
|
return sp.asDuplex;
|
|
54
52
|
});
|
|
55
53
|
|
|
@@ -60,36 +58,46 @@ $.through = $.io = throughProcess;
|
|
|
60
58
|
// define shell functions
|
|
61
59
|
|
|
62
60
|
export const shell = bqShell(shellEscape, (command, options) =>
|
|
63
|
-
spawn(buildShellCommand(options?.shellPath, options?.shellArgs, command),
|
|
61
|
+
spawn(buildShellCommand(options?.shellPath, options?.shellArgs, command), {
|
|
62
|
+
...options,
|
|
63
|
+
windowsVerbatimArguments: true
|
|
64
|
+
})
|
|
64
65
|
);
|
|
65
66
|
export {shell as sh};
|
|
66
67
|
|
|
67
68
|
export const $sh = bqShell(shellEscape, (command, options) => {
|
|
68
|
-
const sp = spawn(buildShellCommand(options?.shellPath, options?.shellArgs, command),
|
|
69
|
+
const sp = spawn(buildShellCommand(options?.shellPath, options?.shellArgs, command), {
|
|
70
|
+
...options,
|
|
71
|
+
windowsVerbatimArguments: true
|
|
72
|
+
});
|
|
69
73
|
return sp.exited.then(() => ({code: sp.exitCode, signal: sp.signalCode, killed: sp.killed}));
|
|
70
74
|
});
|
|
71
75
|
|
|
72
76
|
const fromShell = bqShell(shellEscape, (command, options) => {
|
|
73
|
-
const sp = spawn(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
+
const sp = spawn(buildShellCommand(options?.shellPath, options?.shellArgs, command), {
|
|
78
|
+
...options,
|
|
79
|
+
stdout: 'pipe',
|
|
80
|
+
windowsVerbatimArguments: true
|
|
81
|
+
});
|
|
77
82
|
return sp.stdout;
|
|
78
83
|
});
|
|
79
84
|
|
|
80
85
|
const toShell = bqShell(shellEscape, (command, options) => {
|
|
81
|
-
const sp = spawn(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
86
|
+
const sp = spawn(buildShellCommand(options?.shellPath, options?.shellArgs, command), {
|
|
87
|
+
...options,
|
|
88
|
+
stdin: 'pipe',
|
|
89
|
+
windowsVerbatimArguments: true
|
|
90
|
+
});
|
|
85
91
|
return sp.stdin;
|
|
86
92
|
});
|
|
87
93
|
|
|
88
94
|
const throughShell = bqShell(shellEscape, (command, options) => {
|
|
89
|
-
const sp = spawn(
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
95
|
+
const sp = spawn(buildShellCommand(options?.shellPath, options?.shellArgs, command), {
|
|
96
|
+
...options,
|
|
97
|
+
stdin: 'pipe',
|
|
98
|
+
stdout: 'pipe',
|
|
99
|
+
windowsVerbatimArguments: true
|
|
100
|
+
});
|
|
93
101
|
return sp.asDuplex;
|
|
94
102
|
});
|
|
95
103
|
|
package/src/shell/unix.js
CHANGED
package/src/shell/windows.js
CHANGED
package/src/spawn/bun.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
1
|
const sanitize = (value, defaultValue = 'ignore') => {
|
|
4
2
|
switch (value) {
|
|
5
3
|
case 'pipe':
|
|
@@ -20,8 +18,10 @@ class Subprocess {
|
|
|
20
18
|
this.options = options;
|
|
21
19
|
|
|
22
20
|
this.killed = false;
|
|
21
|
+
this.finished = false;
|
|
23
22
|
|
|
24
|
-
const spawnOptions = {
|
|
23
|
+
const spawnOptions = {};
|
|
24
|
+
if (options.windowsVerbatimArguments) spawnOptions.windowsVerbatimArguments = true;
|
|
25
25
|
options.cwd && (spawnOptions.cwd = options.cwd);
|
|
26
26
|
options.env && (spawnOptions.env = options.env);
|
|
27
27
|
|
|
@@ -31,27 +31,33 @@ class Subprocess {
|
|
|
31
31
|
|
|
32
32
|
this.spawnOptions = spawnOptions;
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
try {
|
|
35
|
+
this.childProcess = Bun.spawn(command, spawnOptions);
|
|
36
|
+
} catch (error) {
|
|
37
|
+
this.childProcess = null;
|
|
38
|
+
this.finished = true;
|
|
39
|
+
this.exited = Promise.reject(error);
|
|
40
|
+
this.stdin = null;
|
|
41
|
+
this.stdout = null;
|
|
42
|
+
this.stderr = null;
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
this.exited = this.childProcess.exited.then(code => {
|
|
46
|
+
this.finished = true;
|
|
47
|
+
return code;
|
|
48
|
+
});
|
|
35
49
|
|
|
36
50
|
this.stdin = this.childProcess.stdin ? new WritableStream(this.childProcess.stdin) : null;
|
|
37
51
|
this.stdout = this.childProcess.stdout || null;
|
|
38
52
|
this.stderr = this.childProcess.stderr || null;
|
|
39
53
|
}
|
|
40
54
|
|
|
41
|
-
get exited() {
|
|
42
|
-
return this.childProcess.exited;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
get finished() {
|
|
46
|
-
return this.childProcess.killed;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
55
|
get exitCode() {
|
|
50
|
-
return this.childProcess.exitCode;
|
|
56
|
+
return this.childProcess ? this.childProcess.exitCode : null;
|
|
51
57
|
}
|
|
52
58
|
|
|
53
59
|
get signalCode() {
|
|
54
|
-
return this.childProcess.signalCode;
|
|
60
|
+
return this.childProcess ? this.childProcess.signalCode : null;
|
|
55
61
|
}
|
|
56
62
|
|
|
57
63
|
get asDuplex() {
|
package/src/spawn/deno.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
1
|
const sanitize = (value, defaultValue = 'null') => {
|
|
4
2
|
switch (value) {
|
|
5
3
|
case 'pipe':
|
|
@@ -28,9 +26,9 @@ class Subprocess {
|
|
|
28
26
|
|
|
29
27
|
const spawnOptions = {
|
|
30
28
|
signal: this.controller.signal,
|
|
31
|
-
args: command.slice(1)
|
|
32
|
-
windowsRawArguments: true
|
|
29
|
+
args: command.slice(1)
|
|
33
30
|
};
|
|
31
|
+
if (options.windowsVerbatimArguments) spawnOptions.windowsRawArguments = true;
|
|
34
32
|
options.cwd && (spawnOptions.cwd = options.cwd);
|
|
35
33
|
options.env && (spawnOptions.env = options.env);
|
|
36
34
|
|
|
@@ -40,7 +38,14 @@ class Subprocess {
|
|
|
40
38
|
|
|
41
39
|
this.spawnOptions = spawnOptions;
|
|
42
40
|
|
|
43
|
-
|
|
41
|
+
try {
|
|
42
|
+
this.childProcess = new Deno.Command(command[0], spawnOptions).spawn();
|
|
43
|
+
} catch (error) {
|
|
44
|
+
this.childProcess = null;
|
|
45
|
+
this.finished = true;
|
|
46
|
+
this.exited = Promise.reject(error);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
44
49
|
|
|
45
50
|
this.exited = this.childProcess.status
|
|
46
51
|
.then(status => {
|
|
@@ -56,15 +61,21 @@ class Subprocess {
|
|
|
56
61
|
}
|
|
57
62
|
|
|
58
63
|
get stdin() {
|
|
59
|
-
return this.spawnOptions.stdin === 'piped'
|
|
64
|
+
return this.childProcess && this.spawnOptions.stdin === 'piped'
|
|
65
|
+
? this.childProcess.stdin
|
|
66
|
+
: null;
|
|
60
67
|
}
|
|
61
68
|
|
|
62
69
|
get stdout() {
|
|
63
|
-
return this.spawnOptions.stdout === 'piped'
|
|
70
|
+
return this.childProcess && this.spawnOptions.stdout === 'piped'
|
|
71
|
+
? this.childProcess.stdout
|
|
72
|
+
: null;
|
|
64
73
|
}
|
|
65
74
|
|
|
66
75
|
get stderr() {
|
|
67
|
-
return this.spawnOptions.stderr === 'piped'
|
|
76
|
+
return this.childProcess && this.spawnOptions.stderr === 'piped'
|
|
77
|
+
? this.childProcess.stderr
|
|
78
|
+
: null;
|
|
68
79
|
}
|
|
69
80
|
|
|
70
81
|
get asDuplex() {
|
package/src/spawn/node.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
1
|
import {spawn} from 'node:child_process';
|
|
4
2
|
import {Readable, Writable} from 'node:stream';
|
|
5
3
|
|
|
@@ -29,7 +27,8 @@ class Subprocess {
|
|
|
29
27
|
this.killed = false;
|
|
30
28
|
this.finished = false;
|
|
31
29
|
|
|
32
|
-
const spawnOptions = {stdio: ['ignore', 'ignore', 'ignore']
|
|
30
|
+
const spawnOptions = {stdio: ['ignore', 'ignore', 'ignore']};
|
|
31
|
+
if (options.windowsVerbatimArguments) spawnOptions.windowsVerbatimArguments = true;
|
|
33
32
|
options.cwd && (spawnOptions.cwd = options.cwd);
|
|
34
33
|
options.env && (spawnOptions.env = options.env);
|
|
35
34
|
|
|
@@ -39,6 +38,22 @@ class Subprocess {
|
|
|
39
38
|
|
|
40
39
|
this.spawnOptions = spawnOptions;
|
|
41
40
|
|
|
41
|
+
let settled = false;
|
|
42
|
+
this.exited = new Promise((resolve, reject) => {
|
|
43
|
+
this.resolve = value => {
|
|
44
|
+
if (!settled) {
|
|
45
|
+
settled = true;
|
|
46
|
+
resolve(value);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
this.reject = value => {
|
|
50
|
+
if (!settled) {
|
|
51
|
+
settled = true;
|
|
52
|
+
reject(value);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
|
|
42
57
|
this.childProcess = spawn(command[0], command.slice(1), spawnOptions);
|
|
43
58
|
this.childProcess.on('exit', (code, signal) => {
|
|
44
59
|
this.finished = true;
|
|
@@ -51,11 +66,6 @@ class Subprocess {
|
|
|
51
66
|
this.reject(error);
|
|
52
67
|
});
|
|
53
68
|
|
|
54
|
-
this.exited = new Promise((resolve, reject) => {
|
|
55
|
-
this.resolve = resolve;
|
|
56
|
-
this.reject = reject;
|
|
57
|
-
});
|
|
58
|
-
|
|
59
69
|
this.stdin = this.childProcess.stdin && Writable.toWeb(this.childProcess.stdin);
|
|
60
70
|
this.stdout = this.childProcess.stdout && Readable.toWeb(this.childProcess.stdout);
|
|
61
71
|
this.stderr = this.childProcess.stderr && Readable.toWeb(this.childProcess.stderr);
|
package/src/utils.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
1
|
let getEnv, isWindows, isAndroid;
|
|
4
2
|
if (typeof Deno !== 'undefined') {
|
|
5
3
|
getEnv = name => Deno.env.get(name);
|
|
@@ -16,8 +14,7 @@ if (typeof Deno !== 'undefined') {
|
|
|
16
14
|
}
|
|
17
15
|
export {getEnv, isWindows, isAndroid};
|
|
18
16
|
|
|
19
|
-
export const verifyStrings = strings =>
|
|
20
|
-
Array.isArray(strings) && strings.every(s => typeof s === 'string');
|
|
17
|
+
export const verifyStrings = strings => Array.isArray(strings) && Array.isArray(strings.raw);
|
|
21
18
|
|
|
22
19
|
export const toBase64 = s => {
|
|
23
20
|
// const buf = new TextEncoder().encode(s),
|