Files
Aislo/resources/tester/helper_323_9_definition_stamp.cjs
T
eomsangdonandClaude Sonnet 5.5 156ce1cf52 test(508-1b 옛 헬퍼 공용 불러오기 3/7): 헬퍼 28 곳 loadTs 베낌 걷고 makeLoader 로
- 헬퍼 동작 그대로(풀이 함수 본문은 옮겨 담음) · 제품 코드 안 고침
- 확인: 이 묶음 헬퍼를 쓰는 시험 218 개 전 218 통과 → 후 218 통과 (시험별 junit 대조 · 어긋남 0)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-21 17:08:08 +09:00

106 lines
4.1 KiB
JavaScript

/* PLAN 323-9 ② — 정의 판 알림 되풀이. 진짜 `B05_Profile_Api_Structures.ts`(판 알림 · 정본 내보내기)를
* Node 로 돌림. 서버는 가짜 한 벌 — 구조물 PUT 이 지금 정의 판을 도장(진짜 저장소와 같음).
*/
const fs = require("fs");
const path = require("path");
const { makeLoader } = require("./helper_ts_stub_loader.cjs");
const CATALOG = require("./helper_322_catalog_module.cjs"); // 구조물 표(322-1)
const ROOT = path.join(__dirname, "..", "..");
const memory = () => {
const map = new Map();
return {
getItem: (key) => (map.has(key) ? map.get(key) : null),
setItem: (key, value) => map.set(key, String(value)),
removeItem: (key) => map.delete(key),
key: (index) => [...map.keys()][index] ?? null,
get length() {
return map.size;
},
};
};
globalThis.window = {
sessionStorage: memory(),
localStorage: memory(),
setTimeout: () => 0,
clearTimeout: () => undefined,
};
globalThis.sessionStorage = globalThis.window.sessionStorage;
// 가짜 서버 — 정의 판 21 · 프로젝트 정본은 판 20 으로 적힘
const NOW = 21;
const server = {
revision: 3,
structures: [{ structure_id: "s1", type_id: "retaining_wall", chainage_m: 40 }],
definition_version: 20,
};
const puts = [];
const reply = (body) => ({ ok: true, status: 200, json: async () => body });
globalThis.fetch = async (url, init = {}) => {
const at = url.replace(/^.*?(?=\/(m02|projects))/, "");
if (at === "/m02/structure-definition") return reply({ 판: NOW, types: [] });
if (at === "/projects/structure-types") return reply({ types: [] });
if (at.endsWith("/route/structures") && init.method === "PUT") {
const body = JSON.parse(init.body);
puts.push(body.structures.length);
Object.assign(server, {
revision: server.revision + 1,
structures: body.structures,
definition_version: NOW,
});
return reply({ revision: server.revision });
}
if (at.endsWith("/route/structures")) return reply({ ...server });
throw new Error(`모르는 요청 ${at}`);
};
const { loadTs } = makeLoader({
root: ROOT,
requireFor: (full) => (request) => {
if (CATALOG.isCatalogRequest(request)) return CATALOG;
if (request === "@config/config_frontend") return { API_BASE_URL: "", API_TIMEOUT_MS: 1000 };
if (request.endsWith(".json")) return require(path.join(path.dirname(full), request));
if (request.endsWith(".css")) return {};
if (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`));
if (request.startsWith("@")) return new Proxy({}, { get: () => () => undefined });
return require(request);
},
});
const api = loadTs(path.join(ROOT, "B05_Profile", "B05_Profile_Api_Structures.ts"));
// 472-6 — B06 [저장] = 한 본문 구조물 조각(옛 기본 창구 `flushPendingStructures` 걷음) · 서버 창구 = 가짜 PUT
async function saveLikeOneBody(projectId) {
const part = await api.structuresPart(projectId);
if (!part) return;
await api.saveStructures(projectId, part.body.base_revision, part.body.structures);
await part.after?.(undefined);
}
(async () => {
const P = "p1";
// 열기 — 종류(정의 판) · 정본(옛 판) → 알림 한 줄 · 옛 판 표시
await api.fetchStructureTypes(true);
const opened = await api.fetchStructures(P);
const notice = api.staleDefinitionNotice(P, opened.definition_version);
const staleOnOpen = api.definitionStale(P);
// 고침 없음 [저장](B06 기본 창구) — 정본을 그대로 다시 써 판 도장
await saveLikeOneBody(P);
const afterSave = { version: server.definition_version, puts: [...puts] };
// 다시 열기 — 알림 없음 · 또 [저장] 해도 안 나감
const reopened = await api.fetchStructures(P);
const again = api.staleDefinitionNotice("p1-새탭", reopened.definition_version);
api.staleDefinitionNotice(P, reopened.definition_version);
await saveLikeOneBody(P);
process.stdout.write(
JSON.stringify({
notice,
staleOnOpen,
afterSave,
again,
staleAfter: api.definitionStale(P),
putsAfterSecond: puts.length,
structures: server.structures,
}),
);
})();