#!/usr/bin/env node // Copies module NN's tests for the learner's track into /tests/. import { cpSync, existsSync, mkdirSync, readFileSync } from "node:fs"; import { basename, join } from "node:path"; import { moduleDirs, courseRoot, testFiles, fail } from "./lib.mjs"; const [num, ws] = process.argv.slice(2); if (!/^\d\d$/.test(num || "") || !ws) fail("usage: start-module.mjs "); if (num === "00") fail("Module 00 is not startable: M0 uses the naive-engine/ project, not a workspace."); const cfg = JSON.parse(readFileSync(join(ws, ".course.json"), "utf8")); const track = cfg.track; if (track !== "rust" && track !== "ts") fail(`bad track in .course.json: ${track}`); const mods = moduleDirs(); const mod = mods.find((m) => m.num === num); if (!mod) fail(`no module ${num} in ${courseRoot()}`); if (num !== "01") { const prevNum = String(Number(num) - 1).padStart(2, "0"); const prev = mods.find((m) => m.num === prevNum); if (prev) { const missing = testFiles(prev.path, track).map((f) => basename(f)) .filter((f) => !existsSync(join(ws, "tests", f))); if (missing.length) fail(`Cannot start module ${num}: finish module ${prevNum} first. Missing tests/${missing.join(", tests/")}`); } } const files = testFiles(mod.path, track); if (!files.length) fail(`module ${num} has no ${track} tests`); mkdirSync(join(ws, "tests"), { recursive: true }); for (const f of files) cpSync(f, join(ws, "tests", basename(f))); console.log(`Copied ${files.length} test file(s) for module ${num} into ${join(ws, "tests")}`); // Harness additions: module-local note, else the "- M:" line of course/harness.md. const note = join(mod.path, "harness-adds.md"); let adds = existsSync(note) ? readFileSync(note, "utf8").trim() : ""; if (!adds) { const h = join(courseRoot(), "harness.md"); if (existsSync(h)) { const re = new RegExp(`^\\s*[-*]\\s*\\**M${Number(num)}\\b.*$`, "m"); adds = (re.exec(readFileSync(h, "utf8")) || [""])[0].trim(); } } console.log(adds ? `Harness functions added by module ${num}:\n${adds}` : `No harness additions recorded for module ${num} (see course/harness.md).`);