/* 54-12 빈 필수 칸 실시간 반영 헬퍼 — `_Structures_Panel_Commit.commit` 을 Node 로 돌려 * 결과를 표준출력 JSON 한 벌로. 화면 그림은 안 씀(ORCA 가 따로 봄). * TS 로더는 `helper_54_9_etc_pill.cjs` 와 같다. */ const fs = require("fs"); const path = require("path"); const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); const CATALOG = require("./helper_322_catalog_module.cjs"); // 구조물 표(322-1) const ROOT = path.join(__dirname, "..", ".."); const cache = new Map(); const session = new Map(); const fakeStorage = { getItem: (k) => session.get(k) ?? null, setItem: (k, v) => session.set(k, String(v)), removeItem: (k) => session.delete(k), }; globalThis.window = { sessionStorage: fakeStorage, localStorage: fakeStorage }; globalThis.sessionStorage = fakeStorage; globalThis.localStorage = fakeStorage; const STUBS = { "@config/config_frontend": { API_BASE_URL: "/api", API_TIMEOUT_MS: 1000 }, "./ui_template_checkbox.css": {}, }; function loadTs(file) { const full = path.resolve(file); if (cache.has(full)) return cache.get(full); const js = ts.transpileModule(fs.readFileSync(full, "utf8"), { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 }, }).outputText; const box = { exports: {} }; cache.set(full, box.exports); const localRequire = (request) => { if (CATALOG.isCatalogRequest(request)) return CATALOG; if (STUBS[request]) return STUBS[request]; if (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`)); if (request.startsWith("@")) return new Proxy({}, { get: () => () => {} }); return require(request); }; new Function("exports", "module", "require", js)(box.exports, box, localRequire); cache.set(full, box.exports); return box.exports; } const { commit } = loadTs( path.join(ROOT, "B05_Profile", "B05_Profile_UI_Structures_Panel_Commit.ts"), ); const type = { type_id: "stone_wall_test", name: "돌쌓기(찰)", group: "C", placement: "point", options: [ { key: "height_m", label: "높이", input: "number" }, { key: "back_length_m", label: "뒷길이", input: "number", required: true, phase: "detail" }, ], }; function run(live, height) { const focused = []; const entry = (key, value, required) => { const input = { value, focus: () => focused.push(key), classList: { add() {} } }; return { key, required, input, read: () => Number(input.value) || 0, isEmpty: () => input.value.trim() === "", }; }; const structures = [ { structure_id: "s1", type_id: type.type_id, placement: "point", chainage_m: 80, options: { height_m: 1.5 }, }, ]; const changes = []; const anchor = { read: () => 100, station: { focus: () => focused.push("anchor") } }; const ctx = { callbacks: { onChange: (next) => changes.push(next) }, structures, memoField: { value: "" }, anchorFields: anchor, startFields: anchor, endFields: anchor, optionRow: null, optionInputs: [entry("height_m", String(height), false), entry("back_length_m", "", true)], pipeFacilities: () => [], interval: () => 20, typeMap: () => new Map([[type.type_id, type]]), currentType: () => type, facilityFormKind: () => null, hasComputedRange: () => false, summary: () => null, editingId: () => "s1", groupBoxes: { get: () => ({}), shapes: () => ({}), shapeKeys: () => [] }, renderList: () => {}, cancelTempPipe: () => {}, }; return commit(ctx, live).then(() => ({ changes: changes.length, height: structures[0].options.height_m, chainage: structures[0].chainage_m, hasBack: "back_length_m" in structures[0].options, focused, })); } Promise.all([run(true, 3.2), run(false, 3.2)]).then(([live, button]) => { process.stdout.write(JSON.stringify({ live, button })); });