evaluateWatches

tcmts.loader.evaluateWatches · #tlap6jgp · term · runs on the server

uses node:path

Evaluate watch expressions (already materialized as definitions) in a child process.

import { exportId } from "#codebase/tcmts/core/hash";
import { materialize, moduleFile, nodeArgs, runnerStdout, writeIfChanged } from "#codebase/tcmts/loader";
import type { DefSource, Layout, WatchResult } from "#codebase/tcmts/loader";
import { spawnSync } from "node:child_process";
import fs from "node:fs";
import path_2 from "node:path";

export function evaluateWatches(
  watches: { hash: string; componentHash: string; line: number }[],
  src: DefSource,
  lay: Layout,
): WatchResult[] {
  if (!watches.length) return [];
  materialize(
    watches.map((w) => w.hash),
    src,
    lay,
  );
  const runner = path_2.join(lay.cacheDir, "watch_runner.ts");
  const out = path_2.join(lay.cacheDir, "watch_results.json");
  fs.rmSync(out, { force: true });
  const list = watches.map((w) => [
    w.line,
    `./${moduleFile(w.componentHash, src)}`,
    exportId(w.hash),
  ]);
  writeIfChanged(
    runner,
    `import { inspect } from "node:util";
import { writeFileSync } from "node:fs";
const watches: [number, string, string][] = ${JSON.stringify(list)};
const results: { line: number; ok: boolean; value: string }[] = [];
const colors = !process.env.NO_COLOR;
for (const [line, file, id] of watches) {
  try {
    let value = (await import(file))[id];
    if (value && typeof value.then === "function") value = await value;
    results.push({ line, ok: true, value: inspect(value, { colors, depth: 4 }) });
  } catch (e) {
    results.push({ line, ok: false, value: inspect(e, { colors }) });
  }
}
writeFileSync(${JSON.stringify(out)}, JSON.stringify(results));
`,
  );
  // a session's branch (TCM_BRANCH) is this codebase's: codebases the code opens aren't on it; and its brief reports
  // (TCM_BRIEF) are tcm's, not what the code prints
  const { TCM_BRANCH: _, TCM_BRIEF: __, ...env } = process.env;
  spawnSync(process.execPath, [...nodeArgs(lay), runner], {
    stdio: ["inherit", runnerStdout, "inherit"],
    timeout: 10_000,
    env,
  });
  if (!fs.existsSync(out))
    return watches.map((w) => ({
      line: w.line,
      ok: false,
      value: "evaluation did not finish (timeout or crash)",
      infrastructure: true,
    }));
  return JSON.parse(fs.readFileSync(out, "utf8")) as WatchResult[];
}

uses

used by