writeBuildRoot

tcmts.cli.web.writeBuildRoot · #p232viin · term · runs on the server

uses node:fs

import type { Codebase } from "#codebase/tcmts/cli/codebase";
import { entrySource, escapeHtml, ssrSource } from "#codebase/tcmts/cli/web";
import type { AppState } from "#codebase/tcmts/cli/web";
import { writeIfChanged } from "#codebase/tcmts/loader";
import fs from "node:fs";
import path from "node:path";

export function writeBuildRoot(cb: Codebase, dir: string, appName: string, s: AppState) {
  fs.mkdirSync(dir, { recursive: true });
  // the pinned packages, found from here as from the cache: Vite's own lookups (server rendering decides what to
  // load with Node by them) see the same packages the generated modules import
  const modules = path.join(dir, "node_modules");
  // lstat: the link dangles until the codebase uses an npm package, and existsSync follows it
  // (another build of the same app, side by side, a verify's of another branch, may make it first)
  if (!fs.lstatSync(modules, { throwIfNoEntry: false }))
    try {
      fs.symlinkSync(
        path.relative(dir, path.join(cb.lay.cacheDir, "node_modules")),
        modules,
        "dir",
      );
    } catch (e) {
      if ((e as NodeJS.ErrnoException).code !== "EEXIST") throw e;
    }
  writeIfChanged(
    path.join(dir, "index.html"),
    `<!doctype html>\n<html>\n  <head><meta charset="utf-8" /><title>${escapeHtml(appName)}</title></head>\n  <body>\n    <div id="app"></div>\n    <script type="module" src="/entry.ts"></script>\n  </body>\n</html>\n`,
  );
  const cacheRel = path.relative(dir, cb.lay.cacheDir).split(path.sep).join("/");
  writeIfChanged(path.join(dir, "entry.ts"), entrySource(cb, appName, s, cacheRel));
  if (s.react && !s.plan.errors.length)
    writeIfChanged(path.join(dir, "ssr.ts"), ssrSource(cb, appName, s, cacheRel));
  else fs.rmSync(path.join(dir, "ssr.ts"), { force: true });
}

uses

used by