Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion packages/cli-kit/src/public/node/system.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as system from './system.js'
import {_resetIsStdinPipedCache} from './system.js'
import {execa} from 'execa'
import {describe, expect, test, vi} from 'vitest'
import {beforeEach, describe, expect, test, vi} from 'vitest'
import which from 'which'
import {Readable} from 'stream'

Expand All @@ -16,6 +17,10 @@ vi.mock('fs', async (importOriginal) => {
}
})

beforeEach(() => {
_resetIsStdinPipedCache()
})

describe('captureOutput', () => {
test('runs the command when it is not found in the current directory', async () => {
// Given
Expand Down Expand Up @@ -351,6 +356,18 @@ describe('isStdinPiped', () => {
// Then
expect(got).toBe(false)
})

test('memoizes the result', () => {
// Given
vi.mocked(fs.fstatSync).mockReturnValue({isFIFO: () => true, isFile: () => false} as fs.Stats)

// When
system.isStdinPiped()
system.isStdinPiped()

// Then
expect(fs.fstatSync).toHaveBeenCalledTimes(1)
})
})

describe('readStdinString', () => {
Expand Down
22 changes: 20 additions & 2 deletions packages/cli-kit/src/public/node/system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,19 @@ export async function isWsl(): Promise<boolean> {
return wsl.default
}

/**
* Memoized value for the stdin piped check.
*/
let memoizedIsStdinPiped: boolean | undefined

/**
* Reset the memoized value for the stdin piped check.
* This is only used for testing.
*/
export function _resetIsStdinPipedCache(): void {
memoizedIsStdinPiped = undefined
}

/**
* Check if stdin has piped data available.
* This distinguishes between actual piped input (e.g., `echo "query" | cmd`)
Expand All @@ -372,13 +385,18 @@ export async function isWsl(): Promise<boolean> {
* @returns True if stdin is receiving piped data or file redirect, false otherwise.
*/
export function isStdinPiped(): boolean {
if (memoizedIsStdinPiped !== undefined) {
return memoizedIsStdinPiped
}

try {
const stats = fstatSync(0)
return stats.isFIFO() || stats.isFile()
memoizedIsStdinPiped = stats.isFIFO() || stats.isFile()
// eslint-disable-next-line no-catch-all/no-catch-all
} catch {
return false
memoizedIsStdinPiped = false
}
return memoizedIsStdinPiped
}

/**
Expand Down
Loading