/* 506-3 B07 저장 길 헬퍼 — `_UI_Save` 를 Node 로 돌려 끊긴(abort) 저장 판정 · 저장 중 표 · 자동백업 열쇠 · * [초기화] 물음 글을 표준출력 JSON 한 벌로. 서버 길 · 알림 · 물음은 기록용 가짜. */ const fs = require("fs"); const path = require("path"); const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const B07 = path.join(__dirname, "..", "..", "B07_DesignDetail"); const calls = []; let confirmError = null; let listConfirmed = false; let savingSeen = null; let asked = ""; let Save; const STUBS = { "@ui/ui_template_elements": { showToast: (message, kind) => calls.push(["toast", kind]), showLoadingOverlay: () => calls.push(["overlay+"]), hideLoadingOverlay: () => calls.push(["overlay-"]), showConfirmDialog: async (message) => ((asked = message), calls.push(["ask"]), true), }, "./B07_DesignDetail_Api_Fetch": { confirmDesignDrawing: async (projectId, id) => { calls.push(["confirm", id]); savingSeen = Save.isSaving(); if (confirmError) throw confirmError; }, fetchDesignDrawingList: async () => { calls.push(["list"]); return { drawings: [{ id: "cross_s1", confirmed: listConfirmed }] }; }, invalidateDesignDrawing: async () => undefined, resetDesignDrawings: async () => ({ status: "success" }), }, }; global.localStorage = { removeItem: (key) => calls.push(["drop", key]) }; global.location = { reload: () => calls.push(["reload"]) }; global.document = { querySelectorAll: () => [] }; const { loadTs } = makeLoader({ root: path.join(__dirname, "..", ".."), cache: false, requireFor: (full) => { return (r) => STUBS[r] ?? {}; }, }); Save = loadTs(path.join(B07, "B07_DesignDetail_UI_Save.ts")); const storeOf = () => { let dirty = true; const tab = { id: "cross_s1", dirty }; return { projectId: "p1", drawings: [{ id: "cross_s1", kind: "cross", label: "횡단 1", confirmed: false }], tabs: { tabs: () => [tab], active: () => tab, markClean: (t) => ((t ?? tab).dirty = false), anyDirty: () => tab.dirty, }, current: () => ({ id: "cross_s1", kind: "cross", label: "횡단 1", confirmed: false }), cadDirty: () => dirty, setCadClean: () => (dirty = false), requestCad: async () => ({ drawing: {}, quantityTable: null }), isFrameEditing: () => false, forget: () => undefined, reload: async () => undefined, }; }; const take = () => calls.splice(0).map((c) => c.join(":")); const abort = () => new DOMException("The operation was aborted.", "AbortError"); (async () => { const out = {}; out.scope = Save.recoveryScopeOf("p1", "cross_s1"); await Save.saveDrawingsNow(storeOf(), () => calls.push(["saved"])); out.normal = { calls: take(), savingSeen, savingAfter: Save.isSaving() }; confirmError = abort(); listConfirmed = true; await Save.saveDrawingsNow(storeOf(), () => calls.push(["saved"])); out.abortSaved = { calls: take(), savingAfter: Save.isSaving() }; listConfirmed = false; await Save.saveDrawingsNow(storeOf(), () => calls.push(["saved"])); out.abortUnsaved = { calls: take(), savingAfter: Save.isSaving() }; confirmError = new Error("서버 오류"); listConfirmed = true; await Save.saveDrawingsNow(storeOf(), () => calls.push(["saved"])); out.otherError = take(); confirmError = null; await Save.resetDrawings(storeOf()); out.reset = { calls: take(), asked }; process.stdout.write(JSON.stringify(out)); })().catch((error) => { process.stderr.write(String(error && error.stack ? error.stack : error)); process.exit(1); });