Skip to content

Commit

Permalink
feat: add default spawn properties override: timeout, killSignal
Browse files Browse the repository at this point in the history
…and `maxBuffer`
  • Loading branch information
antongolub committed Mar 13, 2022
1 parent 450917a commit 7d219e5
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 5 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,8 @@ Or use a CLI argument: `--shell=/bin/bash`
#### `$.spawn`

Specifies a `spawn` api. Defaults to `require('child_process').spawn`.
You may also assign `spawn.timeout`, `spawn.maxBuffer` and `spawn.killSignal`
to override the default spawn options for all calls.

#### `$.prefix`

Expand Down
8 changes: 6 additions & 2 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import {ChildProcess, spawn} from 'child_process'
import {ChildProcess, spawn, SpawnOptions} from 'child_process'
import {Readable, Writable} from 'stream'
import * as _fs from 'fs-extra'
import * as _globby from 'globby'
Expand All @@ -30,7 +30,11 @@ interface $ {
shell: string
prefix: string
quote: (input: string) => string
spawn: typeof spawn
spawn: typeof spawn & {
maxBuffer?: number | undefined
timeout?: SpawnOptions['timeout']
killSignal?: SpawnOptions['killSignal']
}
}

export interface ProcessPromise<T> extends Promise<T> {
Expand Down
12 changes: 9 additions & 3 deletions index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ export function registerGlobals() {
}

export function $(pieces, ...args) {
let {verbose, shell, prefix} = $
let {verbose, shell, prefix, spawn} = $
let {timeout, killSignal, maxBuffer = 200 * 1024 * 1024 /* 200 MiB*/} = spawn
let __from = (new Error().stack.split(/^\s*at\s/m)[2]).trim()

let cmd = pieces[0], i = 0
Expand All @@ -80,15 +81,20 @@ export function $(pieces, ...args) {
printCmd(cmd)
}

let child = $.spawn(prefix + cmd, {
let child = spawn(prefix + cmd, {
cwd: process.cwd(),
shell: typeof shell === 'string' ? shell : true,
stdio: [promise._inheritStdin ? 'inherit' : 'pipe', 'pipe', 'pipe'],
windowsHide: true,
maxBuffer: 200 * 1024 * 1024, // 200 MiB
maxBuffer,
})

if (timeout) {
promise._timeout = setTimeout(() => promise.kill(killSignal), timeout)
}

child.on('close', (code, signal) => {
promise._timeout && clearTimeout(promise._timeout)
let message = `${stderr || '\n'} at ${__from}`
message += `\n exit code: ${code}${exitCodeInfo(code) ? ' (' + exitCodeInfo(code) + ')' : ''}`
if (signal !== null) {
Expand Down
14 changes: 14 additions & 0 deletions test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,20 @@ if (test('Retry works')) {
assert(Date.now() >= now + 50 * (5 - 1))
}

if (test('spawn timeout')) {
let signal = 0
$.spawn.timeout = 100
$.spawn.killSignal = 'SIGKILL'
try {
await $`sleep 9999`
} catch (p) {
signal = p.signal
}
delete $.spawn.timeout
delete $.spawn.killSignal
assert.equal(signal, 'SIGKILL')
}

let version
if (test('require() is working in ESM')) {
let data = require('./package.json')
Expand Down

0 comments on commit 7d219e5

Please sign in to comment.