Commit bfff0ef
Changed files (5)
test
src/core.ts
@@ -30,7 +30,6 @@ import {
chalk,
which,
ps,
- isStringLiteral,
type ChalkInstance,
type RequestInfo,
type RequestInit,
@@ -43,6 +42,7 @@ import {
formatCmd,
getCallerLocation,
isString,
+ isStringLiteral,
noop,
parseDuration,
preferLocalBin,
@@ -325,7 +325,6 @@ export class ProcessPromise extends Promise<ProcessOutput> {
c
) => {
self._resolved = true
-
// Ensures EOL
if (stderr && !stderr.endsWith('\n')) c.on.stderr?.(eol, c)
if (stdout && !stdout.endsWith('\n')) c.on.stdout?.(eol, c)
@@ -466,7 +465,7 @@ export class ProcessPromise extends Promise<ProcessOutput> {
dest: Writable | ProcessPromise | TemplateStringsArray,
...args: any[]
): ProcessPromise {
- if (isStringLiteral(dest))
+ if (isStringLiteral(dest, ...args))
return this.pipe($(dest as TemplateStringsArray, ...args))
if (isString(dest))
throw new Error('The pipe() method does not take strings. Forgot $?')
src/util.ts
@@ -17,8 +17,6 @@ import path from 'node:path'
import fs from 'node:fs'
import { chalk } from './vendor-core.js'
-export { isStringLiteral } from './vendor-core.js'
-
export function tempdir(prefix = `zx-${randomId()}`) {
const dirpath = path.join(os.tmpdir(), prefix)
fs.mkdirSync(dirpath, { recursive: true })
@@ -47,6 +45,18 @@ export function isString(obj: any) {
return typeof obj === 'string'
}
+export const isStringLiteral = (
+ pieces: any,
+ ...rest: any[]
+): pieces is TemplateStringsArray => {
+ return (
+ pieces?.length > 0 &&
+ pieces.raw?.length === pieces.length &&
+ Object.isFrozen(pieces) &&
+ rest.length + 1 === pieces.length
+ )
+}
+
const pad = (v: string) => (v === ' ' ? ' ' : '')
export function preferLocalBin(
src/vendor-core.ts
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-export { exec, buildCmd, isStringLiteral, type TSpawnStore } from 'zurk/spawn'
+export { exec, buildCmd, type TSpawnStore } from 'zurk/spawn'
export type RequestInfo = Parameters<typeof globalThis.fetch>[0]
export type RequestInit = Parameters<typeof globalThis.fetch>[1]
test/core.test.js
@@ -358,6 +358,13 @@ describe('core', () => {
assert.equal(p.stdout.trim(), 'foo')
})
+ test('accepts stdout', async () => {
+ const p1 = $`echo pipe-to-stdout`
+ const p2 = p1.pipe(process.stdout)
+ assert.equal(p1, p2)
+ assert.equal((await p1).stdout.trim(), 'pipe-to-stdout')
+ })
+
test('checks argument type', async () => {
let err
try {
test/util.test.js
@@ -20,6 +20,7 @@ import {
errnoMessage,
formatCmd,
isString,
+ isStringLiteral,
noop,
parseDuration,
quote,
@@ -59,6 +60,17 @@ describe('util', () => {
assert.ok(!isString(1))
})
+ test('isStringLiteral()', () => {
+ const bar = 'baz'
+ assert.ok(isStringLiteral``)
+ assert.ok(isStringLiteral`foo`)
+ assert.ok(isStringLiteral`foo ${bar}`)
+
+ assert.ok(!isStringLiteral(''))
+ assert.ok(!isStringLiteral('foo'))
+ assert.ok(!isStringLiteral(['foo']))
+ })
+
test('quote()', () => {
assert.ok(quote('string') === 'string')
assert.ok(quote(`'\f\n\r\t\v\0`) === `$'\\'\\f\\n\\r\\t\\v\\0'`)