Commit d09a117
Changed files (5)
src/context.ts
@@ -20,7 +20,7 @@ export type Options = {
cwd: string
env: NodeJS.ProcessEnv
prefix: string
- shell: string
+ shell: string | boolean
maxBuffer: number
quote: (v: string) => string
spawn: typeof spawn
@@ -43,13 +43,20 @@ let root: Options
const storage = new AsyncLocalStorage<Options>()
export function getCtx() {
- return storage.getStore() as Context
+ return (storage.getStore() as Context) || getRootCtx()
}
+
export function setRootCtx(ctx: Options) {
storage.enterWith(ctx)
root = ctx
}
+
export function getRootCtx() {
return root
}
-export const runInCtx = storage.run.bind(storage)
+
+export const runInCtx = <R, TArgs extends any[]>(
+ ctx: Options = root,
+ cb: (...args: TArgs) => R,
+ ...args: TArgs
+): R => storage.run(ctx, cb, ...args)
src/core.ts
@@ -23,7 +23,7 @@ import { inspect, promisify } from 'node:util'
import { spawn } from 'node:child_process'
import { chalk, which } from './goods.js'
-import { runInCtx, getCtx, setRootCtx, Context, Options } from './context.js'
+import { runInCtx, getCtx, Context, Options, setRootCtx } from './context.js'
import { printCmd, log } from './print.js'
import { quote, substitute } from './guards.js'
@@ -52,13 +52,14 @@ export const $: Zx = function (pieces: TemplateStringsArray, ...args: any[]) {
cmd += s + pieces[++i]
}
- promise.ctx = {
+ const ctx = {
...getCtx(),
cmd,
__from: new Error().stack!.split(/^\s*at\s/m)[2].trim(),
resolve,
reject,
}
+ Object.defineProperty(promise, 'ctx', { value: ctx })
setImmediate(() => promise._run()) // Make sure all subprocesses are started, if not explicitly by await or then().
@@ -72,6 +73,7 @@ $.spawn = spawn
$.verbose = 2
$.maxBuffer = 200 * 1024 * 1024 /* 200 MiB*/
$.prefix = '' // Bash not found, no prefix.
+$.shell = true
try {
$.shell = which.sync('bash')
$.prefix = 'set -euo pipefail;'
src/goods.ts
@@ -18,6 +18,7 @@ import { setTimeout as sleep } from 'node:timers/promises'
import nodeFetch, { RequestInfo, RequestInit } from 'node-fetch'
import { getCtx, getRootCtx } from './context.js'
import { colorize } from './print.js'
+import { log } from './print.js'
export { default as chalk } from 'chalk'
export { default as fs } from 'fs-extra'
@@ -40,13 +41,13 @@ globbyModule)
export const glob = globby
export async function fetch(url: RequestInfo, init?: RequestInit) {
- if (getCtx().verbose) {
- if (typeof init !== 'undefined') {
- console.log('$', colorize(`fetch ${url}`), init)
- } else {
- console.log('$', colorize(`fetch ${url}`))
- }
- }
+ log(
+ { scope: 'fetch' },
+ '$',
+ colorize(`fetch ${url}`),
+ init && JSON.stringify(init, null, 2)
+ )
+
return nodeFetch(url, init)
}
test/index.test.js
@@ -169,6 +169,17 @@ test('ProcessPromise: inherits native Promise', async () => {
assert.ok(p5 !== p1)
})
+test('ProcessPromise: ctx is protected from removal', async () => {
+ const p = $`echo 1`
+
+ try {
+ delete p.ctx
+ assert.unreachable()
+ } catch (e) {
+ assert.match(e.message, /Cannot delete property/)
+ }
+})
+
test('ProcessOutput thrown as error', async () => {
let err
try {
package.json
@@ -51,7 +51,7 @@
"globby": "^13.1.1",
"ignore": "^5.2.0",
"minimist": "^1.2.6",
- "node-fetch": "^3.2.4",
+ "node-fetch": "^3.2.5",
"ps-tree": "^1.2.0",
"which": "^2.0.2",
"yaml": "^2.1.1"