(
a: HookCommand | { type: 'function'; timeout?: number },
b: HookCommand | { type: 'function'; timeout?: number },
)
| 31 | * Check if two hooks are equal (comparing only command/prompt content, not timeout) |
| 32 | */ |
| 33 | export function isHookEqual( |
| 34 | a: HookCommand | { type: 'function'; timeout?: number }, |
| 35 | b: HookCommand | { type: 'function'; timeout?: number }, |
| 36 | ): boolean { |
| 37 | if (a.type !== b.type) return false |
| 38 | |
| 39 | // Use switch for exhaustive type checking |
| 40 | // Note: We only compare command/prompt content, not timeout |
| 41 | // `if` is part of identity: same command with different `if` conditions |
| 42 | // are distinct hooks (e.g., setup.sh if=Bash(git *) vs if=Bash(npm *)). |
| 43 | const sameIf = (x: { if?: string }, y: { if?: string }) => |
| 44 | (x.if ?? '') === (y.if ?? '') |
| 45 | switch (a.type) { |
| 46 | case 'command': |
| 47 | // shell is part of identity: same command string with different |
| 48 | // shells are distinct hooks. Default 'bash' so undefined === 'bash'. |
| 49 | return ( |
| 50 | b.type === 'command' && |
| 51 | a.command === b.command && |
| 52 | (a.shell ?? DEFAULT_HOOK_SHELL) === (b.shell ?? DEFAULT_HOOK_SHELL) && |
| 53 | sameIf(a, b) |
| 54 | ) |
| 55 | case 'prompt': |
| 56 | return b.type === 'prompt' && a.prompt === b.prompt && sameIf(a, b) |
| 57 | case 'agent': |
| 58 | return b.type === 'agent' && a.prompt === b.prompt && sameIf(a, b) |
| 59 | case 'http': |
| 60 | return b.type === 'http' && a.url === b.url && sameIf(a, b) |
| 61 | case 'function': |
| 62 | // Function hooks can't be compared (no stable identifier) |
| 63 | return false |
| 64 | } |
| 65 | } |
| 66 | |
| 67 | /** Get the display text for a hook */ |
| 68 | export function getHookDisplayText( |
no test coverage detected