diff --git a/resources/tester/helper_344_3_pipeline_stations.cjs b/resources/tester/helper_344_3_pipeline_stations.cjs index b7508c923..05864f5d3 100644 --- a/resources/tester/helper_344_3_pipeline_stations.cjs +++ b/resources/tester/helper_344_3_pipeline_stations.cjs @@ -4,26 +4,13 @@ * 짝 = `test_344_3_pipeline_stations_mirror.py`. */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const CATALOG = require("./helper_322_catalog_module.cjs"); // 구조물 표(322-1) const ROOT = path.join(__dirname, "..", ".."); -const cache = new Map(); -function loadTs(full) { - 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 (CATALOG.isCatalogRequest(request)) return CATALOG; - if (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`)); - return require(request); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - return box.exports; -} +const { loadTs } = makeLoader({ + root: ROOT, +}); const logic = loadTs(path.join(ROOT, "B05_Profile", "logic", "B05_Profile_Sections_Stations.ts")); const stage = loadTs( diff --git a/resources/tester/helper_344_4_design_pipeline.cjs b/resources/tester/helper_344_4_design_pipeline.cjs index 19e39415b..b2b9ce1c3 100644 --- a/resources/tester/helper_344_4_design_pipeline.cjs +++ b/resources/tester/helper_344_4_design_pipeline.cjs @@ -4,7 +4,7 @@ * 짝 = `test_344_4_design_pipeline.py`. */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); @@ -24,23 +24,13 @@ const session = memoryStorage(); globalThis.window = { sessionStorage: session, localStorage: memoryStorage() }; globalThis.fetch = async () => ({ ok: false }); -const cache = new Map(); -function loadTs(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) => +const { loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => (request) => request.startsWith(".") ? loadTs(path.join(path.dirname(full), `${request}.ts`)) - : require(request); - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - cache.set(full, box.exports); - return box.exports; -} + : require(request), +}); const DESIGN = path.join(ROOT, "A00_Common", "design"); const pipeMod = loadTs(path.join(DESIGN, "logic/design_pipeline.ts")); diff --git a/resources/tester/helper_345_2_3d_modal.cjs b/resources/tester/helper_345_2_3d_modal.cjs index 2bda4f7c1..c0732987d 100644 --- a/resources/tester/helper_345_2_3d_modal.cjs +++ b/resources/tester/helper_345_2_3d_modal.cjs @@ -4,7 +4,7 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); @@ -78,15 +78,11 @@ const STUBS = { }, }; -function loadTs(file) { - const js = ts.transpileModule(fs.readFileSync(file, "utf8"), { - compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 }, - }).outputText; - const box = { exports: {} }; - const localRequire = (request) => STUBS[request] ?? require(request); - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - return box.exports; -} +const { loadTs } = makeLoader({ + root: ROOT, + cache: false, + requireFor: (full) => (request) => STUBS[request] ?? require(request), +}); const { createViewer3dModal } = loadTs( path.join(ROOT, "A00_Common", "design", "design_view_profile_3d_modal.ts"), diff --git a/resources/tester/helper_345_3_undo_owner.cjs b/resources/tester/helper_345_3_undo_owner.cjs index 2dd4a7671..4c3ddce37 100644 --- a/resources/tester/helper_345_3_undo_owner.cjs +++ b/resources/tester/helper_345_3_undo_owner.cjs @@ -4,7 +4,7 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); const listeners = {}; @@ -14,22 +14,13 @@ global.window = { }; const fire = (type, event) => [...(listeners[type] ?? [])].forEach((fn) => fn(event)); -const cache = new Map(); -function loadTs(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) => +const { loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => (request) => request.startsWith(".") ? loadTs(`${path.resolve(path.dirname(full), request)}.ts`) - : require(request); - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - return box.exports; -} + : require(request), +}); const page = path.join(ROOT, "B05_Profile"); const { bindHistoryControls } = loadTs(path.join(page, "B05_Profile_UI_RouteEdit_History.ts")); diff --git a/resources/tester/helper_346_1_pipeline_page.cjs b/resources/tester/helper_346_1_pipeline_page.cjs index ab9a7dc42..48f7f6f75 100644 --- a/resources/tester/helper_346_1_pipeline_page.cjs +++ b/resources/tester/helper_346_1_pipeline_page.cjs @@ -5,7 +5,7 @@ * 결과 = 표준출력 JSON 한 벌. 짝 = `test_346_1_pipeline_page.py`. */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const CATALOG = require("./helper_322_catalog_module.cjs"); const ROOT = path.join(__dirname, "..", ".."); @@ -28,15 +28,9 @@ globalThis.window = { sessionStorage: session, localStorage: memoryStorage() }; globalThis.fetch = async () => ({ ok: false }); const STUBS = {}; -const cache = new Map(); -function loadTs(full) { - 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) => { +const { load, loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => (request) => { if (CATALOG.isCatalogRequest(request)) return CATALOG; const key = Object.keys(STUBS).find((name) => request.endsWith(name)); if (key) return STUBS[key]; @@ -44,11 +38,8 @@ function loadTs(full) { return loadTs(path.join(ROOT, "common_util", `${request.slice(6)}.ts`)); if (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`)); return require(request); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - return box.exports; -} -const load = (...parts) => loadTs(path.join(ROOT, ...parts)); + }, +}); const sampler = load("common_util", "common_util_surface_sampler.ts"); const bytes = fs.readFileSync(process.argv[3]); diff --git a/resources/tester/helper_346_2_draft_cross_pills.cjs b/resources/tester/helper_346_2_draft_cross_pills.cjs index c51153bc2..8c25fc387 100644 --- a/resources/tester/helper_346_2_draft_cross_pills.cjs +++ b/resources/tester/helper_346_2_draft_cross_pills.cjs @@ -5,7 +5,7 @@ * 결과 = 표준출력 JSON. 짝 = `test_346_2_draft_cross_pills.py`. */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); const P = "p3463"; @@ -63,15 +63,9 @@ const STUBS = { }, }; -const cache = new Map(); -function loadTs(full) { - 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) => { +const { load, loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => (request) => { const key = Object.keys(STUBS).find((name) => request.endsWith(name)); if (key) return STUBS[key]; if (request.endsWith("config_frontend") || request.startsWith("@config/")) @@ -80,11 +74,8 @@ function loadTs(full) { return loadTs(path.join(ROOT, "common_util", `${request.slice(6)}.ts`)); if (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`)); return require(request); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - return box.exports; -} -const load = (...parts) => loadTs(path.join(ROOT, ...parts)); + }, +}); const pipeMod = load("A00_Common", "design", "logic", "design_pipeline.ts"); const storeMod = load("A00_Common", "design", "design_store.ts"); diff --git a/resources/tester/helper_346_3_route_save.cjs b/resources/tester/helper_346_3_route_save.cjs index 35d83f333..0b860674c 100644 --- a/resources/tester/helper_346_3_route_save.cjs +++ b/resources/tester/helper_346_3_route_save.cjs @@ -3,7 +3,7 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); @@ -70,23 +70,14 @@ const STUBS = { }, }; -const cache = new Map(); -function loadTs(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) => { +const { loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => (request) => { if (STUBS[request]) return STUBS[request]; if (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`)); return require(request); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - return box.exports; -} + }, +}); const { useDesignStore } = loadTs(path.join(ROOT, "A00_Common", "design", "design_store.ts")); const { readState, writeState } = loadTs(path.join(ROOT, "A00_Common", "b_page_state.ts")); diff --git a/resources/tester/helper_346_4_design_leave.cjs b/resources/tester/helper_346_4_design_leave.cjs index 57b410461..16a4eb96f 100644 --- a/resources/tester/helper_346_4_design_leave.cjs +++ b/resources/tester/helper_346_4_design_leave.cjs @@ -3,7 +3,7 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); @@ -59,21 +59,17 @@ const STUBS = { }, }; -function loadTs(file) { - const js = ts.transpileModule(fs.readFileSync(file, "utf8"), { - compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 }, - }).outputText; - const box = { exports: {} }; - const localRequire = (request) => { +const { loadTs } = makeLoader({ + root: ROOT, + cache: false, + requireFor: (full, file) => (request) => { if (request in STUBS) return STUBS[request]; if (request === "@ui/ui_template_window_watch") return loadTs(path.join(ROOT, "ui_template", "ui_template_window_watch.ts")); if (request.startsWith(".")) return loadTs(path.join(path.dirname(file), `${request}.ts`)); return require(request); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - return box.exports; -} + }, +}); const leave = loadTs(path.join(ROOT, "A00_Common", "design", "design_leave.ts")); const P = "p1"; diff --git a/resources/tester/helper_346_4_one_undo.cjs b/resources/tester/helper_346_4_one_undo.cjs index 198db7c34..5a1308058 100644 --- a/resources/tester/helper_346_4_one_undo.cjs +++ b/resources/tester/helper_346_4_one_undo.cjs @@ -4,7 +4,7 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); const data = new Map(); @@ -24,22 +24,13 @@ win.sessionStorage = globalThis.sessionStorage; win.localStorage = { getItem: (k) => (k === "frd_current_project_id" ? "p1" : null) }; // 연 프로젝트(387-1) globalThis.window = win; -const cache = new Map(); -function loadTs(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) => +const { loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => (request) => request.startsWith(".") ? loadTs(`${path.resolve(path.dirname(full), request)}.ts`) - : require(request); - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - return box.exports; -} + : require(request), +}); const page = path.join(ROOT, "B05_Profile"); const album = loadTs(path.join(page, "B05_Profile_UI_Profile_History.ts")); const edit = loadTs(path.join(page, "B05_Profile_UI_RouteEdit_History.ts")); diff --git a/resources/tester/helper_347_2_drainage_live.cjs b/resources/tester/helper_347_2_drainage_live.cjs index ab70c09ca..22dc10d7c 100644 --- a/resources/tester/helper_347_2_drainage_live.cjs +++ b/resources/tester/helper_347_2_drainage_live.cjs @@ -3,18 +3,15 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); -function loadTs(file) { - const js = ts.transpileModule(fs.readFileSync(file, "utf8"), { - compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 }, - }).outputText; - const box = { exports: {} }; - new Function("exports", "module", "require", js)(box.exports, box, require); - return box.exports; -} +const { loadTs } = makeLoader({ + root: ROOT, + cache: false, + requireFor: () => require, +}); const live = loadTs(path.join(ROOT, "B05_Profile", "logic", "B05_Profile_Drainage_Live.ts")); const sug = loadTs(path.join(ROOT, "B05_Profile", "logic", "B05_Profile_Drainage_Suggest.ts")); diff --git a/resources/tester/helper_352_3_terrain.cjs b/resources/tester/helper_352_3_terrain.cjs index 1bb86fc36..6c2dea39c 100644 --- a/resources/tester/helper_352_3_terrain.cjs +++ b/resources/tester/helper_352_3_terrain.cjs @@ -3,7 +3,7 @@ * 결과 = 표준출력 JSON 한 벌. 짝 = `test_352_3_analysis_terrain_default.py`. */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); const store = new Map(); @@ -17,22 +17,14 @@ const STUBS = { common_util_surface_sampler: { heightAt: () => 0 }, B05_Profile_Api_TerrainGrid: { loadDesignTerrainGrid: async () => null }, }; -const cache = new Map(); -function loadTs(full) { - 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) => { +const { loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => (request) => { const key = Object.keys(STUBS).find((name) => request.endsWith(name)); if (key) return STUBS[key]; return require(request); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - return box.exports; -} + }, +}); const api = loadTs(path.join(ROOT, "B05_Profile", "B05_Profile_Api_Replan.ts")); const out = {}; diff --git a/resources/tester/helper_355_1_pivot_tilt.cjs b/resources/tester/helper_355_1_pivot_tilt.cjs index 206f98170..a3af56928 100644 --- a/resources/tester/helper_355_1_pivot_tilt.cjs +++ b/resources/tester/helper_355_1_pivot_tilt.cjs @@ -6,26 +6,12 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); -const cache = new Map(); -function loadTs(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 (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`)); - return require(request); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - cache.set(full, box.exports); - return box.exports; -} +const { loadTs } = makeLoader({ + root: ROOT, +}); const LOGIC = path.join(ROOT, "B05_Profile", "logic"); const align = loadTs(path.join(LOGIC, "B05_Profile_UI_Profile_Alignment.ts")); diff --git a/resources/tester/helper_356_4_undo_grade.cjs b/resources/tester/helper_356_4_undo_grade.cjs index db10665fc..96f614fcf 100644 --- a/resources/tester/helper_356_4_undo_grade.cjs +++ b/resources/tester/helper_356_4_undo_grade.cjs @@ -6,7 +6,7 @@ * argv[4] = "off" 면 되살림 표시를 끔(옛 동작 대조). 결과 = 표준출력 JSON. 짝 = `test_356_4_undo_grade.py`. */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const CATALOG = require("./helper_322_catalog_module.cjs"); const ROOT = path.join(__dirname, "..", ".."); @@ -53,14 +53,9 @@ globalThis.fetch = (url, init) => const STUBS = {}; const cache = new Map(); -function loadTs(full) { - 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) => { +const { load, loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => (request) => { if (CATALOG.isCatalogRequest(request)) return CATALOG; const key = Object.keys(STUBS).find((name) => request.endsWith(name)); if (key) return STUBS[key]; @@ -72,11 +67,8 @@ function loadTs(full) { return loadTs(path.join(ROOT, "common_util", `${request.slice(6)}.ts`)); if (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`)); return require(request); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - return box.exports; -} -const load = (...parts) => loadTs(path.join(ROOT, ...parts)); + }, +}); const sampler = load("common_util", "common_util_surface_sampler.ts"); const bytes = fs.readFileSync(process.argv[3]); diff --git a/resources/tester/helper_356_center.cjs b/resources/tester/helper_356_center.cjs index dc89b9094..8255df5cc 100644 --- a/resources/tester/helper_356_center.cjs +++ b/resources/tester/helper_356_center.cjs @@ -4,10 +4,9 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); -const cache = new Map(); const STUBS = { "@ui/ui_template_toast": { showToast: () => undefined }, "@ui/ui_template_elements": { showToast: () => undefined }, @@ -124,24 +123,10 @@ globalThis.document = { }; globalThis.window = { setTimeout, clearTimeout, addEventListener: () => {} }; -function loadTs(file) { - const full = path.resolve(file); - if (cache.has(full)) return cache.get(full); - if (full.endsWith(".json")) { - const data = JSON.parse(fs.readFileSync(full, "utf8")); - cache.set(full, data); - return data; - } - const js = ts.transpileModule(fs.readFileSync(full, "utf8"), { - compilerOptions: { - module: ts.ModuleKind.CommonJS, - target: ts.ScriptTarget.ES2020, - esModuleInterop: true, - }, - }).outputText; - const box = { exports: {} }; - cache.set(full, box.exports); - const localRequire = (request) => { +const { loadTs } = makeLoader({ + root: ROOT, + interop: true, + requireFor: (full) => (request) => { if (STUBS[request]) return STUBS[request]; if (request.endsWith(".css")) return {}; const alias = { "@util/": "common_util", "@ui/": "ui_template", "@config/": "config" }; @@ -149,11 +134,8 @@ function loadTs(file) { if (request.startsWith(prefix)) return loadTs(resolve(path.join(ROOT, dir, request.slice(prefix.length)))); return loadTs(resolve(path.join(path.dirname(full), request))); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - cache.set(full, box.exports); - return box.exports; -} + }, +}); const resolve = (base) => [base, `${base}.ts`, path.join(base, "index.ts")].find( (p) => fs.existsSync(p) && fs.statSync(p).isFile(), diff --git a/resources/tester/helper_365_page_pipeline.cjs b/resources/tester/helper_365_page_pipeline.cjs index fc23318d8..34613542d 100644 --- a/resources/tester/helper_365_page_pipeline.cjs +++ b/resources/tester/helper_365_page_pipeline.cjs @@ -4,7 +4,7 @@ * 짝 = `test_365_page_pipeline.py`. */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const CATALOG = require("./helper_322_catalog_module.cjs"); const ROOT = path.join(__dirname, "..", ".."); @@ -46,15 +46,9 @@ globalThis.fetch = (url, init) => }); const STUBS = {}; -const cache = new Map(); -function loadTs(full) { - 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) => { +const { load, loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => (request) => { if (CATALOG.isCatalogRequest(request)) return CATALOG; const key = Object.keys(STUBS).find((name) => request.endsWith(name)); if (key) return STUBS[key]; @@ -63,11 +57,8 @@ function loadTs(full) { return loadTs(path.join(ROOT, "common_util", `${request.slice(6)}.ts`)); if (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`)); return require(request); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - return box.exports; -} -const load = (...parts) => loadTs(path.join(ROOT, ...parts)); + }, +}); // 상세 가게 칸(472-5) — 실제는 상세 가게가 받을 때 채움 · 여기선 종단도가 내주는 저장 상세 그대로 const slots = () => load("B06_Section", "B06_Section_Section_Canon.ts"); /** 이 시험은 묶음 여럿(P · Q · B)이 같은 종단도 흉내를 씀 — 칸 = 지금 연 프로젝트. */ diff --git a/resources/tester/helper_366_3_station_fit.cjs b/resources/tester/helper_366_3_station_fit.cjs index ca331318d..4b704f503 100644 --- a/resources/tester/helper_366_3_station_fit.cjs +++ b/resources/tester/helper_366_3_station_fit.cjs @@ -4,27 +4,17 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); -const cache = new Map(); -function loadTs(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) => +const { loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => (request) => request.startsWith(".") ? loadTs(path.join(path.dirname(full), `${request}.ts`)) - : require(request); - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - cache.set(full, box.exports); - return box.exports; -} + : require(request), +}); const LOGIC = path.join(ROOT, "B05_Profile", "logic"); const fit = loadTs(path.join(LOGIC, "B05_Profile_RouteEdit_StationFit.ts")); diff --git a/resources/tester/helper_368_4_probe_station.cjs b/resources/tester/helper_368_4_probe_station.cjs index 66a051959..8f36024d0 100644 --- a/resources/tester/helper_368_4_probe_station.cjs +++ b/resources/tester/helper_368_4_probe_station.cjs @@ -3,26 +3,13 @@ * 입력 argv[2] JSON {line, curves, pipes, structures, types, at: [m...]} · 짝 = test_368_4_probe_station.py. */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const CATALOG = require("./helper_322_catalog_module.cjs"); const ROOT = path.join(__dirname, "..", ".."); -const cache = new Map(); -function loadTs(full) { - 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 (CATALOG.isCatalogRequest(request)) return CATALOG; - if (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`)); - return require(request); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - return box.exports; -} +const { loadTs } = makeLoader({ + root: ROOT, +}); const logic = loadTs(path.join(ROOT, "B05_Profile", "logic", "B05_Profile_Sections_Stations.ts")); const station = loadTs(path.join(ROOT, "common_util", "common_util_structure_station.ts")); diff --git a/resources/tester/helper_370_2_toe_stop.cjs b/resources/tester/helper_370_2_toe_stop.cjs index 29ba90f41..8eb0b2ed9 100644 --- a/resources/tester/helper_370_2_toe_stop.cjs +++ b/resources/tester/helper_370_2_toe_stop.cjs @@ -4,10 +4,9 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); -const cache = new Map(); const STUBS = { "@ui/ui_template_toast": { showToast: () => undefined }, "@ui/ui_template_elements": { showToast: () => undefined }, @@ -116,24 +115,10 @@ globalThis.document = { }; globalThis.window = { setTimeout, clearTimeout, addEventListener: () => {} }; -function loadTs(file) { - const full = path.resolve(file); - if (cache.has(full)) return cache.get(full); - if (full.endsWith(".json")) { - const data = JSON.parse(fs.readFileSync(full, "utf8")); - cache.set(full, data); - return data; - } - const js = ts.transpileModule(fs.readFileSync(full, "utf8"), { - compilerOptions: { - module: ts.ModuleKind.CommonJS, - target: ts.ScriptTarget.ES2020, - esModuleInterop: true, - }, - }).outputText; - const box = { exports: {} }; - cache.set(full, box.exports); - const localRequire = (request) => { +const { loadTs } = makeLoader({ + root: ROOT, + interop: true, + requireFor: (full) => (request) => { if (STUBS[request]) return STUBS[request]; if (request.endsWith(".css")) return {}; const alias = { "@util/": "common_util", "@ui/": "ui_template", "@config/": "config" }; @@ -141,11 +126,8 @@ function loadTs(file) { if (request.startsWith(prefix)) return loadTs(resolve(path.join(ROOT, dir, request.slice(prefix.length)))); return loadTs(resolve(path.join(path.dirname(full), request))); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - cache.set(full, box.exports); - return box.exports; -} + }, +}); const resolve = (base) => [base, `${base}.ts`, path.join(base, "index.ts")].find( (p) => fs.existsSync(p) && fs.statSync(p).isFile(), diff --git a/resources/tester/helper_370_3_rock_cell.cjs b/resources/tester/helper_370_3_rock_cell.cjs index 24995d42f..86f44d5af 100644 --- a/resources/tester/helper_370_3_rock_cell.cjs +++ b/resources/tester/helper_370_3_rock_cell.cjs @@ -3,10 +3,9 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); -const cache = new Map(); class Node { constructor(tag) { @@ -84,22 +83,13 @@ const key = (name) => fn({ key: name, target: null, preventDefault: () => undefined }), ); -function loadTs(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 req = (r) => +const { loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => (r) => r.startsWith("@util/") ? loadTs(path.join(ROOT, "common_util", `${r.slice(6)}.ts`)) - : loadTs(path.join(path.dirname(full), `${r}.ts`)); - new Function("exports", "module", "require", js)(box.exports, box, req); - cache.set(full, box.exports); - return box.exports; -} + : loadTs(path.join(path.dirname(full), `${r}.ts`)), +}); globalThis.Element = Node; const pick = loadTs(path.join(ROOT, "B06_Section", "B06_Section_UI_Cross_Design_Pick.ts")); diff --git a/resources/tester/helper_371_2_pipe_slope.cjs b/resources/tester/helper_371_2_pipe_slope.cjs index 23be4ef11..fd4d9d855 100644 --- a/resources/tester/helper_371_2_pipe_slope.cjs +++ b/resources/tester/helper_371_2_pipe_slope.cjs @@ -3,10 +3,9 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); -const cache = new Map(); const noop = new Proxy({}, { get: () => () => "" }); /** 아주 작은 SVG 가짜 — 글 자리 판정에 쓰는 것만(class 고르기 · 속성 · 부모). */ @@ -47,26 +46,20 @@ class El { } globalThis.document = { addEventListener: () => undefined, createElementNS: (_ns, t) => new El(t) }; -function loadTs(file) { - const full = path.resolve(file); - if (cache.has(full)) return cache.get(full); - if (full.endsWith(".json")) return JSON.parse(fs.readFileSync(full, "utf8")); - 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 resolve = (base) => - fs.existsSync(base) && fs.statSync(base).isFile() ? base : `${base}.ts`; - const req = (r) => { - if (r.startsWith("@ui/") || r.startsWith("@config/")) return noop; - if (r.startsWith("@util/")) return loadTs(resolve(path.join(ROOT, "common_util", r.slice(6)))); - return loadTs(resolve(path.join(path.dirname(full), r))); - }; - new Function("exports", "module", "require", js)(box.exports, box, req); - cache.set(full, box.exports); - return box.exports; -} +const { loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => { + const resolve = (base) => + fs.existsSync(base) && fs.statSync(base).isFile() ? base : `${base}.ts`; + const req = (r) => { + if (r.startsWith("@ui/") || r.startsWith("@config/")) return noop; + if (r.startsWith("@util/")) + return loadTs(resolve(path.join(ROOT, "common_util", r.slice(6)))); + return loadTs(resolve(path.join(path.dirname(full), r))); + }; + return req; + }, +}); const { computeCulvertLayout } = loadTs( path.join(ROOT, "B06_Section", "B06_Section_UI_Cross_Culvert_Geom.ts"), diff --git a/resources/tester/helper_380_2_site_station.cjs b/resources/tester/helper_380_2_site_station.cjs index 33eaf4a12..d2dd6ae2c 100644 --- a/resources/tester/helper_380_2_site_station.cjs +++ b/resources/tester/helper_380_2_site_station.cjs @@ -3,21 +3,19 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); function loadTs(file, stubs = {}) { - const js = ts.transpileModule(fs.readFileSync(path.join(ROOT, file), "utf8"), { - compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 }, - }).outputText; - const box = { exports: {} }; - const localRequire = (request) => { - if (stubs[request]) return stubs[request]; - throw new Error(`stub 없음: ${request} (${file})`); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - return box.exports; + return makeLoader({ + root: ROOT, + cache: false, + requireFor: (full) => (request) => { + if (stubs[request]) return stubs[request]; + throw new Error(`stub 없음: ${request} (${file})`); + }, + }).loadTs(path.join(ROOT, file)); } const input = JSON.parse(fs.readFileSync(process.argv[2], "utf8")); diff --git a/resources/tester/helper_380_3_site_follow.cjs b/resources/tester/helper_380_3_site_follow.cjs index e8e70aeec..46d040a82 100644 --- a/resources/tester/helper_380_3_site_follow.cjs +++ b/resources/tester/helper_380_3_site_follow.cjs @@ -3,21 +3,19 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); function loadTs(file, stubs = {}) { - const js = ts.transpileModule(fs.readFileSync(path.join(ROOT, file), "utf8"), { - compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 }, - }).outputText; - const box = { exports: {} }; - const localRequire = (request) => { - if (stubs[request]) return stubs[request]; - throw new Error(`stub 없음: ${request} (${file})`); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - return box.exports; + return makeLoader({ + root: ROOT, + cache: false, + requireFor: (full) => (request) => { + if (stubs[request]) return stubs[request]; + throw new Error(`stub 없음: ${request} (${file})`); + }, + }).loadTs(path.join(ROOT, file)); } const input = JSON.parse(fs.readFileSync(process.argv[2], "utf8")); diff --git a/resources/tester/helper_383_2_key_nudge.cjs b/resources/tester/helper_383_2_key_nudge.cjs index 04ce20c3e..01e6b70fa 100644 --- a/resources/tester/helper_383_2_key_nudge.cjs +++ b/resources/tester/helper_383_2_key_nudge.cjs @@ -3,27 +3,17 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); -const cache = new Map(); -function loadTs(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) => +const { loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => (request) => request.startsWith(".") ? loadTs(path.join(path.dirname(full), `${request}.ts`)) - : require(request); - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - cache.set(full, box.exports); - return box.exports; -} + : require(request), +}); const nudge = loadTs(path.join(ROOT, "B05_Profile", "logic", "B05_Profile_RouteEdit_KeyNudge.ts")); diff --git a/resources/tester/helper_384_4_adjusts.cjs b/resources/tester/helper_384_4_adjusts.cjs index 9a4a46c6e..5ae01db00 100644 --- a/resources/tester/helper_384_4_adjusts.cjs +++ b/resources/tester/helper_384_4_adjusts.cjs @@ -3,26 +3,16 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const CATALOG = require("./helper_322_catalog_module.cjs"); // 구조물 표(322-1) const ROOT = path.join(__dirname, "..", ".."); -const cache = new Map(); const STUBS = { "@ui/ui_template_toast": { showToast: () => undefined } }; -function loadTs(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, - esModuleInterop: true, - }, - }).outputText; - const box = { exports: {} }; - cache.set(full, box.exports); - const localRequire = (request) => { +const { loadTs } = makeLoader({ + root: ROOT, + interop: true, + requireFor: (full) => (request) => { if (CATALOG.isCatalogRequest(request)) return CATALOG; if (STUBS[request]) return STUBS[request]; const alias = { "@util/": "common_util", "@ui/": "ui_template", "@config/": "config" }; @@ -30,11 +20,8 @@ function loadTs(file) { if (request.startsWith(prefix)) return loadTs(resolve(path.join(ROOT, dir, request.slice(prefix.length)))); return loadTs(resolve(path.join(path.dirname(full), request))); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - cache.set(full, box.exports); - return box.exports; -} + }, +}); const resolve = (base) => [base, `${base}.ts`, path.join(base, "index.ts")].find( (p) => fs.existsSync(p) && fs.statSync(p).isFile(), diff --git a/resources/tester/helper_387_4b_pipe_options.cjs b/resources/tester/helper_387_4b_pipe_options.cjs index 20a705a44..af8cf6a80 100644 --- a/resources/tester/helper_387_4b_pipe_options.cjs +++ b/resources/tester/helper_387_4b_pipe_options.cjs @@ -4,26 +4,16 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const CATALOG = require("./helper_322_catalog_module.cjs"); // 구조물 표(322-1) const ROOT = path.join(__dirname, "..", ".."); -const cache = new Map(); const STUBS = { "@ui/ui_template_toast": { showToast: () => undefined } }; -function loadTs(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, - esModuleInterop: true, - }, - }).outputText; - const box = { exports: {} }; - cache.set(full, box.exports); - const localRequire = (request) => { +const { loadTs } = makeLoader({ + root: ROOT, + interop: true, + requireFor: (full) => (request) => { if (CATALOG.isCatalogRequest(request)) return CATALOG; if (STUBS[request]) return STUBS[request]; const alias = { "@util/": "common_util", "@ui/": "ui_template", "@config/": "config" }; @@ -31,11 +21,8 @@ function loadTs(file) { if (request.startsWith(prefix)) return loadTs(resolve(path.join(ROOT, dir, request.slice(prefix.length)))); return loadTs(resolve(path.join(path.dirname(full), request))); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - cache.set(full, box.exports); - return box.exports; -} + }, +}); const resolve = (base) => [base, `${base}.ts`, path.join(base, "index.ts")].find( (p) => fs.existsSync(p) && fs.statSync(p).isFile(), diff --git a/resources/tester/helper_387_8_folded_profile.cjs b/resources/tester/helper_387_8_folded_profile.cjs index 36e8f3242..061435904 100644 --- a/resources/tester/helper_387_8_folded_profile.cjs +++ b/resources/tester/helper_387_8_folded_profile.cjs @@ -5,7 +5,7 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const CATALOG = require("./helper_322_catalog_module.cjs"); const ROOT = path.join(__dirname, "..", ".."); @@ -95,35 +95,23 @@ const STUBS = { "config_frontend.ts": anyModule({ PIPE_TYPES: [] }), }; -const cache = new Map(); const resolve = (base) => [base, `${base}.ts`, path.join(base, "index.ts")].find( (p) => fs.existsSync(p) && fs.statSync(p).isFile(), ) ?? `${base}.ts`; -function loadTs(full) { - const stub = STUBS[path.basename(full)]; - if (stub) return stub; - 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, - esModuleInterop: true, - }, - }).outputText; - const box = { exports: {} }; - cache.set(full, box.exports); - const near = (request) => { +const { loadTs } = makeLoader({ + root: ROOT, + interop: true, + fileStub: (full) => STUBS[path.basename(full)], + requireFor: (full) => (request) => { if (CATALOG.isCatalogRequest(request)) return CATALOG; const alias = { "@util/": "common_util", "@ui/": "ui_template", "@config/": "config" }; for (const [prefix, dir] of Object.entries(alias)) if (request.startsWith(prefix)) return loadTs(resolve(path.join(ROOT, dir, request.slice(prefix.length)))); return loadTs(resolve(path.join(path.dirname(full), request))); - }; - new Function("exports", "module", "require", js)(box.exports, box, near); - return box.exports; -} + }, +}); const B06 = (f) => path.join(ROOT, "B06_Section", `${f}.ts`); const store = loadTs(B06("B06_Section_Section_Store")); diff --git a/resources/tester/helper_390_5_snap_step_ops.cjs b/resources/tester/helper_390_5_snap_step_ops.cjs index 9c63a27fd..134ba4b63 100644 --- a/resources/tester/helper_390_5_snap_step_ops.cjs +++ b/resources/tester/helper_390_5_snap_step_ops.cjs @@ -5,27 +5,17 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); -const cache = new Map(); -function loadTs(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) => +const { loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => (request) => request.startsWith(".") ? loadTs(path.join(path.dirname(full), `${request}.ts`)) - : require(request); - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - cache.set(full, box.exports); - return box.exports; -} + : require(request), +}); const LOGIC = path.join(ROOT, "B05_Profile", "logic"); const fit = loadTs(path.join(LOGIC, "B05_Profile_RouteEdit_StationFit.ts")); diff --git a/resources/tester/helper_397_cross_ctrl_wheel.cjs b/resources/tester/helper_397_cross_ctrl_wheel.cjs index 0760f949d..b58b8db83 100644 --- a/resources/tester/helper_397_cross_ctrl_wheel.cjs +++ b/resources/tester/helper_397_cross_ctrl_wheel.cjs @@ -4,7 +4,7 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); const common = fs.readFileSync( @@ -13,15 +13,11 @@ const common = fs.readFileSync( ); const CROSS_PAD = Function(`return ${/export const CROSS_PAD = (\{[^}]*\})/.exec(common)[1]}`)(); const STUBS = { "./B06_Section_UI_Section_Common": { CROSS_PAD, L: (k) => k } }; -function loadTs(full) { - const js = ts.transpileModule(fs.readFileSync(full, "utf8"), { - compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 }, - }).outputText; - const box = { exports: {} }; - const localRequire = (request) => STUBS[request] ?? {}; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - return box.exports; -} +const { loadTs } = makeLoader({ + root: ROOT, + cache: false, + requireFor: (full) => (request) => STUBS[request] ?? {}, +}); globalThis.localStorage = { getItem: () => null }; // 휠 방향 기본(밂 = 확대) STUBS["./input_prefs"] = loadTs(path.join(ROOT, "A00_Common", "input_prefs.ts")); STUBS["../A00_Common/b_svg_zoom_pan"] = loadTs(path.join(ROOT, "A00_Common", "b_svg_zoom_pan.ts")); diff --git a/resources/tester/helper_400_profile_carry.cjs b/resources/tester/helper_400_profile_carry.cjs index 824a8ad56..ca1b3a339 100644 --- a/resources/tester/helper_400_profile_carry.cjs +++ b/resources/tester/helper_400_profile_carry.cjs @@ -3,21 +3,19 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); function loadTs(file, stubs = {}) { - const js = ts.transpileModule(fs.readFileSync(path.join(ROOT, file), "utf8"), { - compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 }, - }).outputText; - const box = { exports: {} }; - const localRequire = (request) => { - if (stubs[request]) return stubs[request]; - throw new Error(`stub 없음: ${request} (${file})`); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - return box.exports; + return makeLoader({ + root: ROOT, + cache: false, + requireFor: (full) => (request) => { + if (stubs[request]) return stubs[request]; + throw new Error(`stub 없음: ${request} (${file})`); + }, + }).loadTs(path.join(ROOT, file)); } const straightJudge = loadTs("B05_Profile/logic/B05_Profile_Profile_Straight.ts"); diff --git a/resources/tester/helper_401_routeedit_pan.cjs b/resources/tester/helper_401_routeedit_pan.cjs index 115b910f4..6232d2ac4 100644 --- a/resources/tester/helper_401_routeedit_pan.cjs +++ b/resources/tester/helper_401_routeedit_pan.cjs @@ -5,10 +5,9 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); -const cache = new Map(); function memoryStorage() { const map = new Map(); @@ -23,23 +22,14 @@ globalThis.localStorage = globalThis.window.localStorage; const STUBS = { "@ui/ui_template_palette": { themeColor: (_name, fallback) => fallback } }; -function loadTs(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) => { +const { loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => (request) => { if (STUBS[request]) return STUBS[request]; if (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`)); return require(request); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - cache.set(full, box.exports); - return box.exports; -} + }, +}); const input = loadTs(path.join(ROOT, "B05_Profile", "B05_Profile_UI_RouteEdit_Input.ts")); const rotateMod = loadTs(path.join(ROOT, "B05_Profile", "B05_Profile_UI_RouteEdit_Rotate.ts")); diff --git a/resources/tester/helper_409_2_plan_release_form.cjs b/resources/tester/helper_409_2_plan_release_form.cjs index a585c4219..beb2cbf8f 100644 --- a/resources/tester/helper_409_2_plan_release_form.cjs +++ b/resources/tester/helper_409_2_plan_release_form.cjs @@ -5,19 +5,17 @@ const fs = require("fs"); const path = require("path"); const ROOT = path.join(__dirname, "..", ".."); -const ts = require(path.join(ROOT, "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); function loadTs(file, stubs = {}) { - const js = ts.transpileModule(fs.readFileSync(path.join(ROOT, file), "utf8"), { - compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 }, - }).outputText; - const box = { exports: {} }; - const localRequire = (request) => { - if (stubs[request]) return stubs[request]; - throw new Error(`stub 없음: ${request}`); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - return box.exports; + return makeLoader({ + root: ROOT, + cache: false, + requireFor: (full) => (request) => { + if (stubs[request]) return stubs[request]; + throw new Error(`stub 없음: ${request}`); + }, + }).loadTs(path.join(ROOT, file)); } globalThis.window = { addEventListener() {}, removeEventListener() {} }; diff --git a/resources/tester/helper_410_follow_xy.cjs b/resources/tester/helper_410_follow_xy.cjs index 089cc32fb..581629080 100644 --- a/resources/tester/helper_410_follow_xy.cjs +++ b/resources/tester/helper_410_follow_xy.cjs @@ -5,21 +5,19 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); function loadTs(file, stubs = {}) { - const js = ts.transpileModule(fs.readFileSync(path.join(ROOT, file), "utf8"), { - compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 }, - }).outputText; - const box = { exports: {} }; - const localRequire = (request) => { - if (stubs[request]) return stubs[request]; - throw new Error(`stub 없음: ${request} (${file})`); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - return box.exports; + return makeLoader({ + root: ROOT, + cache: false, + requireFor: (full) => (request) => { + if (stubs[request]) return stubs[request]; + throw new Error(`stub 없음: ${request} (${file})`); + }, + }).loadTs(path.join(ROOT, file)); } const catalog = require("./helper_322_catalog_module.cjs"); diff --git a/resources/tester/helper_415_h2.cjs b/resources/tester/helper_415_h2.cjs index abb5e8364..185d2370c 100644 --- a/resources/tester/helper_415_h2.cjs +++ b/resources/tester/helper_415_h2.cjs @@ -3,7 +3,7 @@ * 입력 argv[2] JSON · argv[3] 격자 이진 · 결과 = 표준출력 JSON. 짝 = `test_415_page_split.py`. */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const CATALOG = require("./helper_322_catalog_module.cjs"); const ROOT = path.join(__dirname, "..", ".."); @@ -45,15 +45,9 @@ globalThis.fetch = (url, init) => }); const STUBS = {}; -const cache = new Map(); -function loadTs(full) { - 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) => { +const { load, loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => (request) => { if (CATALOG.isCatalogRequest(request)) return CATALOG; const key = Object.keys(STUBS).find((name) => request.endsWith(name)); if (key) return STUBS[key]; @@ -62,11 +56,8 @@ function loadTs(full) { return loadTs(path.join(ROOT, "common_util", `${request.slice(6)}.ts`)); if (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`)); return require(request); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - return box.exports; -} -const load = (...parts) => loadTs(path.join(ROOT, ...parts)); + }, +}); const sampler = load("common_util", "common_util_surface_sampler.ts"); const bytes = fs.readFileSync(process.argv[3]); diff --git a/resources/tester/helper_416_page_cache.cjs b/resources/tester/helper_416_page_cache.cjs index 3f5d5f893..4f1881d64 100644 --- a/resources/tester/helper_416_page_cache.cjs +++ b/resources/tester/helper_416_page_cache.cjs @@ -8,7 +8,7 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const CATALOG = require("./helper_322_catalog_module.cjs"); const ROOT = path.join(__dirname, "..", ".."); @@ -96,35 +96,23 @@ const STUBS = { "config_frontend.ts": anyModule({ PIPE_TYPES: [] }), }; -const cache = new Map(); const resolve = (base) => [base, `${base}.ts`, path.join(base, "index.ts")].find( (p) => fs.existsSync(p) && fs.statSync(p).isFile(), ) ?? `${base}.ts`; -function loadTs(full) { - const stub = STUBS[path.basename(full)]; - if (stub) return stub; - 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, - esModuleInterop: true, - }, - }).outputText; - const box = { exports: {} }; - cache.set(full, box.exports); - const near = (request) => { +const { loadTs } = makeLoader({ + root: ROOT, + interop: true, + fileStub: (full) => STUBS[path.basename(full)], + requireFor: (full) => (request) => { if (CATALOG.isCatalogRequest(request)) return CATALOG; const alias = { "@util/": "common_util", "@ui/": "ui_template", "@config/": "config" }; for (const [prefix, dir] of Object.entries(alias)) if (request.startsWith(prefix)) return loadTs(resolve(path.join(ROOT, dir, request.slice(prefix.length)))); return loadTs(resolve(path.join(path.dirname(full), request))); - }; - new Function("exports", "module", "require", js)(box.exports, box, near); - return box.exports; -} + }, +}); const store = loadTs(path.join(ROOT, "B06_Section", "B06_Section_Section_Store.ts")); const pageRoute = loadTs(path.join(ROOT, "A00_Common", "design", "design_page_route.ts")); diff --git a/resources/tester/helper_421_2_violation_lines.cjs b/resources/tester/helper_421_2_violation_lines.cjs index 0141d7cc7..7aee5d3cc 100644 --- a/resources/tester/helper_421_2_violation_lines.cjs +++ b/resources/tester/helper_421_2_violation_lines.cjs @@ -3,10 +3,9 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); -const cache = new Map(); function memoryStorage() { const map = new Map(); @@ -27,26 +26,17 @@ globalThis.fetch = () => Promise.resolve({ ok: false }); const STUBS = { "@ui/ui_template_palette": { themeColor: (_name, fallback) => fallback } }; -function loadTs(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) => { +const { loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => (request) => { if (STUBS[request]) return STUBS[request]; if (request.endsWith(".css")) return {}; if (request.startsWith("@ui/")) return loadTs(path.join(ROOT, "ui_template", `${request.slice(4)}.ts`)); if (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`)); return require(request); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - cache.set(full, box.exports); - return box.exports; -} + }, +}); const model = loadTs(path.join(ROOT, "B05_Profile", "B05_Profile_UI_RouteEdit_Initial_Model.ts")); diff --git a/resources/tester/helper_421_profile_toggle.cjs b/resources/tester/helper_421_profile_toggle.cjs index fc4a3f6bd..564e807c1 100644 --- a/resources/tester/helper_421_profile_toggle.cjs +++ b/resources/tester/helper_421_profile_toggle.cjs @@ -3,10 +3,9 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); -const cache = new Map(); function memoryStorage() { const map = new Map(); @@ -27,26 +26,17 @@ globalThis.fetch = () => Promise.resolve({ ok: false }); const STUBS = { "@ui/ui_template_palette": { themeColor: (_name, fallback) => fallback } }; -function loadTs(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) => { +const { loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => (request) => { if (STUBS[request]) return STUBS[request]; if (request.endsWith(".css")) return {}; if (request.startsWith("@ui/")) return loadTs(path.join(ROOT, "ui_template", `${request.slice(4)}.ts`)); if (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`)); return require(request); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - cache.set(full, box.exports); - return box.exports; -} + }, +}); const model = loadTs(path.join(ROOT, "B05_Profile", "B05_Profile_UI_RouteEdit_Initial_Model.ts")); diff --git a/resources/tester/helper_426_profile_straight.cjs b/resources/tester/helper_426_profile_straight.cjs index e94097ecd..74227b793 100644 --- a/resources/tester/helper_426_profile_straight.cjs +++ b/resources/tester/helper_426_profile_straight.cjs @@ -5,25 +5,12 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); -const cache = new Map(); -function loadTs(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 (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`)); - return require(request); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - return box.exports; -} +const { loadTs } = makeLoader({ + root: ROOT, +}); const LOGIC = path.join(ROOT, "B05_Profile", "logic"); const align = loadTs(path.join(LOGIC, "B05_Profile_UI_Profile_Alignment.ts")); diff --git a/resources/tester/helper_430_route_edit_rules.cjs b/resources/tester/helper_430_route_edit_rules.cjs index 7632c8f85..accb0e8ee 100644 --- a/resources/tester/helper_430_route_edit_rules.cjs +++ b/resources/tester/helper_430_route_edit_rules.cjs @@ -5,28 +5,18 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); const LOGIC = path.join(ROOT, "B05_Profile", "logic"); -const cache = new Map(); -function loadTs(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) => +const { loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => (request) => request.startsWith(".") ? loadTs(path.join(path.dirname(full), `${request}.ts`)) - : require(request); - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - cache.set(full, box.exports); - return box.exports; -} + : require(request), +}); const edits = loadTs(path.join(LOGIC, "B05_Profile_UI_RouteEdit_Edits.ts")); const nudge = loadTs(path.join(LOGIC, "B05_Profile_RouteEdit_KeyNudge.ts")); diff --git a/resources/tester/helper_432_1_curve_law.cjs b/resources/tester/helper_432_1_curve_law.cjs index 36b1c3350..44f3a5530 100644 --- a/resources/tester/helper_432_1_curve_law.cjs +++ b/resources/tester/helper_432_1_curve_law.cjs @@ -4,25 +4,12 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); -const cache = new Map(); -function loadTs(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 (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`)); - return require(request); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - return box.exports; -} +const { loadTs } = makeLoader({ + root: ROOT, +}); const LOGIC = path.join(ROOT, "B05_Profile", "logic"); const align = loadTs(path.join(LOGIC, "B05_Profile_UI_Profile_Alignment.ts")); diff --git a/resources/tester/helper_449_save_pipes.cjs b/resources/tester/helper_449_save_pipes.cjs index 7d2f4d16f..03a3bea5f 100644 --- a/resources/tester/helper_449_save_pipes.cjs +++ b/resources/tester/helper_449_save_pipes.cjs @@ -2,7 +2,7 @@ * Node 로 · 서버 창구 · 계획고 초안 · 노선 편집 창구만 가짜. 짝 = `test_449_save_pipes.py`. */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const CATALOG = require("./helper_322_catalog_module.cjs"); const ROOT = path.join(__dirname, "..", ".."); @@ -27,15 +27,9 @@ globalThis.window = { }; const STUBS = { "/design_leave": { designSignature: () => "", markDesignClean: () => undefined } }; -const cache = new Map(); -function loadTs(full) { - 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) => { +const { load, loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => (request) => { if (CATALOG.isCatalogRequest(request)) return CATALOG; const key = Object.keys(STUBS).find((name) => request.endsWith(name)); if (key) return STUBS[key]; @@ -44,11 +38,8 @@ function loadTs(full) { return loadTs(path.join(ROOT, "common_util", `${request.slice(6)}.ts`)); if (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`)); return require(request); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - return box.exports; -} -const load = (...parts) => loadTs(path.join(ROOT, ...parts)); + }, +}); let calls = []; let failAt = null; // 이 차례에서 throw diff --git a/resources/tester/helper_451_drop_cross.cjs b/resources/tester/helper_451_drop_cross.cjs index 8b6deb3f7..731eb7513 100644 --- a/resources/tester/helper_451_drop_cross.cjs +++ b/resources/tester/helper_451_drop_cross.cjs @@ -3,7 +3,7 @@ * 입력 argv[2] JSON · argv[3] 격자 이진 · 결과 = 표준출력 JSON. 짝 = `test_451_drop_cross.py`. */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const CATALOG = require("./helper_322_catalog_module.cjs"); const ROOT = path.join(__dirname, "..", ".."); @@ -45,15 +45,9 @@ globalThis.fetch = (url, init) => }); const STUBS = {}; -const cache = new Map(); -function loadTs(full) { - 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) => { +const { load, loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => (request) => { if (CATALOG.isCatalogRequest(request)) return CATALOG; const key = Object.keys(STUBS).find((name) => request.endsWith(name)); if (key) return STUBS[key]; @@ -62,11 +56,8 @@ function loadTs(full) { return loadTs(path.join(ROOT, "common_util", `${request.slice(6)}.ts`)); if (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`)); return require(request); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - return box.exports; -} -const load = (...parts) => loadTs(path.join(ROOT, ...parts)); + }, +}); // 상세 가게 칸(472-5) — 실제는 상세 가게가 받을 때 채움 · 여기선 종단도가 내주는 저장 상세 그대로 const slots = () => load("B06_Section", "B06_Section_Section_Canon.ts"); diff --git a/resources/tester/helper_451_refresh_hold.cjs b/resources/tester/helper_451_refresh_hold.cjs index f090d9f7c..0e5168b9c 100644 --- a/resources/tester/helper_451_refresh_hold.cjs +++ b/resources/tester/helper_451_refresh_hold.cjs @@ -4,7 +4,7 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const CATALOG = require("./helper_322_catalog_module.cjs"); const ROOT = path.join(__dirname, "..", ".."); @@ -85,30 +85,19 @@ const resolve = (base) => [base, `${base}.ts`, path.join(base, "index.ts")].find( (p) => fs.existsSync(p) && fs.statSync(p).isFile(), ) ?? `${base}.ts`; -function loadTs(full) { - const stub = STUBS[path.basename(full)]; - if (stub) return stub; - 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, - esModuleInterop: true, - }, - }).outputText; - const box = { exports: {} }; - cache.set(full, box.exports); - const near = (request) => { +const { loadTs } = makeLoader({ + root: ROOT, + interop: true, + fileStub: (full) => STUBS[path.basename(full)], + requireFor: (full) => (request) => { if (CATALOG.isCatalogRequest(request)) return CATALOG; const alias = { "@util/": "common_util", "@ui/": "ui_template", "@config/": "config" }; for (const [prefix, dir] of Object.entries(alias)) if (request.startsWith(prefix)) return loadTs(resolve(path.join(ROOT, dir, request.slice(prefix.length)))); return loadTs(resolve(path.join(path.dirname(full), request))); - }; - new Function("exports", "module", "require", js)(box.exports, box, near); - return box.exports; -} + }, +}); let store = loadTs(path.join(ROOT, "B06_Section", "B06_Section_Section_Store.ts")); const state = loadTs(path.join(ROOT, "A00_Common", "b_page_state.ts")); diff --git a/resources/tester/helper_451_session_canon.cjs b/resources/tester/helper_451_session_canon.cjs index 80e16b9e2..3a11f3709 100644 --- a/resources/tester/helper_451_session_canon.cjs +++ b/resources/tester/helper_451_session_canon.cjs @@ -4,7 +4,7 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const CATALOG = require("./helper_322_catalog_module.cjs"); const ROOT = path.join(__dirname, "..", ".."); @@ -77,35 +77,23 @@ const STUBS = { "config_frontend.ts": anyModule({ PIPE_TYPES: [] }), }; -const cache = new Map(); const resolve = (base) => [base, `${base}.ts`, path.join(base, "index.ts")].find( (p) => fs.existsSync(p) && fs.statSync(p).isFile(), ) ?? `${base}.ts`; -function loadTs(full) { - const stub = STUBS[path.basename(full)]; - if (stub) return stub; - 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, - esModuleInterop: true, - }, - }).outputText; - const box = { exports: {} }; - cache.set(full, box.exports); - const near = (request) => { +const { loadTs } = makeLoader({ + root: ROOT, + interop: true, + fileStub: (full) => STUBS[path.basename(full)], + requireFor: (full) => (request) => { if (CATALOG.isCatalogRequest(request)) return CATALOG; const alias = { "@util/": "common_util", "@ui/": "ui_template", "@config/": "config" }; for (const [prefix, dir] of Object.entries(alias)) if (request.startsWith(prefix)) return loadTs(resolve(path.join(ROOT, dir, request.slice(prefix.length)))); return loadTs(resolve(path.join(path.dirname(full), request))); - }; - new Function("exports", "module", "require", js)(box.exports, box, near); - return box.exports; -} + }, +}); const store = loadTs(path.join(ROOT, "B06_Section", "B06_Section_Section_Store.ts")); const state = loadTs(path.join(ROOT, "A00_Common", "b_page_state.ts")); diff --git a/resources/tester/helper_453_plan_pick_draft.cjs b/resources/tester/helper_453_plan_pick_draft.cjs index c19499898..31d13ffc5 100644 --- a/resources/tester/helper_453_plan_pick_draft.cjs +++ b/resources/tester/helper_453_plan_pick_draft.cjs @@ -3,7 +3,7 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); const data = new Map(); @@ -27,23 +27,14 @@ const STUBS = { "@ui/ui_template_palette": { themeColor: (_name, fallback) => fallback }, "@util/common_util_svg": { stationLabel: (c, i) => `No.${Math.round(c / i)}` }, }; -const cache = new Map(); -function loadTs(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) => { +const { loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => (request) => { if (STUBS[request]) return STUBS[request]; if (request.startsWith(".")) return loadTs(`${path.resolve(path.dirname(full), request)}.ts`); return require(request); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - return box.exports; -} + }, +}); const page = path.join(ROOT, "B05_Profile"); const input = loadTs(path.join(page, "B05_Profile_UI_RouteEdit_Input.ts")); const edit = loadTs(path.join(page, "B05_Profile_UI_RouteEdit_History.ts")); diff --git a/resources/tester/helper_454_arrow_station_step.cjs b/resources/tester/helper_454_arrow_station_step.cjs index fd8ac2627..4dbcef29e 100644 --- a/resources/tester/helper_454_arrow_station_step.cjs +++ b/resources/tester/helper_454_arrow_station_step.cjs @@ -4,27 +4,17 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); -const cache = new Map(); -function loadTs(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) => +const { loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => (request) => request.startsWith(".") ? loadTs(path.join(path.dirname(full), `${request}.ts`)) - : require(request); - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - cache.set(full, box.exports); - return box.exports; -} + : require(request), +}); const LOGIC = path.join(ROOT, "B05_Profile", "logic"); const fit = loadTs(path.join(LOGIC, "B05_Profile_RouteEdit_StationFit.ts")); diff --git a/resources/tester/helper_455_arrow_auto_radius.cjs b/resources/tester/helper_455_arrow_auto_radius.cjs index 1210f49fe..70b4ee029 100644 --- a/resources/tester/helper_455_arrow_auto_radius.cjs +++ b/resources/tester/helper_455_arrow_auto_radius.cjs @@ -4,26 +4,12 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); -const cache = new Map(); -function loadTs(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 (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`)); - return require(request); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - cache.set(full, box.exports); - return box.exports; -} +const { loadTs } = makeLoader({ + root: ROOT, +}); const align = loadTs( path.join(ROOT, "B05_Profile", "logic", "B05_Profile_UI_Profile_Alignment.ts"), diff --git a/resources/tester/helper_455_old_policy.cjs b/resources/tester/helper_455_old_policy.cjs index b4b2519b2..87c08b99e 100644 --- a/resources/tester/helper_455_old_policy.cjs +++ b/resources/tester/helper_455_old_policy.cjs @@ -4,25 +4,12 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); -const cache = new Map(); -function loadTs(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 (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`)); - return require(request); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - return box.exports; -} +const { loadTs } = makeLoader({ + root: ROOT, +}); const LOGIC = path.join(ROOT, "B05_Profile", "logic"); const data = loadTs(path.join(LOGIC, "B05_Profile_UI_Profile_Data.ts")); diff --git a/resources/tester/helper_466_pipe_move_options.cjs b/resources/tester/helper_466_pipe_move_options.cjs index 101b18c99..316c72d8f 100644 --- a/resources/tester/helper_466_pipe_move_options.cjs +++ b/resources/tester/helper_466_pipe_move_options.cjs @@ -3,23 +3,21 @@ * 표준출력 JSON 한 벌 · 짝 = test_466_pipe_move_options.py. */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const CATALOG = require("./helper_322_catalog_module.cjs"); // 구조물 표(322-1) const ROOT = path.join(__dirname, "..", ".."); function loadTs(file, stubs = {}) { - const js = ts.transpileModule(fs.readFileSync(file, "utf8"), { - compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 }, - }).outputText; - const box = { exports: {} }; - const localRequire = (request) => { - if (CATALOG.isCatalogRequest(request)) return CATALOG; - if (stubs[request]) return stubs[request]; - throw new Error(`stub 없음: ${request}`); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - return box.exports; + return makeLoader({ + root: ROOT, + cache: false, + requireFor: (full) => (request) => { + if (CATALOG.isCatalogRequest(request)) return CATALOG; + if (stubs[request]) return stubs[request]; + throw new Error(`stub 없음: ${request}`); + }, + }).loadTs(file); } // 세션(structure-pick) — 메모리 한 벌 diff --git a/resources/tester/helper_472_5c_drop_once.cjs b/resources/tester/helper_472_5c_drop_once.cjs index 64917ad12..636fdfc77 100644 --- a/resources/tester/helper_472_5c_drop_once.cjs +++ b/resources/tester/helper_472_5c_drop_once.cjs @@ -4,7 +4,7 @@ * 입력 argv[2] JSON · argv[3] 격자 이진 · 결과 = 표준출력 JSON. 짝 = `test_472_5c_drop_once.py`. */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const CATALOG = require("./helper_322_catalog_module.cjs"); const ROOT = path.join(__dirname, "..", ".."); @@ -55,15 +55,9 @@ STUBS["B05_Profile_UI_Profile_History"] = new Proxy( }, { get: (target, key) => (key in target ? target[key] : () => undefined) }, ); -const cache = new Map(); -function loadTs(full) { - 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) => { +const { load, loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => (request) => { if (CATALOG.isCatalogRequest(request)) return CATALOG; const key = Object.keys(STUBS).find((name) => request.endsWith(name)); if (key) return STUBS[key]; @@ -72,11 +66,8 @@ function loadTs(full) { return loadTs(path.join(ROOT, "common_util", `${request.slice(6)}.ts`)); if (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`)); return require(request); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - return box.exports; -} -const load = (...parts) => loadTs(path.join(ROOT, ...parts)); + }, +}); // 상세 가게 칸(472-5) — 실제는 상세 가게가 받을 때 채움 · 여기선 종단도가 내주는 저장 상세 그대로 const slots = () => load("B06_Section", "B06_Section_Section_Canon.ts"); diff --git a/resources/tester/helper_472_d_b05_pipe_undo.cjs b/resources/tester/helper_472_d_b05_pipe_undo.cjs index 4a2d65aa9..01d041c54 100644 --- a/resources/tester/helper_472_d_b05_pipe_undo.cjs +++ b/resources/tester/helper_472_d_b05_pipe_undo.cjs @@ -4,11 +4,10 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const CATALOG = require("./helper_322_catalog_module.cjs"); const ROOT = path.join(__dirname, "..", ".."); -const cache = new Map(); const listeners = {}; const storage = () => { @@ -54,24 +53,15 @@ const STUBS = { }, }; -function loadTs(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) => +const { loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => (request) => (CATALOG.isCatalogRequest(request) ? CATALOG : null) ?? STUBS[request] ?? (request.startsWith(".") ? loadTs(path.join(path.dirname(full), `${request}.ts`)) - : require(request)); - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - cache.set(full, box.exports); - return box.exports; -} + : require(request)), +}); const store = loadTs(path.join(ROOT, "A00_Common", "design", "design_store.ts")); const tools = loadTs(path.join(ROOT, "B05_Profile", "B05_Profile_UI_Profile_Panel_Tools.ts")); diff --git a/resources/tester/helper_473_lane_ready.cjs b/resources/tester/helper_473_lane_ready.cjs index 9a8986bc7..3db3902a4 100644 --- a/resources/tester/helper_473_lane_ready.cjs +++ b/resources/tester/helper_473_lane_ready.cjs @@ -5,7 +5,7 @@ const fs = require("fs"); const path = require("path"); const ROOT = path.join(__dirname, "..", ".."); -const ts = require(path.join(ROOT, "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const CATALOG = require(path.join(__dirname, "helper_322_catalog_module.cjs")); function memoryStorage() { @@ -39,25 +39,15 @@ const STUBS = { "B06_Section_UI_Page_Persist.ts": anyModule({ bermSpansFromStructures: () => [] }), }; -const cache = new Map(); const resolve = (base) => [base, `${base}.ts`, path.join(base, "index.ts")].find( (p) => fs.existsSync(p) && fs.statSync(p).isFile(), ) ?? `${base}.ts`; -function loadTs(full) { - const stub = STUBS[path.basename(full)]; - if (stub) return stub; - 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, - esModuleInterop: true, - }, - }).outputText; - const box = { exports: {} }; - cache.set(full, box.exports); - const near = (request) => { +const { loadTs } = makeLoader({ + root: ROOT, + interop: true, + fileStub: (full) => STUBS[path.basename(full)], + requireFor: (full) => (request) => { if (CATALOG.isCatalogRequest(request)) return CATALOG; if (request.endsWith(".json")) return JSON.parse(fs.readFileSync(path.join(path.dirname(full), request), "utf8")); @@ -66,10 +56,8 @@ function loadTs(full) { if (request.startsWith(prefix)) return loadTs(resolve(path.join(ROOT, dir, request.slice(prefix.length)))); return loadTs(resolve(path.join(path.dirname(full), request))); - }; - new Function("exports", "module", "require", js)(box.exports, box, near); - return box.exports; -} + }, +}); const design = path.join(ROOT, "A00_Common", "design"); const { createFacilityLane } = loadTs(path.join(design, "design_facility_lane.ts")); diff --git a/resources/tester/helper_476_1_flatten.cjs b/resources/tester/helper_476_1_flatten.cjs index 55402bede..2d752e640 100644 --- a/resources/tester/helper_476_1_flatten.cjs +++ b/resources/tester/helper_476_1_flatten.cjs @@ -5,27 +5,17 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); -const cache = new Map(); -function loadTs(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) => +const { loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => (request) => request.startsWith(".") ? loadTs(path.join(path.dirname(full), `${request}.ts`)) - : require(request); - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - cache.set(full, box.exports); - return box.exports; -} + : require(request), +}); const edits = loadTs(path.join(ROOT, "B05_Profile", "logic", "B05_Profile_UI_RouteEdit_Edits.ts")); const body = JSON.parse(fs.readFileSync(process.argv[2], "utf8")); diff --git a/resources/tester/helper_476_2_initial_profile.cjs b/resources/tester/helper_476_2_initial_profile.cjs index 74dc83276..5da70b77c 100644 --- a/resources/tester/helper_476_2_initial_profile.cjs +++ b/resources/tester/helper_476_2_initial_profile.cjs @@ -3,10 +3,9 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); -const cache = new Map(); function memoryStorage() { const map = new Map(); @@ -27,26 +26,17 @@ globalThis.fetch = () => Promise.resolve({ ok: false }); const STUBS = { "@ui/ui_template_palette": { themeColor: (_name, fallback) => fallback } }; -function loadTs(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) => { +const { loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => (request) => { if (STUBS[request]) return STUBS[request]; if (request.endsWith(".css")) return {}; if (request.startsWith("@ui/")) return loadTs(path.join(ROOT, "ui_template", `${request.slice(4)}.ts`)); if (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`)); return require(request); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - cache.set(full, box.exports); - return box.exports; -} + }, +}); const model = loadTs(path.join(ROOT, "B05_Profile", "B05_Profile_UI_RouteEdit_Initial_Model.ts")); const prof = loadTs( diff --git a/resources/tester/helper_493_3_follow_steps.cjs b/resources/tester/helper_493_3_follow_steps.cjs index d2be8d33f..848c76219 100644 --- a/resources/tester/helper_493_3_follow_steps.cjs +++ b/resources/tester/helper_493_3_follow_steps.cjs @@ -7,21 +7,19 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); function loadTs(file, stubs = {}) { - const js = ts.transpileModule(fs.readFileSync(path.join(ROOT, file), "utf8"), { - compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 }, - }).outputText; - const box = { exports: {} }; - const localRequire = (request) => { - if (stubs[request]) return stubs[request]; - throw new Error(`stub 없음: ${request} (${file})`); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - return box.exports; + return makeLoader({ + root: ROOT, + cache: false, + requireFor: (full) => (request) => { + if (stubs[request]) return stubs[request]; + throw new Error(`stub 없음: ${request} (${file})`); + }, + }).loadTs(path.join(ROOT, file)); } const catalog = require("./helper_322_catalog_module.cjs"); diff --git a/resources/tester/helper_54_10_soil_tiers.cjs b/resources/tester/helper_54_10_soil_tiers.cjs index b75a8794b..22f7f2c14 100644 --- a/resources/tester/helper_54_10_soil_tiers.cjs +++ b/resources/tester/helper_54_10_soil_tiers.cjs @@ -4,11 +4,10 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const CATALOG = require("./helper_322_catalog_module.cjs"); // 구조물 표(322-1) const ROOT = path.join(__dirname, "..", ".."); -const cache = new Map(); // ── 화면 그릇 흉내 — 태그 · 클래스 · data 만 ───────────────────────────────── class FakeNode { @@ -97,25 +96,16 @@ const STUBS = { "../../B05_Profile/B05_Profile_UI_Structures_Summary_Row": { buildSummaryRow: () => null }, }; -function loadTs(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) => { +const { loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => (request) => { if (CATALOG.isCatalogRequest(request)) return CATALOG; if (STUBS[request]) return STUBS[request]; if (request.startsWith("@util/")) return loadTs(path.join(ROOT, "common_util", `${request.slice(6)}.ts`)); return loadTs(path.join(path.dirname(full), `${request}.ts`)); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - cache.set(full, box.exports); - return box.exports; -} + }, +}); const out = {}; diff --git a/resources/tester/helper_54_12_live_required.cjs b/resources/tester/helper_54_12_live_required.cjs index 7d322b0db..c98033e58 100644 --- a/resources/tester/helper_54_12_live_required.cjs +++ b/resources/tester/helper_54_12_live_required.cjs @@ -4,11 +4,10 @@ */ const fs = require("fs"); const path = require("path"); -const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const CATALOG = require("./helper_322_catalog_module.cjs"); // 구조물 표(322-1) const ROOT = path.join(__dirname, "..", ".."); -const cache = new Map(); const session = new Map(); const fakeStorage = { getItem: (k) => session.get(k) ?? null, @@ -23,25 +22,16 @@ const STUBS = { "./ui_template_checkbox.css": {}, }; -function loadTs(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) => { +const { loadTs } = makeLoader({ + root: ROOT, + requireFor: (full) => (request) => { if (CATALOG.isCatalogRequest(request)) return CATALOG; if (STUBS[request]) return STUBS[request]; if (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`)); if (request.startsWith("@")) return new Proxy({}, { get: () => () => {} }); return require(request); - }; - new Function("exports", "module", "require", js)(box.exports, box, localRequire); - cache.set(full, box.exports); - return box.exports; -} + }, +}); const { commit } = loadTs( path.join(ROOT, "B05_Profile", "B05_Profile_UI_Structures_Panel_Commit.ts"), diff --git a/resources/tester/helper_ts_stub_loader.cjs b/resources/tester/helper_ts_stub_loader.cjs index d41c94492..30eb9b369 100644 --- a/resources/tester/helper_ts_stub_loader.cjs +++ b/resources/tester/helper_ts_stub_loader.cjs @@ -29,7 +29,7 @@ function memoryStorage() { } /* 옵션 — 옮겨 온 옛 헬퍼가 저마다 달리 쓰던 것(헬퍼 동작 그대로). - * requireFor(full) 풀이 함수를 헬퍼가 직접 지음(기본 풀이 대신) · 인자 없으면 진짜 require + * requireFor(full, file) 풀이 함수를 헬퍼가 직접 지음(기본 풀이 대신) · 인자 없으면 진짜 require * interop esModuleInterop 로 트랜스파일 * cache:false 같은 파일을 부를 때마다 새로 읽음(기본은 한 번만) * fileStub(full) 파일 경로로 통째 대신할 값(없으면 undefined) */ @@ -73,7 +73,7 @@ function makeLoader({ const js = ts.transpileModule(fs.readFileSync(full, "utf8"), { compilerOptions }).outputText; const box = { exports: {} }; if (useCache) cache.set(full, box.exports); - const localRequire = requireFor ? requireFor(full) : defaultRequire(full); + const localRequire = requireFor ? requireFor(full, file) : defaultRequire(full); new Function("exports", "module", "require", js)(box.exports, box, localRequire); if (useCache) cache.set(full, box.exports); return box.exports;