Skip to main content
Glama
loader.ts2.25 kB
import { promises as fs } from 'node:fs'; import { join } from 'node:path'; import type { Rule } from '../types.js'; function resolveRulesDirs(): string[] { // Prefer alongside dist (../rules), also check CWD/rules for dev // dist/.. = project root const here = new URL('', import.meta.url).pathname; // here ends with /dist/... const distDir = here.replace(/\/[^/]*$/, ''); const projectRoot = distDir.replace(/\/dist\/?$/, ''); return [join(projectRoot, 'rules'), join(process.cwd(), 'rules')]; } async function readYaml(filePath: string): Promise<any | null> { try { // dynamic import to avoid hard dependency during tests const mod: any = await import('js-yaml'); const text = await fs.readFile(filePath, 'utf8'); return mod.load(text); } catch { return null; } } function validateRule(obj: any): Rule | null { if (!obj || typeof obj !== 'object') return null; const { id, title, severity, language, description, pattern } = obj; if (!id || !title || !severity || !language || !pattern) return null; let re: RegExp; try { if (typeof pattern === 'string') { // pattern is a plain regex source; use default flags 'i' re = new RegExp(pattern, 'i'); } else if (pattern && typeof pattern.source === 'string') { re = new RegExp(pattern.source, pattern.flags ?? 'i'); } else { return null; } } catch { return null; } return { id, title, severity, language, description, pattern: re } as Rule; } export async function loadYamlRules(): Promise<Rule[]> { const dirs = resolveRulesDirs(); const results: Rule[] = []; for (const dir of dirs) { try { const entries = await fs.readdir(dir); for (const name of entries) { if (!name.endsWith('.yaml') && !name.endsWith('.yml')) continue; const full = join(dir, name); const data = await readYaml(full); if (Array.isArray(data)) { for (const item of data) { const r = validateRule(item); if (r) results.push(r); } } else if (data) { const r = validateRule(data); if (r) results.push(r); } } } catch { // ignore missing directories } } return results; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/rachellarralde/risk-audit-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server