MCPcopy Create free account
hub / github.com/winfunc/opcode / validateConfig

Method validateConfig

src/lib/hooksManager.ts:109–191  ·  view source on GitHub ↗

* Validate hooks configuration

(hooks: HooksConfiguration)

Source from the content-addressed store, hash-verified

107 * Validate hooks configuration
108 */
109 static async validateConfig(hooks: HooksConfiguration): Promise<HookValidationResult> {
110 const errors: HookValidationError[] = [];
111 const warnings: HookValidationWarning[] = [];
112
113 // Guard against undefined or null hooks
114 if (!hooks) {
115 return { valid: true, errors, warnings };
116 }
117
118 // Events with matchers
119 const matcherEvents = ['PreToolUse', 'PostToolUse'] as const;
120
121 // Events without matchers
122 const directEvents = ['Notification', 'Stop', 'SubagentStop'] as const;
123
124 // Validate events with matchers
125 for (const event of matcherEvents) {
126 const matchers = hooks[event];
127 if (!matchers || !Array.isArray(matchers)) continue;
128
129 for (const matcher of matchers) {
130 // Validate regex pattern if provided
131 if (matcher.matcher) {
132 try {
133 new RegExp(matcher.matcher);
134 } catch (e) {
135 errors.push({
136 event,
137 matcher: matcher.matcher,
138 message: `Invalid regex pattern: ${e instanceof Error ? e.message : 'Unknown error'}`
139 });
140 }
141 }
142
143 // Validate commands
144 if (matcher.hooks && Array.isArray(matcher.hooks)) {
145 for (const hook of matcher.hooks) {
146 if (!hook.command || !hook.command.trim()) {
147 errors.push({
148 event,
149 matcher: matcher.matcher,
150 message: 'Empty command'
151 });
152 }
153
154 // Check for dangerous patterns
155 const dangers = this.checkDangerousPatterns(hook.command || '');
156 warnings.push(...dangers.map(d => ({
157 event,
158 matcher: matcher.matcher,
159 command: hook.command || '',
160 message: d
161 })));
162 }
163 }
164 }
165 }
166

Callers 1

validateHooksFunction · 0.80

Calls 1

Tested by

no test coverage detected