ScratchPage

tcmts.studio.ScratchPage · #bsxjwziz · term · runs on the server

uses node:path

A scratch file, to edit (ScratchEditor; show, a definition it holds, in view as it opens): read only while the browser reads another branch, since what it saves goes to the codebase's own.

import { HttpError } from "#codebase/tcmts/server";
import { at, servedCodebase, shareNow } from "#codebase/tcmts/share";
import { scratchDir, ScratchEditor, scratchPath, StudioFrame, studioShare } from "#codebase/tcmts/studio";
import fs from "node:fs";
import path from "node:path";

export async function ScratchPage({ file, show }: { file: string; show: string }) {
  studioShare();
  const s = shareNow();
  if (!s.signedIn)
    return (
      <StudioFrame tab="scratch" title="Sign in">
        {null}
      </StudioFrame>
    );
  const own = servedCodebase().cb;
  // (gone: saved, or thrown away; a kept file's name says nothing of it then)
  if (path.basename(file) === file && !fs.existsSync(path.join(scratchDir(own), file)))
    return (
      <StudioFrame tab="scratch" title={file}>
        <div className="box">
          <div className="empty">
            {`There's no ${file}: updating the codebase with it saved what it held, or it was thrown away. `}
            <a href={at("/scratch")}>Scratch files</a>
          </div>
        </div>
      </StudioFrame>
    );
  let abs: string;
  try {
    abs = scratchPath(own, file);
  } catch (e) {
    if (!(e instanceof HttpError)) throw e;
    return (
      <StudioFrame tab="scratch" title={file}>
        <div className="empty">{e.message}</div>
      </StudioFrame>
    );
  }
  return (
    <StudioFrame tab="scratch" title={file}>
      <ScratchEditor
        key={file}
        file={file}
        initial={fs.readFileSync(abs, "utf8")}
        readOnly={s.cb !== own}
        {...(show ? { show } : {})}
      />
    </StudioFrame>
  );
}

uses

used by