Files
bitvid/scripts/check-tailwind-colors.mjs
google-labs-jules[bot]andPR0M3TH3AN eb4bc255d5 feat: add load-test script and fix lint exclusions
This adds `scripts/agent/load-test.mjs`, a stress testing tool that:
- Spawns a local relay server in a separate process.
- Simulates N concurrent WebSocket clients.
- Publishes a configurable mix of large (Video Post) and small (View) events.
- Measures and reports on latency, throughput, memory usage, and cryptographic signing time.
- Identifies potential bottlenecks (error rate > 5%, latency > 500ms, sign time > 5ms).

Includes a sample run report in `artifacts/`.

Also updates linting scripts (`scripts/check-hex.js`, `scripts/check-design-tokens.mjs`, `scripts/check-inline-styles.mjs`, `scripts/check-tailwind-colors.mjs`) to correctly ignore working directories (`bitvid-working-webtorrent`, `scripts/agent`), preventing CI failures.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-01 19:16:13 +00:00

139 lines
3.3 KiB
JavaScript
Executable File

#!/usr/bin/env node
import { readdir, readFile } from "node:fs/promises";
import path from "node:path";
import process from "node:process";
import { fileURLToPath } from "node:url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const repoRoot = path.resolve(__dirname, "..");
const TARGET_DIRECTORIES = ["components", "js", "views"];
const IGNORED_DIRECTORIES = new Set([
"ed-legacy",
"legacy",
"__snapshots__",
"bitvid-working-webtorrent",
]);
const LEGACY_ALLOWLIST = new Set([
"components/ed-/revert-video-modal.html",
"components/ed-/profile-modal.html",
]);
const COLOR_PATTERN =
/\b(?:text|bg|border|divide|ring|stroke|fill|outline|shadow|accent|placeholder)-(?:slate|gray|zinc|stone|neutral|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)(?:-[\w/]+)?\b/gim;
function toPosix(relPath) {
return relPath.split(path.sep).join("/");
}
async function collectFiles() {
const results = new Set();
for (const directory of TARGET_DIRECTORIES) {
const absolute = path.resolve(repoRoot, directory);
await walkDirectory(absolute, results);
}
return [...results];
}
async function walkDirectory(dir, results) {
let entries = [];
try {
entries = await readdir(dir, { withFileTypes: true });
} catch (error) {
return;
}
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
if (IGNORED_DIRECTORIES.has(entry.name)) {
continue;
}
await walkDirectory(fullPath, results);
continue;
}
if (!entry.isFile()) {
continue;
}
results.add(fullPath);
}
}
function buildLineIndex(content) {
const lines = [0];
let index = 0;
while ((index = content.indexOf("\n", index)) !== -1) {
lines.push(index + 1);
index += 1;
}
return lines;
}
function getLineNumber(indexes, matchIndex) {
let low = 0;
let high = indexes.length;
while (low < high) {
const mid = Math.floor((low + high) / 2);
if (indexes[mid] <= matchIndex) {
low = mid + 1;
} else {
high = mid;
}
}
return low;
}
async function main() {
const files = await collectFiles();
const violations = [];
for (const filePath of files) {
const rel = toPosix(path.relative(repoRoot, filePath));
if (LEGACY_ALLOWLIST.has(rel)) {
continue;
}
let content;
try {
content = await readFile(filePath, "utf8");
} catch (error) {
continue;
}
const lineIndex = buildLineIndex(content);
let match;
COLOR_PATTERN.lastIndex = 0;
while ((match = COLOR_PATTERN.exec(content))) {
const line = getLineNumber(lineIndex, match.index);
violations.push({
file: rel,
line,
value: match[0],
});
}
}
if (violations.length > 0) {
console.error("Tailwind color lint failed: raw palette classes detected.\n");
for (const violation of violations) {
console.error(`${violation.file}:${violation.line} → ${violation.value}`);
}
console.error(
"\nReplace raw tailwind colors with semantic utilities (text-muted, bg-status-warning-surface, etc.)."
);
process.exit(1);
}
process.exit(0);
}
main().catch((error) => {
console.error("Failed to check Tailwind color usage.");
console.error(error);
process.exit(1);
});