Skip to content

Commit dbd252f

Browse files
committed
feat: provide preset api
1 parent 5875929 commit dbd252f

File tree

3 files changed

+38
-22
lines changed

3 files changed

+38
-22
lines changed

src/core.ts

+28-20
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ import {
4141
quotePowerShell,
4242
} from './util.js'
4343

44-
export type Shell = (
45-
pieces: TemplateStringsArray,
46-
...args: any[]
47-
) => ProcessPromise
44+
export interface Shell {
45+
(pieces: TemplateStringsArray, ...args: any[]): ProcessPromise
46+
(opts: Partial<Options>): Shell
47+
}
4848

4949
const processCwd = Symbol('processCwd')
5050

@@ -54,6 +54,7 @@ export interface Options {
5454
verbose: boolean
5555
env: NodeJS.ProcessEnv
5656
shell: string | boolean
57+
nothrow: boolean
5758
prefix: string
5859
quote: typeof quote
5960
spawn: typeof spawn
@@ -75,6 +76,7 @@ export const defaults: Options = {
7576
verbose: true,
7677
env: process.env,
7778
shell: true,
79+
nothrow: false,
7880
prefix: '',
7981
quote: () => {
8082
throw new Error('No quote function is defined: https://ï.at/no-quote-func')
@@ -102,15 +104,27 @@ function getStore() {
102104
return storage.getStore() || defaults
103105
}
104106

105-
export const $ = new Proxy<Shell & Options>(
107+
export const $: Shell & Options = new Proxy<Shell & Options>(
106108
function (pieces, ...args) {
109+
if (!Array.isArray(pieces)) {
110+
return function (this: any, ...args: any) {
111+
const self = this
112+
return within(() => {
113+
return Object.assign($, pieces).apply(self, args)
114+
})
115+
}
116+
}
107117
const from = new Error().stack!.split(/^\s*at\s/m)[2].trim()
108118
if (pieces.some((p) => p == undefined)) {
109119
throw new Error(`Malformed command at ${from}`)
110120
}
111121
let resolve: Resolve, reject: Resolve
112122
const promise = new ProcessPromise((...args) => ([resolve, reject] = args))
113-
const cmd = buildCmd($.quote, pieces, args) as string
123+
const cmd = buildCmd(
124+
$.quote,
125+
pieces as TemplateStringsArray,
126+
args
127+
) as string
114128

115129
promise._bind(cmd, from, resolve!, reject!, getStore())
116130
// Postpone run to allow promise configuration.
@@ -148,7 +162,7 @@ export class ProcessPromise extends Promise<ProcessOutput> {
148162
private _reject: Resolve = noop
149163
private _snapshot = getStore()
150164
private _stdio: [IO, IO, IO] = ['inherit', 'pipe', 'pipe']
151-
private _nothrow = false
165+
private _nothrow?: boolean
152166
private _quiet = false
153167
private _timeout?: number
154168
private _timeoutSignal?: string
@@ -187,18 +201,10 @@ export class ProcessPromise extends Promise<ProcessOutput> {
187201

188202
this._zurk = zurk$({
189203
cmd: $.prefix + this._command,
190-
get cwd() {
191-
return $.cwd ?? $[processCwd]
192-
},
193-
get shell() {
194-
return typeof $.shell === 'string' ? $.shell : true
195-
},
196-
get env() {
197-
return $.env
198-
},
199-
get spawn() {
200-
return $.spawn
201-
},
204+
cwd: $.cwd ?? $[processCwd],
205+
shell: typeof $.shell === 'string' ? $.shell : true,
206+
env: $.env,
207+
spawn: $.spawn,
202208
quote: <T>(v: T): T => v, // let zx handle quoting
203209
stdio: this._stdio as any,
204210
sync: false,
@@ -222,6 +228,7 @@ export class ProcessPromise extends Promise<ProcessOutput> {
222228
this._zurk.then(({ error, stdout, stderr, stdall, status, signal }) => {
223229
if (error) {
224230
const message = ProcessOutput.getErrorMessage(error, self._from)
231+
// (nothrow ? self._resolve : self._reject)(
225232
self._reject(
226233
new ProcessOutput(null, null, stdout, stderr, stdall, message)
227234
)
@@ -240,7 +247,8 @@ export class ProcessPromise extends Promise<ProcessOutput> {
240247
stdall,
241248
message
242249
)
243-
if (status === 0 || self._nothrow) {
250+
251+
if (status === 0 || (self._nothrow ?? $.nothrow)) {
244252
self._resolve(output)
245253
} else {
246254
self._reject(output)

src/index.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@ export { minimist, chalk, fs, which, YAML, ssh } from './vendor.js'
2121
export { type Duration, quote, quotePowerShell } from './util.js'
2222

2323
/**
24-
* @deprecated Use $.nothrow() instead.
24+
* @deprecated Use $`cmd`.nothrow() instead.
2525
*/
2626
export function nothrow(promise: ProcessPromise) {
2727
return promise.nothrow()
2828
}
2929

3030
/**
31-
* @deprecated Use $.quiet() instead.
31+
* @deprecated Use $`cmd`.quiet() instead.
3232
*/
3333
export function quiet(promise: ProcessPromise) {
3434
return promise.quiet()

test/core.test.js

+8
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,14 @@ describe('core', () => {
124124
}
125125
})
126126

127+
test('provides presets', async () => {
128+
const $$ = $({ nothrow: true })
129+
assert.equal(
130+
(await $$`ffff`).stderr.toString(),
131+
'/bin/bash: ffff: command not found\n'
132+
)
133+
})
134+
127135
test('ProcessPromise', async () => {
128136
let contents = ''
129137
let stream = new Writable({

0 commit comments

Comments
 (0)