* Generate hooks metadata (similar to skills - folder-based)
(gitDates)
| 218 | * Generate hooks metadata (similar to skills - folder-based) |
| 219 | */ |
| 220 | function generateHooksData(gitDates) { |
| 221 | const hooks = []; |
| 222 | |
| 223 | // Check if hooks directory exists |
| 224 | if (!fs.existsSync(HOOKS_DIR)) { |
| 225 | return { |
| 226 | items: hooks, |
| 227 | filters: { |
| 228 | hooks: [], |
| 229 | tags: [], |
| 230 | }, |
| 231 | }; |
| 232 | } |
| 233 | |
| 234 | // Get all hook folders (directories) |
| 235 | const hookFolders = fs.readdirSync(HOOKS_DIR).filter((file) => { |
| 236 | const filePath = path.join(HOOKS_DIR, file); |
| 237 | return fs.statSync(filePath).isDirectory(); |
| 238 | }); |
| 239 | |
| 240 | // Track all unique values for filters |
| 241 | const allHookTypes = new Set(); |
| 242 | const allTags = new Set(); |
| 243 | |
| 244 | for (const folder of hookFolders) { |
| 245 | const hookPath = path.join(HOOKS_DIR, folder); |
| 246 | const metadata = parseHookMetadata(hookPath); |
| 247 | if (!metadata) continue; |
| 248 | |
| 249 | const relativePath = path |
| 250 | .relative(ROOT_FOLDER, hookPath) |
| 251 | .replace(/\\/g, "/"); |
| 252 | const readmeRelativePath = `${relativePath}/README.md`; |
| 253 | |
| 254 | // Track unique values |
| 255 | (metadata.hooks || []).forEach((h) => allHookTypes.add(h)); |
| 256 | (metadata.tags || []).forEach((t) => allTags.add(t)); |
| 257 | |
| 258 | hooks.push({ |
| 259 | id: folder, |
| 260 | title: metadata.name, |
| 261 | description: metadata.description, |
| 262 | hooks: metadata.hooks || [], |
| 263 | tags: metadata.tags || [], |
| 264 | assets: metadata.assets || [], |
| 265 | path: relativePath, |
| 266 | readmeFile: readmeRelativePath, |
| 267 | lastUpdated: gitDates.get(readmeRelativePath) || null, |
| 268 | }); |
| 269 | } |
| 270 | |
| 271 | // Sort and return with filter metadata |
| 272 | const sortedHooks = hooks.sort((a, b) => a.title.localeCompare(b.title)); |
| 273 | |
| 274 | return { |
| 275 | items: sortedHooks, |
| 276 | filters: { |
| 277 | hooks: Array.from(allHookTypes).sort(), |
no test coverage detected