Files
CursorInitGeneral/.cursor/hooks/run-hook.ps1

112 lines
4.0 KiB
PowerShell

# Hook dispatcher: select the PowerShell or Bash implementation from local-env.json.
param([string]$HookName)
$utf8 = New-Object System.Text.UTF8Encoding($false)
[Console]::InputEncoding = $utf8
[Console]::OutputEncoding = $utf8
function Write-EmptyHookResult {
[Console]::Out.WriteLine('{}')
}
$inputPayload = [Console]::In.ReadToEnd()
try {
if ([string]::IsNullOrWhiteSpace($HookName) -or $HookName -notmatch '^[A-Za-z0-9][A-Za-z0-9._-]*$') {
throw "Invalid hook name."
}
$cursorDir = Split-Path -Parent $PSScriptRoot
$repoRoot = Split-Path -Parent $cursorDir
$localEnvPath = Join-Path $cursorDir 'local-env.json'
$shell = 'powershell'
if (Test-Path -LiteralPath $localEnvPath -PathType Leaf) {
try {
$config = Get-Content -LiteralPath $localEnvPath -Raw -Encoding UTF8 | ConvertFrom-Json
if ($config.shell -is [string] -and -not [string]::IsNullOrWhiteSpace($config.shell)) {
$shell = $config.shell.Trim().ToLowerInvariant()
}
} catch {
[Console]::Error.WriteLine("[run-hook] Ignoring invalid local-env.json: {0}", $_.Exception.Message)
}
}
$processInfo = New-Object System.Diagnostics.ProcessStartInfo
$processInfo.UseShellExecute = $false
$processInfo.CreateNoWindow = $true
$processInfo.RedirectStandardInput = $true
$processInfo.RedirectStandardOutput = $true
$processInfo.RedirectStandardError = $true
$processInfo.WorkingDirectory = $repoRoot
if ($processInfo.PSObject.Properties.Name -contains 'StandardInputEncoding') {
$processInfo.StandardInputEncoding = $utf8
$processInfo.StandardOutputEncoding = $utf8
$processInfo.StandardErrorEncoding = $utf8
}
switch ($shell) {
{ $_ -in @('powershell', 'powershell.exe', 'pwsh', 'pwsh.exe') } {
$scriptPath = Join-Path $PSScriptRoot "$HookName.ps1"
if (-not (Test-Path -LiteralPath $scriptPath -PathType Leaf)) {
throw "PowerShell hook not found: $HookName"
}
$processInfo.FileName = if ($shell -in @('pwsh', 'pwsh.exe')) { 'pwsh' } else { 'powershell' }
$processInfo.Arguments = "-NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass -File `"$scriptPath`""
break
}
{ $_ -in @('bash', 'bash.exe', 'zsh', 'sh') } {
$scriptPath = (Join-Path $PSScriptRoot "$HookName.sh") -replace '\\', '/'
if (-not (Test-Path -LiteralPath $scriptPath -PathType Leaf)) {
throw "Shell hook not found: $HookName"
}
$processInfo.FileName = 'bash'
$processInfo.Arguments = "`"$scriptPath`""
break
}
default {
throw "Unsupported shell '$shell'."
}
}
$process = New-Object System.Diagnostics.Process
$process.StartInfo = $processInfo
if (-not $process.Start()) {
throw "Unable to start hook process."
}
$stdoutTask = $process.StandardOutput.ReadToEndAsync()
$stderrTask = $process.StandardError.ReadToEndAsync()
$process.StandardInput.Write($inputPayload)
$process.StandardInput.Close()
$process.WaitForExit()
$stdout = $stdoutTask.Result
$stderr = $stderrTask.Result
if (-not [string]::IsNullOrWhiteSpace($stderr)) {
[Console]::Error.WriteLine($stderr.TrimEnd())
}
if ($process.ExitCode -ne 0) {
throw "Hook exited with code $($process.ExitCode)."
}
$trimmed = $stdout.Trim()
if ([string]::IsNullOrWhiteSpace($trimmed) -or -not $trimmed.StartsWith('{')) {
throw "Hook returned an empty or non-object response."
}
$result = $trimmed | ConvertFrom-Json
$normalized = $result | ConvertTo-Json -Compress -Depth 20
if ([string]::IsNullOrWhiteSpace($normalized) -or -not $normalized.StartsWith('{')) {
throw "Hook response is not a JSON object."
}
[Console]::Out.WriteLine($normalized)
} catch {
[Console]::Error.WriteLine("[run-hook] {0}", $_.Exception.Message)
Write-EmptyHookResult
}
exit 0