/* ============================================================================= * common_util_spreadsheet_node.ts * 산출근거 스프레드시트 풀이를 **서버가** 돌리는 진입점 — [저장] 때 정본 `계산값`. * * 풀이는 화면이 쓰는 `A00_Common/spreadsheet/spreadsheet_recalc.ts` 그대로 — 여기에는 계산이 없음(CLAUDE.md 5장 ②). * 파이썬 껍데기 = `common_util_spreadsheet.py` · 번들 = `npm run build:spreadsheet`. * * 실행: node <번들> <입력.json> <출력.json> * 입력 { books?: Workbook[], tables?: TableAsk[] } * 출력 { results: ({ ok: true, 계산값 } | { ok: false, 까닭 })[], * tables: ({ ok: true, 표, 시트, 범위, 값 } | { ok: false, 까닭 })[] } — 입력 차례 그대로 · 하나가 죽어도 나머지는 풂 * 표(41-1) = 면적산출 시트 · 범위 → CAD 표 객체(TableEntity 꼴) — 풀이는 `A00_Common/spreadsheet/spreadsheet_area_table.ts` * (화면 도면 패널의 저장 전 실시간 표 값과 같은 코드 · 112-1) · 저장 안 함. * 끝 코드: 0 성공 / 2 인자 오류 * ⚠ `A00_Common/spreadsheet/` 밖에 둠 — node:fs 가 브라우저 번들로 새지 않게. * ========================================================================== */ import { readFileSync, writeFileSync } from "node:fs"; import { parseRange } from "../A00_Common/spreadsheet/spreadsheet_address"; import { areaTable, type TableAsk } from "../A00_Common/spreadsheet/spreadsheet_area_table"; import { recalcWorkbook } from "../A00_Common/spreadsheet/spreadsheet_recalc"; import type { Workbook } from "../A00_Common/spreadsheet/spreadsheet_types"; /** 면적 시트에 보낸 범위 이름을 더하거나(같은 이름 있으면) 범위를 갱신(104-1 · 도면 [저장] 때 새 연결 줄마다) */ interface NameAsk { book: Workbook; 시트: string; 범위: string; 이름: string; } /** 이름정의를 더하거나(있으면) 범위만 바꿈 — 책 사본을 돌려줌(저장은 python 쪽) */ function defineAreaName(ask: NameAsk): { book: Workbook } { const book = ask.book; const sheet = book.시트.find((s) => s.id === ask.시트) ?? book.시트.find((s) => s.이름 === ask.시트); if (!sheet) throw new Error(`없는 시트 「${ask.시트}」`); const range = parseRange(ask.범위); if (!range) throw new Error(`범위 꼴 아님 「${ask.범위}」`); const kept = (sheet.이름정의 ?? []).filter((n) => n.이름 !== ask.이름); sheet.이름정의 = [...kept, { 이름: ask.이름, 범위: range }]; return { book }; } const [inputPath, outputPath] = process.argv.slice(2); if (!inputPath || !outputPath) { console.error("사용법: node <번들> <입력.json> <출력.json>"); process.exit(2); } const input = JSON.parse(readFileSync(inputPath, "utf8")) as { books?: Workbook[]; tables?: TableAsk[]; names?: NameAsk[]; }; const results = (input.books ?? []).map((book) => { try { return { ok: true, 계산값: recalcWorkbook(book) }; } catch (error) { return { ok: false, 까닭: error instanceof Error ? error.message : String(error) }; } }); const tables = (input.tables ?? []).map((ask) => { try { return { ok: true, ...areaTable(ask) }; } catch (error) { return { ok: false, 까닭: error instanceof Error ? error.message : String(error) }; } }); const names = (input.names ?? []).map((ask) => { try { return { ok: true, ...defineAreaName(ask) }; } catch (error) { return { ok: false, 까닭: error instanceof Error ? error.message : String(error) }; } }); writeFileSync(outputPath, JSON.stringify({ results, tables, names }));