* 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, )
| 1525 | * returned closure is called per hook. Returns undefined for non-tool events. |
| 1526 | */ |
| 1527 | async function prepareIfConditionMatcher( |
| 1528 | hookInput: HookInput, |
| 1529 | tools: Tools | undefined, |
| 1530 | ): Promise<IfConditionMatcher | undefined> { |
| 1531 | if ( |
| 1532 | hookInput.hook_event_name !== 'PreToolUse' && |
| 1533 | hookInput.hook_event_name !== 'PostToolUse' && |
| 1534 | hookInput.hook_event_name !== 'PostToolUseFailure' && |
| 1535 | hookInput.hook_event_name !== 'PermissionRequest' |
| 1536 | ) { |
| 1537 | return undefined |
| 1538 | } |
| 1539 | |
| 1540 | const toolName = normalizeLegacyToolName(hookInput.tool_name as string) |
| 1541 | const tool = tools && findToolByName(tools, hookInput.tool_name as string) |
| 1542 | const input = tool?.inputSchema.safeParse(hookInput.tool_input) |
| 1543 | const patternMatcher = |
| 1544 | input?.success && tool?.preparePermissionMatcher |
| 1545 | ? await tool.preparePermissionMatcher(input.data) |
| 1546 | : undefined |
| 1547 | |
| 1548 | return ifCondition => { |
| 1549 | const parsed = permissionRuleValueFromString(ifCondition) |
| 1550 | if (normalizeLegacyToolName(parsed.toolName) !== toolName) { |
| 1551 | return false |
| 1552 | } |
| 1553 | if (!parsed.ruleContent) { |
| 1554 | return true |
| 1555 | } |
| 1556 | return patternMatcher ? patternMatcher(parsed.ruleContent) : false |
| 1557 | } |
| 1558 | } |
| 1559 | |
| 1560 | type FunctionHookMatcher = { |
| 1561 | matcher: string |
no test coverage detected