1// @effect-diagnostics nodeBuiltinImport:off - a one-off maintenance script with no
2// Effect runtime; it only spawns vitest and reads and writes two files.
3import * as NodeChildProcess from "node:child_process";
4import * as NodeFS from "node:fs";
5import * as NodeOS from "node:os";
6import * as NodePath from "node:path";
7import * as NodeURL from "node:url";
8
9const MIN_RECORDED_SECONDS = 0.5;
10
11interface VitestJsonReport {
12 readonly testResults: ReadonlyArray<{
13 readonly name: string;
14 readonly startTime: number;
15 readonly endTime: number;
16 }>;
17}
18
19const serverDir = NodeURL.fileURLToPath(new URL("..", import.meta.url));
20const weightsPath = NodePath.join(serverDir, "src/testUtils/shardWeights.json");
21const reportDir = NodeFS.mkdtempSync(NodePath.join(NodeOS.tmpdir(), "t3-server-test-report-"));
22const reportPath = NodePath.join(reportDir, "report.json");
23
24// `node --run` finds the package's vp; failed tests still report durations, so ignore exit status.
25NodeChildProcess.spawnSync(
26 process.execPath,
27 ["--run", "test", "--", "--reporter=json", `--outputFile=${reportPath}`],
28 { cwd: serverDir, stdio: "inherit" },
29);
30
31const report: VitestJsonReport = JSON.parse(NodeFS.readFileSync(reportPath, "utf8"));
32NodeFS.rmSync(reportDir, { recursive: true, force: true });
33
34const weights = Object.fromEntries(
35 report.testResults
36 .map(
37 (file) =>
38 [
39 NodePath.relative(serverDir, file.name).replaceAll("\\", "/"),
40 Math.round((file.endTime - file.startTime) / 100) / 10,
41 ] as const,
42 )
43 .filter(([, seconds]) => seconds >= MIN_RECORDED_SECONDS)
44 .toSorted(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)),
45);
46
47NodeFS.writeFileSync(weightsPath, `${JSON.stringify(weights, null, 2)}\n`);