configValue

tcmts.cli.config.configValue · #t2inu7hd · term · runs on the server

uses node:path

A stored definition's value (any version of it, by hash), evaluated once per hash; functions in it are dropped. A hash fixes the value, so it's kept in the codebase: later commands don't evaluate it again.

import { values } from "#codebase/tcmts/cli/config";
import type { Evaluating } from "#codebase/tcmts/cli/config";
import { materialize, nodeArgs } from "#codebase/tcmts/loader";
import { spawnSync } from "node:child_process";
import fs from "node:fs";
import path_1 from "node:path";

export function configValue(
  cb: Evaluating,
  hash: string,
  name = hash.slice(0, 8),
): Record<string, unknown> {
  const rec = cb.store.getDef(hash)!;
  const kept = values.has(hash) ? undefined : cb.store.getMetadata(hash, "value");
  if (kept !== undefined) values.set(hash, JSON.parse(kept));
  if (!values.has(hash)) {
    materialize([hash], cb.source(), cb.lay);
    const runner = path_1.join(cb.lay.cacheDir, `config_${hash}.ts`);
    fs.writeFileSync(
      runner,
      `import { h_${hash} as config } from "./${path_1.basename(cb.modulePath(rec.componentHash))}";\n` +
        `const value: unknown = typeof config === "function" ? await (config as () => unknown)() : config;\n` +
        `process.stdout.write(JSON.stringify(value ?? {}, (_k, v) => (typeof v === "function" ? undefined : v)));\n`,
    );
    const r = spawnSync(process.execPath, [...nodeArgs(cb.lay), runner], { encoding: "utf8" });
    fs.rmSync(runner, { force: true });
    if (r.status !== 0) throw new Error(`${name} failed to evaluate:\n${r.stderr}`);
    values.set(hash, JSON.parse(r.stdout || "{}"));
    cb.store.setMetadata(hash, "value", r.stdout || "{}");
  }
  return values.get(hash) as Record<string, unknown>;
}

uses

used by