editDefinition
uses node:path
Write the definition name into a scratch file to edit, as tcm edit <name> does: code into scratch.ts (or
scratch.tsx for JSX), beside what it holds already; a file kept as written into one of its own, named as it is
(or, being edited there already, that one); a conflicted name, its definitions merged, into a file named after it.
While a merge waits apart, as merged (tcm edit writes it). The file's name.
import { fileName, isBytes } from "#codebase/tcmts/cli/files"; import { edit, editFiles } from "#codebase/tcmts/cli/main"; import { conflictAt } from "#codebase/tcmts/cli/merge"; import { HttpError } from "#codebase/tcmts/server"; import { editableCodebase, keptFile, mergeWaiting, runTcm, scratchDir, setKeptInto } from "#codebase/tcmts/studio"; import fs from "node:fs"; import path from "node:path"; export async function editDefinition(name: string): Promise<string> { const cb = editableCodebase(); const dir = scratchDir(cb); // (with a merge waiting apart, only a command sees the branch as merged; a conflict's file is named after it: tcm // edit writes them, and says where) if (mergeWaiting(cb) || conflictAt(cb, name)) { const out = await runTcm(cb.lay.root, ["edit", name], { branch: true }); const wrote = /^(?:wrote|added) .+ to (\S+)$/m.exec(out.text)?.[1]; if (out.code !== 0 || !wrote) throw new HttpError( 400, out.text.split("\n").slice(0, 8).join("\n") || `tcm edit ${name} failed`, ); return path.basename(wrote); } const file = cb .lookup(name) .map((h) => cb.store.getDef(h)) .find((r) => r?.kind === "file"); try { if (file) { if (isBytes(file)) throw new HttpError( 400, `${name} isn't text: it's edited as the file it is, outside the studio.`, ); const out = path.join(dir, fileName(name.slice(name.lastIndexOf(".") + 1), file)); if (fs.existsSync(out) && keptFile(cb, out) === name) return path.basename(out); editFiles(cb, [name], out, false); setKeptInto(cb, out, name); return path.basename(out); } let wrote = ""; // (the last file it asks for is the one it writes) edit(cb, [name], (jsx) => (wrote = path.join(dir, jsx ? "scratch.tsx" : "scratch.ts")), false); return path.basename(wrote); } catch (e) { if (e instanceof HttpError) throw e; throw new HttpError(400, (e as Error).message); } }
uses
- tcmts.cli.files.fileName
- tcmts.cli.files.isBytes
- tcmts.cli.main.edit
- tcmts.cli.main.editFiles
- tcmts.cli.merge.conflictAt
- tcmts.server.HttpError
- tcmts.studio.editableCodebase
- tcmts.studio.keptFile
- tcmts.studio.mergeWaiting
- tcmts.studio.runTcm
- tcmts.studio.scratchDir
- tcmts.studio.setKeptInto