"""표 문서(마스터 템플릿 표 양식) 서버 재계산 — 화면과 같은 TS 를 Node 로 돌리는 껍데기. CLAUDE.md 5장 ② — 계산은 `ui_template/sheet/ui_template_sheet_recalc.ts` 한 벌. 여기는 번들을 부르기만 함(`npm run build:formula` → `config/formula_node/`). [저장] 때 브라우저 값을 받아 적지 않고 이 결과를 정본으로 씀. 결과 = `{계산: {줄: {열: 값}}, 합계: {합계줄: {열: 값}}, 오류: [{줄, 열, 까닭}]}` · 값은 십진 글. """ from __future__ import annotations from typing import Any from common_util.common_util_node_bundle import ROOT, build_bundle, run_bundle_json BUNDLE = ROOT / "config" / "formula_node" / "ui_template_sheet_node.js" NPM_SCRIPT = "build:formula" SOURCE_DIR = ROOT / "ui_template" / "sheet" def _stale() -> bool: """번들이 없거나 표 TS 원본보다 오래됐으면 참 — 낡으면 화면과 서버가 다른 값을 냄.""" if not BUNDLE.is_file(): return True built_at = BUNDLE.stat().st_mtime return any(p.stat().st_mtime > built_at for p in SOURCE_DIR.glob("*.ts")) def recalc_sheets(docs: list[dict[str, Any]]) -> list[dict[str, Any]] | None: """표 문서 여럿을 한 번에 — 입력 차례 그대로 결과. 번들 빌드·실행 실패는 None.""" if _stale() and not build_bundle(NPM_SCRIPT): return None out = run_bundle_json(BUNDLE, NPM_SCRIPT, {"docs": docs}) return None if out is None else out["results"] def recalc_sheet(doc: dict[str, Any]) -> dict[str, Any] | None: results = recalc_sheets([doc]) return None if results is None else results[0]