import { describe, expect, it } from 'vitest'; import { readdirSync, readFileSync, statSync } from 'node:fs'; import { join } from 'node:path'; // Profile links must always go to mu.social, never to bsky.app. (API host // public.api.bsky.app and CDN cdn.bsky.app are fine — they are not profile links, // so they never match the "bsky.app/profile" needle below.) const NEEDLE = 'bsky.app' + '/profile'; // split so this test file never matches itself function walk(dir: string): string[] { const out: string[] = []; for (const name of readdirSync(dir)) { const p = join(dir, name); if (statSync(p).isDirectory()) out.push(...walk(p)); else if (/\.(astro|ts|tsx|js|mjs|md)$/.test(name) && !name.includes('.test.')) out.push(p); } return out; } describe('profile links', () => { it('never point at bsky.app — profiles open on mu.social', () => { const offenders: string[] = []; for (const file of walk('src')) { readFileSync(file, 'utf8') .split('\n') .forEach((line, i) => { if (line.includes(NEEDLE)) offenders.push(`${file}:${i + 1}`); }); } expect(offenders, `profile links must use mu.social:\n${offenders.join('\n')}`).toEqual([]); }); });