import { parseSync } from "oxc-parser"; // Shared ESTree helpers for the repository's structural checks. The native // TypeScript (Go) toolchain ships no programmatic compiler API, so scripts parse // with oxc-parser and walk the ESTree result directly. /** Minimal ESTree node shape used by the structural checks. */ export type EsNode = { type: string; [key: string]: unknown }; /** Parse a source file into its ESTree program; language is inferred from the path. */ export function parseModule(file: string, text: string): EsNode { return parseSync(file, text).program as unknown as EsNode; } /** * The string value of a string `Literal` or a no-substitution template literal, * else undefined. Minified output rewrites `import("x")` to `` import(`x`) ``, so * import-specifier checks must accept both. */ export function literalString( node: EsNode | null | undefined, ): string | undefined { if (!node) return undefined; if (node.type === "Literal" && typeof node["value"] === "string") return node["value"]; if ( node.type === "TemplateLiteral" && Array.isArray(node["expressions"]) && node["expressions"].length === 0 ) { const quasi = (node["quasis"] as EsNode[] | undefined)?.[0]; const cooked = (quasi?.["value"] as { cooked?: unknown } | undefined) ?.cooked; return typeof cooked === "string" ? cooked : undefined; } return undefined; } /** Depth-first visit of every typed node in an ESTree tree. */ export function walkEs(node: unknown, visit: (node: EsNode) => void): void { if (!node || typeof node !== "object") return; if (Array.isArray(node)) { for (const child of node) walkEs(child, visit); return; } const record = node as Record; if (typeof record["type"] === "string") visit(record as EsNode); for (const key of Object.keys(record)) if (key !== "type") walkEs(record[key], visit); }