mono/packages/kbot/ref/utils/execFileNoThrowPortable.ts
2026-04-01 01:05:48 +02:00

90 lines
2.6 KiB
TypeScript

import { type Options as ExecaOptions, execaSync } from 'execa'
import { getCwd } from '../utils/cwd.js'
import { slowLogging } from './slowOperations.js'
const MS_IN_SECOND = 1000
const SECONDS_IN_MINUTE = 60
type ExecSyncOptions = {
abortSignal?: AbortSignal
timeout?: number
input?: string
stdio?: ExecaOptions['stdio']
}
/**
* @deprecated Use `execa` directly with `{ shell: true, reject: false }` for non-blocking execution.
* Sync exec calls block the event loop and cause performance issues.
*/
export function execSyncWithDefaults_DEPRECATED(command: string): string | null
/**
* @deprecated Use `execa` directly with `{ shell: true, reject: false }` for non-blocking execution.
* Sync exec calls block the event loop and cause performance issues.
*/
export function execSyncWithDefaults_DEPRECATED(
command: string,
options: ExecSyncOptions,
): string | null
/**
* @deprecated Use `execa` directly with `{ shell: true, reject: false }` for non-blocking execution.
* Sync exec calls block the event loop and cause performance issues.
*/
export function execSyncWithDefaults_DEPRECATED(
command: string,
abortSignal: AbortSignal,
timeout?: number,
): string | null
/**
* @deprecated Use `execa` directly with `{ shell: true, reject: false }` for non-blocking execution.
* Sync exec calls block the event loop and cause performance issues.
*/
export function execSyncWithDefaults_DEPRECATED(
command: string,
optionsOrAbortSignal?: ExecSyncOptions | AbortSignal,
timeout = 10 * SECONDS_IN_MINUTE * MS_IN_SECOND,
): string | null {
let options: ExecSyncOptions
if (optionsOrAbortSignal === undefined) {
// No second argument - use defaults
options = {}
} else if (optionsOrAbortSignal instanceof AbortSignal) {
// Old signature - second argument is AbortSignal
options = {
abortSignal: optionsOrAbortSignal,
timeout,
}
} else {
// New signature - second argument is options object
options = optionsOrAbortSignal
}
const {
abortSignal,
timeout: finalTimeout = 10 * SECONDS_IN_MINUTE * MS_IN_SECOND,
input,
stdio = ['ignore', 'pipe', 'pipe'],
} = options
abortSignal?.throwIfAborted()
using _ = slowLogging`exec: ${command.slice(0, 200)}`
try {
const result = execaSync(command, {
env: process.env,
maxBuffer: 1_000_000,
timeout: finalTimeout,
cwd: getCwd(),
stdio,
shell: true, // execSync typically runs shell commands
reject: false, // Don't throw on non-zero exit codes
input,
})
if (!result.stdout) {
return null
}
return result.stdout.trim() || null
} catch {
return null
}
}