- POST /design/save 에 route(노선 초안) · carry(옛 노선 세션 칸) 칸 · 서버 = 노선 저장 → Node facility.rebase(rebasePipeDraft · rebaseStructureDraft) → 6-A 차례(새 노선) → Node stations.carry(routeCarryPatches) → 횡단 저장 - 되돌림 범위 = 노선 행 · 자식 표 · 단계 · 배수 폴더 · 노선 파일 · 지표면 확정(설계 지형 바꿈) - 손 상단측은 안 넘김(요구 274) · 노선 바뀐 [확정] = [저장](새 노선 본 뒤 다시) - 브라우저 = 노선 초안 + 사용자 칸만 한 본문 · 옛 차례 길(saveRouteDraft 뒤 flush · carryAfterRouteSave · keepDraftsOnNewRoute) · 부름 0 된 flush 창구 여섯 · saveCachedCrossPatches 걷음 - 등록부 R9 stations.carry · F10 facility.rebase · 옛 차례 단언 시험 한 본문 꼴로 · test_472_6_route_save(옛 길 = 새 길 · 실패 되돌림) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
127 lines
4.9 KiB
JavaScript
127 lines
4.9 KiB
JavaScript
/* PLAN 429 단위검증 헬퍼 — [저장] 길 정합.
|
|
* ④ 노선 저장 뒤 횡단 저장 = 고침이 없어도 한 번(472-6 6-B — 서버 한 본문 · 시험은 글 단언)
|
|
* ⑨ 추가 측점 = 계산 묶음 입력(`plusStations` · stations 부터) · 가게 초안 바뀜 → 묶음에 넣음(`feedFacilities`)
|
|
* TS 를 그 자리에서 트랜스파일해 Node 로 돌림 · 서버 창구 · 화면 모듈은 가짜. 짝 = `test_429_save_path.py`. */
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript"));
|
|
|
|
const ROOT = path.join(__dirname, "..", "..");
|
|
globalThis.window = { sessionStorage: null, localStorage: null, setTimeout, clearTimeout };
|
|
|
|
/** 아무 이름이나 받는 가짜 모듈 — 부르면 undefined. */
|
|
const anything = () =>
|
|
new Proxy({}, { get: (_target, key) => (key === "__esModule" ? false : () => undefined) });
|
|
|
|
function loader(stubs, real = () => false) {
|
|
const cache = new Map();
|
|
const load = (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 (stubs[request]) return stubs[request];
|
|
const target = path.join(path.dirname(full), `${request}.ts`);
|
|
if (request.startsWith(".") && real(target)) return load(target);
|
|
return anything();
|
|
};
|
|
new Function("exports", "module", "require", js)(box.exports, box, localRequire);
|
|
cache.set(full, box.exports);
|
|
return box.exports;
|
|
};
|
|
return load;
|
|
}
|
|
|
|
async function run() {
|
|
const out = {};
|
|
|
|
// ④ 노선 저장 뒤 횡단 저장 한 번 = 서버 한 본문 몫(472-6 6-B · test_429_save_path 글 단언)
|
|
|
|
// ⑨ 묶음 — 추가 측점이 바뀌면 stations 부터 · 같은 값이면 안 셈
|
|
const DESIGN = path.join(ROOT, "A00_Common", "design");
|
|
const pipeMod = loader({}, () => true)(path.join(DESIGN, "logic", "design_pipeline.ts"));
|
|
out.stationsDeps = pipeMod.STAGE_DEPS.stations;
|
|
const ran = [];
|
|
const stages = {};
|
|
for (const name of [...pipeMod.BROWSER_STAGES, ...pipeMod.AFTER_STAGES])
|
|
stages[name] = (ctx) => (ran.push(name), { name, plus: ctx.inputs.plusStations ?? null });
|
|
stages.follow = () => (ran.push("follow"), null); // 입력 고침 없음
|
|
const pipe = pipeMod.createDesignPipeline({ stages });
|
|
await pipe.start({
|
|
route: null,
|
|
alignment: null,
|
|
cross: null,
|
|
pipes: [],
|
|
structures: [],
|
|
plusStations: [],
|
|
});
|
|
ran.length = 0;
|
|
await pipe.update("plus", [40]);
|
|
out.plusRan = [...ran];
|
|
out.plusSeen = pipe.output("stations")?.plus ?? null;
|
|
ran.length = 0;
|
|
out.sameValue = pipe.update("plus", [40]); // 같은 값 = 차례 안 띄움(null)
|
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
out.sameRan = [...ran];
|
|
|
|
// ⑨ 먹이기 — 가게 추가 측점 초안이 바뀌면 묶음에 · 비면 저장분 · 되돌리기는 입력과 견줘 다를 때만
|
|
let restore = null;
|
|
const listeners = new Map();
|
|
const values = new Map();
|
|
const fakeStore = {
|
|
get: (key) => values.get(key) ?? null,
|
|
set: (key, value) => (
|
|
values.set(key, value),
|
|
(listeners.get(key) ?? []).forEach((fn) => fn(value))
|
|
),
|
|
subscribe: (key, fn) => {
|
|
listeners.set(key, [...(listeners.get(key) ?? []), fn]);
|
|
return () => undefined;
|
|
},
|
|
};
|
|
const fed = [];
|
|
const inputNow = { plusStations: [12] };
|
|
const feeder = loader({
|
|
"../../B05_Profile/B05_Profile_UI_Profile_History": {
|
|
onPageHistory: (hooks) => ((restore = hooks.restore), () => undefined),
|
|
pageReplaying: () => false, // 묶음 먹이기가 되돌리는 동안 구독을 거름(472-5)
|
|
},
|
|
"./design_save": { savingDesign: () => false },
|
|
})(path.join(DESIGN, "design_pipeline_facilities.ts"));
|
|
feeder.feedFacilities({
|
|
projectId: "p1",
|
|
store: fakeStore,
|
|
ready: () => true,
|
|
gone: () => false,
|
|
saved: (key) => (key === "plusStations" ? [12] : []),
|
|
input: (key) => inputNow[key] ?? null,
|
|
routed: () => false,
|
|
// 묶음처럼 받은 값이 입력이 됨 — 같은 값 다시 알림은 안 넣음(472-5)
|
|
feed: (source, value) => {
|
|
fed.push([source, value]);
|
|
if (source === "plus") inputNow.plusStations = value;
|
|
},
|
|
resync: async () => undefined,
|
|
});
|
|
fakeStore.set("plusStations", [12, 30]);
|
|
fakeStore.set("plusStations", null); // 초안 비움 = 저장분
|
|
out.fed = [...fed];
|
|
fed.length = 0;
|
|
values.set("plusStations", [12, 55]); // 되돌리기 = 세션만 되씀(알림 없음)
|
|
restore?.();
|
|
out.restoreFed = fed.filter(([source]) => source === "plus");
|
|
return out;
|
|
}
|
|
|
|
run().then(
|
|
(out) => console.log(JSON.stringify(out)),
|
|
(error) => {
|
|
console.error(error);
|
|
process.exit(1);
|
|
},
|
|
);
|