fetchProduction

tcmts.studio.fetchProduction · #olfs75tm · term · runs on the server

uses node:fs

Fetch production's traces (GET /__tcm/traces.sqlite on its server, with its traces token) into the studio's copy, which its traces pages read: what came, or why nothing did.

import { HttpError } from "#codebase/tcmts/server";
import { editableCodebase, production, productionFile, productionTraces } from "#codebase/tcmts/studio";
import fs from "node:fs";
import { Readable } from "node:stream";
import { pipeline } from "node:stream/promises";

export async function fetchProduction(): Promise<string> {
  const cb = editableCodebase();
  const p = production(cb);
  if (!p) throw new HttpError(409, "Production isn't set up yet: its address and traces token.");
  let res: Response;
  try {
    res = await fetch(`${p.url}/__tcm/traces.sqlite`, {
      headers: { authorization: `Bearer ${p.token}`, "accept-encoding": "gzip" },
      signal: AbortSignal.timeout(120_000),
    });
  } catch (e) {
    throw new HttpError(502, `${p.url} didn't answer: ${(e as Error).message}`);
  }
  if (res.status === 401)
    throw new HttpError(401, `${p.url} didn't take the token: it's the server's TCM_TRACES_TOKEN.`);
  if (res.status === 404)
    throw new HttpError(
      404,
      `${p.url} hands out no traces: set TCM_TRACES_TOKEN where it runs (tcm start), to the token given here.`,
    );
  if (res.status === 204) {
    fs.rmSync(productionTraces(cb), { force: true });
    return "Production has no traces yet.";
  }
  if (!res.ok || !res.body) throw new HttpError(502, `${p.url} answered ${res.status}.`);
  const tmp = `${productionTraces(cb)}.part`;
  await pipeline(Readable.fromWeb(res.body as never), fs.createWriteStream(tmp));
  fs.renameSync(tmp, productionTraces(cb));
  fs.writeFileSync(
    productionFile(cb),
    `${JSON.stringify({ ...p, fetched: Date.now() }, null, 2)}\n`,
    { mode: 0o600 },
  );
  const mb = fs.statSync(productionTraces(cb)).size / 2 ** 20;
  return `Fetched production's traces (${mb < 1 ? "under 1" : Math.round(mb)} MB).`;
}

uses

used by