/* 472-3 헬퍼 — TS import 도달 집합(472-0 g472/graph.mjs 꼴 · 읽기만). * node helper_472_3_graph.mjs <저장소 뿌리> <입구.ts> [<입구.ts> …] * 입구마다 도달 파일(뿌리 상대 · `/`)을 JSON 한 벌로 표준출력 — 정적 import · export from · 동적 * import() · new URL(…, import.meta.url)(워커) · `import type` · `export type` 은 뺌(지워짐) · 정적 import · * export 는 줄 머리만(주석 속 「import」 낱말 안 셈). */ import fs from "node:fs"; import path from "node:path"; const [root, ...entries] = process.argv.slice(2); const alias = { "@ui/": "ui_template/", "@config/": "config/", "@util/": "common_util/" }; const rel = (p) => path.relative(root, p).split(path.sep).join("/"); const exists = (p) => { for (const c of [p, `${p}.ts`, `${p}/index.ts`]) if (fs.existsSync(c) && fs.statSync(c).isFile()) return c; return null; }; function resolve(from, spec) { let base; if (spec.startsWith(".")) base = path.resolve(path.dirname(from), spec); else { const a = Object.keys(alias).find((k) => spec.startsWith(k)); if (!a) return null; base = path.resolve(root, alias[a] + spec.slice(a.length)); } return exists(base.replace(/\.js$/, "")); } const re = /^\s*(?:import|export)\s+(?:type\s+)?(?:[^;"'`]*?\sfrom\s+)?["']([^"']+)["']|import\(\s*["']([^"']+)["']\s*\)|new URL\(\s*["']([^"']+)["']\s*,\s*import\.meta\.url/gm; function deps(file) { if (!/\.(ts|mts)$/.test(file)) return []; const src = fs.readFileSync(file, "utf8"); const out = []; for (const m of src.matchAll(re)) { if (/^\s*(?:import|export)\s+type\s/.test(m[0])) continue; const target = resolve(file, m[1] || m[2] || m[3]); if (target) out.push(target); } return out; } const result = {}; for (const entry of entries) { const seen = new Set(); const stack = [path.resolve(root, entry)]; while (stack.length) { const file = stack.pop(); if (seen.has(file)) continue; seen.add(file); stack.push(...deps(file)); } result[entry] = [...seen].map(rel).sort(); } process.stdout.write(JSON.stringify(result));