* Prepare a matcher for hook `if` conditions. Expensive work (tool lookup, * Zod validation, tree-sitter parsing for Bash) happens once here; the * returned closure is called per hook. Returns undefined for non-tool events.
( hookInput: HookInput, tools: Tools | undefined, )
| 1388 | * returned closure is called per hook. Returns undefined for non-tool events. |
| 1389 | */ |
| 1390 | async function prepareIfConditionMatcher( |
| 1391 | hookInput: HookInput, |
| 1392 | tools: Tools | undefined, |
| 1393 | ): Promise<IfConditionMatcher | undefined> { |
| 1394 | if ( |
| 1395 | hookInput.hook_event_name !== 'PreToolUse' && |
| 1396 | hookInput.hook_event_name !== 'PostToolUse' && |
| 1397 | hookInput.hook_event_name !== 'PostToolUseFailure' && |
| 1398 | hookInput.hook_event_name !== 'PermissionRequest' |
| 1399 | ) { |
| 1400 | return undefined |
| 1401 | } |
| 1402 | |
| 1403 | const toolName = normalizeLegacyToolName(hookInput.tool_name) |
| 1404 | const tool = tools && findToolByName(tools, hookInput.tool_name) |
| 1405 | const input = tool?.inputSchema.safeParse(hookInput.tool_input) |
| 1406 | const patternMatcher = |
| 1407 | input?.success && tool?.preparePermissionMatcher |
| 1408 | ? await tool.preparePermissionMatcher(input.data) |
| 1409 | : undefined |
| 1410 | |
| 1411 | return ifCondition => { |
| 1412 | const parsed = permissionRuleValueFromString(ifCondition) |
| 1413 | if (normalizeLegacyToolName(parsed.toolName) !== toolName) { |
| 1414 | return false |
| 1415 | } |
| 1416 | if (!parsed.ruleContent) { |
| 1417 | return true |
| 1418 | } |
| 1419 | return patternMatcher ? patternMatcher(parsed.ruleContent) : false |
| 1420 | } |
| 1421 | } |
| 1422 | |
| 1423 | type FunctionHookMatcher = { |
| 1424 | matcher: string |
no test coverage detected