Commit ae55549
Changed files (4)
test
src/core.ts
@@ -40,6 +40,7 @@ import {
quotePowerShell,
noquote,
ensureEol,
+ preferNmBin,
} from './util.js'
export interface Shell {
@@ -74,6 +75,7 @@ export interface Options {
quote: typeof quote
quiet: boolean
detached: boolean
+ preferLocal: boolean
spawn: typeof spawn
spawnSync: typeof spawnSync
log: typeof log
@@ -108,6 +110,7 @@ export const defaults: Options = {
postfix: '',
quote: noquote,
detached: false,
+ preferLocal: false,
spawn,
spawnSync,
log,
@@ -251,6 +254,7 @@ export class ProcessPromise extends Promise<ProcessOutput> {
if (input) this.stdio('pipe')
if ($.timeout) this.timeout($.timeout, $.timeoutSignal)
+ if ($.preferLocal) $.env = preferNmBin($.env, $.cwd, $[processCwd])
$.log({
kind: 'cmd',
src/util.ts
@@ -46,6 +46,28 @@ export function isString(obj: any) {
const pad = (v: string) => (v === ' ' ? ' ' : '')
+export function preferNmBin(
+ env: NodeJS.ProcessEnv,
+ ...dirs: (string | undefined)[]
+) {
+ const pathKey =
+ process.platform === 'win32'
+ ? Object.keys(env)
+ .reverse()
+ .find((key) => key.toUpperCase() === 'PATH') || 'Path'
+ : 'PATH'
+ const pathValue = dirs
+ .map((c) => c && path.resolve(c as string, 'node_modules', '.bin'))
+ .concat(env[pathKey])
+ .filter(Boolean)
+ .join(path.delimiter)
+
+ return {
+ ...env,
+ [pathKey]: pathValue,
+ }
+}
+
export function normalizeMultilinePieces(
pieces: TemplateStringsArray
): TemplateStringsArray {
test/core.test.js
@@ -43,9 +43,10 @@ describe('core', () => {
assert.equal(foo.stdout, 'foo\n')
})
- test('env vars is safe to pass', async () => {
+ test('env vars are safe to pass', async () => {
process.env.ZX_TEST_BAR = 'hi; exit 1'
- await $`echo $ZX_TEST_BAR`
+ const bar = await $`echo $ZX_TEST_BAR`
+ assert.equal(bar.stdout, 'hi; exit 1\n')
})
test('arguments are quoted', async () => {
@@ -205,6 +206,20 @@ describe('core', () => {
assert.equal(exitCode, null)
assert.equal(signal, 'SIGKILL')
})
+
+ test('`env` option', async () => {
+ const baz = await $({
+ env: { ZX_TEST_BAZ: 'baz' },
+ })`echo $ZX_TEST_BAZ`
+ assert.equal(baz.stdout, 'baz\n')
+ })
+
+ test('`preferLocal` preserves env', async () => {
+ const path = await $({
+ preferLocal: true,
+ })`echo $PATH`
+ assert(path.stdout.startsWith(`${process.cwd()}/node_modules/.bin:`))
+ })
})
test('accepts `stdio`', async () => {
test/util.test.js
@@ -30,6 +30,7 @@ import {
tempdir,
tempfile,
ensureEol,
+ preferNmBin,
} from '../build/util.js'
describe('util', () => {
@@ -183,3 +184,11 @@ test('ensureEol() should ensure buffer ends with a newline character', () => {
const result3 = ensureEol(buffer3).toString()
assert.strictEqual(result3, '\n')
})
+
+test('preferNmBin()', () => {
+ const env = {
+ PATH: '/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/sbin',
+ }
+ const _env = preferNmBin(env, process.cwd())
+ assert.equal(_env.PATH, `${process.cwd()}/node_modules/.bin:${env.PATH}`)
+})