diff --git a/common_util/common_util_node_bundle.py b/common_util/common_util_node_bundle.py index 1a5e6e022..d8de92f8f 100644 --- a/common_util/common_util_node_bundle.py +++ b/common_util/common_util_node_bundle.py @@ -19,13 +19,21 @@ from typing import Any logger = logging.getLogger(__name__) ROOT = Path(__file__).resolve().parents[1] -# 번들이 낡았는지 재는 대상 — 기하 계통이 걸쳐 있는 폴더 + 구조물도 식 풀이(B08, 2026-09-13). -SOURCE_DIRS = ("B05_Profile", "B06_Section", "B08_Quantity", "common_util") +# 번들이 낡았는지 재는 대상 — 기하 계통이 걸쳐 있는 폴더 + 구조물도 식 풀이(B08, 2026-09-13) · +# 묶음이 끌어가는 화면 공용(ui_template · A00_Common b_page_state · design) · 하위 폴더째. +SOURCE_DIRS = ( + "B05_Profile", + "B06_Section", + "B08_Quantity", + "common_util", + "ui_template", + "A00_Common", +) # 번들에 박히는 자료(JSON) — 벽 전면 기울기 표준경사 표·기슭막이 치수 표(2026-09-14 B5). 표만 바뀌어도 다시 빌드. SOURCE_DATA_DIRS = ("resources/data_masonry",) # 폴더째 훑지 않는 자리 — B07 은 CAD 앱(openwebcad · node_modules)이 함께 살아 맨 위 TS 만 본다 · -# 구조물 명세(A00 design)는 B07 CAD 칸 옵션 줄 번들이 끌어 씀(166-1). -SOURCE_GLOBS = ("B07_DesignDetail/*.ts", "A00_Common/design/*.ts") +# config 는 node_modules 가 함께 살아 맨 위 TS(config_frontend)만. +SOURCE_GLOBS = ("B07_DesignDetail/*.ts", "config/*.ts") # 번들 만들기·실행 상한(초). 실측 번들 실행 0.1초, 빌드 3초 수준이라 넉넉하다. BUILD_TIMEOUT_S = 300 RUN_TIMEOUT_S = 600 @@ -51,7 +59,7 @@ def bundle_stale(bundle: Path) -> bool: built_at = bundle.stat().st_mtime for directory in SOURCE_DIRS: for path in (ROOT / directory).rglob("*.ts"): - if path.stat().st_mtime > built_at: + if "node_modules" not in path.parts and path.stat().st_mtime > built_at: return True for directory in SOURCE_DATA_DIRS: for path in (ROOT / directory).glob("*.json"): diff --git a/resources/tester/test_342_4_bundle_stale.py b/resources/tester/test_342_4_bundle_stale.py new file mode 100644 index 000000000..39cee8cbb --- /dev/null +++ b/resources/tester/test_342_4_bundle_stale.py @@ -0,0 +1,68 @@ +"""342-4 서버 Node 묶음 낡음 판정 — 묶음이 끌어가는 화면 공용 · config · 새 logic/ 하위 폴더도 잡음. + + ./venv/Scripts/python.exe -m pytest resources/tester/test_342_4_bundle_stale.py -q +""" + +import os +from pathlib import Path + +import pytest + +from common_util import common_util_node_bundle as nb + +BUILT_AT = 1_000_000_000 + + +@pytest.fixture +def tree(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Path: + monkeypatch.setattr(nb, "ROOT", tmp_path) + bundle = tmp_path / "dist" / "bundle.mjs" + bundle.parent.mkdir() + bundle.write_text("", encoding="utf-8") + os.utime(bundle, (BUILT_AT, BUILT_AT)) + return bundle + + +def _touch(root: Path, rel: str, when: int) -> None: + path = root / rel + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text("", encoding="utf-8") + os.utime(path, (when, when)) + + +@pytest.mark.parametrize( + "rel", + [ + "B05_Profile/logic/B05_Profile_Footprint.ts", + "B06_Section/logic/B06_Section_Xxx.ts", + "ui_template/b_notice.ts", + "ui_template/locale/b_text.ts", + "A00_Common/b_page_state.ts", + "A00_Common/design/design_store.ts", + "config/config_frontend.ts", + "common_util/common_util_cross_design.ts", + "B07_DesignDetail/B07_DesignDetail_UI_Cad.ts", + ], +) +def test_새로_고친_TS_는_낡음(tree: Path, rel: str) -> None: + _touch(nb.ROOT, rel, BUILT_AT + 10) + assert nb.bundle_stale(tree) + + +def test_오래된_TS_뿐이면_그대로(tree: Path) -> None: + _touch(nb.ROOT, "B05_Profile/logic/B05_Profile_Footprint.ts", BUILT_AT - 10) + _touch(nb.ROOT, "ui_template/b_notice.ts", BUILT_AT - 10) + assert not nb.bundle_stale(tree) + + +@pytest.mark.parametrize( + "rel", + [ + "config/node_modules/typescript/lib/x.d.ts", + "A00_Common/config/node_modules/.vite/deps/x.ts", + "B07_DesignDetail/openwebcad/src/x.ts", + ], +) +def test_node_modules_CAD_앱은_안_봄(tree: Path, rel: str) -> None: + _touch(nb.ROOT, rel, BUILT_AT + 10) + assert not nb.bundle_stale(tree)