/* 520-7 배수유역 저장분 받기 헬퍼 — `B05_Profile_UI_Drainage_Saved.ts` · `_Run.ts` 를 그 자리에서 * 트랜스파일해 가짜 fetch 로 돌리고 단계별 GET 수 · 「올렸나」를 JSON 으로 냄. */ const fs = require("fs"); const path = require("path"); const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); const B05 = path.join(__dirname, "..", "..", "B05_Profile"); /* ---- 가짜 저장분 GET(답은 시험이 정할 때) ---- */ const gets = []; let pending = null; // 세션 관 초안 const detailCalls = []; const stubs = { "../B04_PreProcess/B04_PreProcess_Api_Fetch": { fetchDetailPipePoints: () => new Promise((resolve) => gets.push(resolve)), computeDetailBasins: async (_projectId, points) => ( detailCalls.push(points), { basins: [], pipe_points: points, stale: null } ), }, "./B05_Profile_Api_Pipes_Draft": { readPendingPipes: () => pending }, "./B05_Profile_UI_Drainage_Parts": { analyzeFailed: (_error, fallback) => fallback }, }; const cache = new Map(); function load(file) { if (cache.has(file)) return cache.get(file); const js = ts.transpileModule(fs.readFileSync(file, "utf8"), { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 }, }).outputText; const box = { exports: {} }; cache.set(file, box.exports); const local = (name) => { if (stubs[name]) return stubs[name]; if (name.startsWith(".")) return load(path.join(path.dirname(file), `${name}.ts`)); return require(name); }; new Function("exports", "module", "require", js)(box.exports, box, local); return box.exports; } const { createSavedLoader } = load(path.join(B05, "B05_Profile_UI_Drainage_Saved.ts")); const { createDetailRunner } = load(path.join(B05, "B05_Profile_UI_Drainage_Run.ts")); const flush = async () => { for (let i = 0; i < 10; i += 1) await new Promise((r) => setImmediate(r)); }; const el = () => ({ hidden: false, textContent: "", disabled: false }); async function main() { const out = {}; let pipes = [{ chainage_m: 386, source: "stream" }]; const shown = []; let loader; const runner = createDetailRunner({ projectId: () => "p1", updateButton: el(), status: el(), showProgress: () => undefined, apply: (response) => (shown.push(response), loader.applied(response)), // 패널 takePipes 와 같은 줄 basinCount: () => 1, scheduleDraw: () => undefined, label: (key) => key, }); loader = createSavedLoader(runner, () => pipes); const answer = (tag) => ({ tag, basins: [], pipe_points: pipes, stale: null }); const results = []; const keep = (promise) => promise.then((ok) => results.push(ok)); // 열 때 — GET 한 번 keep(loader.run()); await flush(); gets[0](answer("saved1")); await flush(); out.open = { gets: gets.length, results: [...results], matches: loader.matches() }; // 되돌리기 ① — 관 자리가 노선 따라 옮겨진 뒤(몸통 다름): 관 자리 되돌림 · reload · 초안 버림 한 번에 pipes = [{ chainage_m: 386.4, source: "stream" }]; results.length = 0; const before = gets.length; keep(loader.matches() ? Promise.resolve(true) : loader.run(true)); // setPipeChainages(null) keep(loader.run()); // followFacilities → reload() keep(loader.back()); // 묶음 초안 버림 → backToSaved await flush(); pipes = [{ chainage_m: 386, source: "stream" }]; gets[gets.length - 1](answer("saved2")); await flush(); out.undoMoved = { gets: gets.length - before, results: [...results], shown: shown.at(-1).tag }; // 되돌리기 ② — 화면이 저장분 그대로 · 초안 버림이 먼저 오고 reload 가 뒤따름 results.length = 0; const before2 = gets.length; const shownBefore = shown.length; keep(loader.back()); keep(loader.run()); await flush(); gets[gets.length - 1](answer("saved3")); await flush(); out.backThenReload = { gets: gets.length - before2, results: [...results], shown: shown.slice(shownBefore).map((r) => r.tag), }; // 초안 버림만 — 화면이 저장분 그대로면 GET 없이 그 답을 다시 올림 results.length = 0; const before3 = gets.length; keep(loader.back()); await flush(); out.backOnly = { gets: gets.length - before3, results: [...results], shown: shown.at(-1).tag }; // 다른 답(지금 노선 [업데이트] 등)이 오른 뒤 초안 버림 — 다시 받음 await runner.run(async () => answer("live"), true); results.length = 0; const before4 = gets.length; keep(loader.back()); await flush(); gets[gets.length - 1](answer("saved4")); await flush(); out.afterLive = { gets: gets.length - before4, results: [...results], shown: shown.at(-1).tag }; // 세션 관 초안이 있으면 그 관 목록으로(GET 아님) pending = [{ chainage_m: 500, source: "user" }]; const before5 = gets.length; results.length = 0; keep(loader.run(true)); await flush(); out.pending = { gets: gets.length - before5, detail: detailCalls.length, results: [...results] }; process.stdout.write(JSON.stringify(out)); } main().catch((error) => { process.stderr.write(String(error && error.stack ? error.stack : error)); process.exit(1); });