diff --git a/packages/cli-kit/src/public/node/system.test.ts b/packages/cli-kit/src/public/node/system.test.ts index ed12516ba40..2a080b7ff1e 100644 --- a/packages/cli-kit/src/public/node/system.test.ts +++ b/packages/cli-kit/src/public/node/system.test.ts @@ -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' @@ -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 @@ -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', () => { diff --git a/packages/cli-kit/src/public/node/system.ts b/packages/cli-kit/src/public/node/system.ts index 3f449f8ff34..3b84c7fe2b4 100644 --- a/packages/cli-kit/src/public/node/system.ts +++ b/packages/cli-kit/src/public/node/system.ts @@ -364,6 +364,19 @@ export async function isWsl(): Promise { 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`) @@ -372,13 +385,18 @@ export async function isWsl(): Promise { * @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 } /**