#!/usr/bin/env node import fs from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; export const DEFAULT_DB_LEGACY_DIRECTORY = "apps/web/app/utils/db"; const REACT_IMPORT_PATTERN = /(?:^|[\n;])\s*import(?:\s+type)?(?:[\s\S]*?\s+from\s*)?["']react(?:\/[^"']*)?["']/g; const ATTRIBUTE_LIKE_MARKUP_TAG_PATTERN = /<\s*\/?\s*[A-Za-z][A-Za-z0-9.:-]*(?:\s+[A-Za-z_:][\w:.-]*(?:\s*=\s*(?:"[^"]*"|'[^']*'|\{[^}]*\}))?)+\s*\/?>/g; const LOWERCASE_HTML_LIKE_TAG_PATTERN = /<\s*\/?\s*[a-z][A-Za-z0-9.:-]*\s*\/?>/g; const STRING_LITERAL_PATTERN = /`(?:\\[\s\S]|[^`\\])*`|"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'/g; const TYPE_CAST_TAG_PATTERN = /<\s*(?:const|keyof|infer|readonly|unique|abstract|new|typeof|[A-Z][A-Za-z0-9_$]*(?:\s+extends\s+[^=>]+)?)(?:\s*,[^>]*)?>\s*(?=[A-Za-z_$({[])/g; const TYPE_RETURN_TAG_PATTERN = /(?<=\bPromise\s*)<[^>]+>|(?<=\b(?:Partial|Pick|Omit|Record|Required|Readonly|Exclude|Extract|NonNullable|Awaited|Array|Set|Map)\s*)<[^>]+>/g; const FORBIDDEN_SOURCE_PATTERNS = [ { reason: "forbidden dangerouslySetInnerHTML marker", pattern: /\bdangerouslySetInnerHTML\b/g, }, { reason: "forbidden JSX.Element type", pattern: /\bJSX\.Element\b/g, }, { reason: "forbidden ReactNode type", pattern: /\bReactNode\b/g, }, { reason: "forbidden ReactElement type", pattern: /\bReactElement\b/g, }, { reason: "forbidden JSXFragment type", pattern: /\bJSXFragment\b/g, }, ]; function stripStringLiterals(source) { return source.replace(STRING_LITERAL_PATTERN, (literal) => " ".repeat(literal.length)); } function stripTypeOnlyTags(source) { return source .replace(TYPE_CAST_TAG_PATTERN, (tag) => " ".repeat(tag.length)) .replace(TYPE_RETURN_TAG_PATTERN, (tag) => " ".repeat(tag.length)); } function hasJsxLikeMarkupTag(source) { ATTRIBUTE_LIKE_MARKUP_TAG_PATTERN.lastIndex = 0; if (ATTRIBUTE_LIKE_MARKUP_TAG_PATTERN.test(source)) { return true; } LOWERCASE_HTML_LIKE_TAG_PATTERN.lastIndex = 0; let match; while ((match = LOWERCASE_HTML_LIKE_TAG_PATTERN.exec(source))) { const afterTag = source.slice(LOWERCASE_HTML_LIKE_TAG_PATTERN.lastIndex).trimStart(); if (match[0].includes("/") || afterTag.startsWith(" 0) { return [ "FAIL DB legacy markup verification", ...result.failures.map((failure) => `- ${failure}`), `Summary: ${result.filesScanned} files scanned, ${result.failures.length} failed`, "", ].join("\n"); } return [ "PASS DB legacy markup verification", `Summary: ${result.filesScanned} files scanned, 0 failed`, "", ].join("\n"); } const isCli = process.argv[1] && fileURLToPath(import.meta.url) === path.resolve(process.argv[1]); if (isCli) { const result = verifyDbLegacyMarkup(process.cwd()); const output = formatDbLegacyMarkupResult(result); if (result.failures.length > 0) { process.stderr.write(output); process.exitCode = 1; } else { process.stdout.write(output); } }