runPatch
uses tcmts.cli.main.execute, which uses tcmts.cli.help.usageError, which uses tcmts.cli.help.usageOf, which uses tcmts.cli.style.bold, which uses node:util
Runs tcm patch.
import { routePatch } from "#codebase/tcmts/cli/commands"; import { execute, patch, patchImportsOf, patchMany } from "#codebase/tcmts/cli/main"; import type { PatchEdit, PatchImport } from "#codebase/tcmts/cli/main"; import type { Context } from "#codebase/tcmts/cli/run"; import { dim } from "#codebase/tcmts/cli/style"; import { UsageError } from "#codebase/tcmts/cli/ui"; import { parse } from "@bomb.sh/router"; export function runPatch({ cb, cmd, rest }: Context): number { const { model } = execute(cmd, parse(routePatch(), { argv: rest })); // several definitions, saved together if (model.patches !== undefined) { if (model.name) throw new UsageError("tcm patch takes a <name> or --patches, not both"); let patches: { name: string; edits: PatchEdit[]; all?: boolean }[]; try { patches = ( JSON.parse(model.patches) as { name?: unknown; edits?: { old?: unknown; new?: unknown }[]; all?: unknown; imports?: unknown; }[] ).map((p, i) => ({ name: String(p.name ?? ""), edits: (p.edits ?? []).map((e) => ({ old: String(e.old ?? ""), new: String(e.new ?? ""), })), all: p.all === true, imports: patchImportsOf(p.imports, `--patches[${i}].imports`), })); } catch (e) { if (e instanceof UsageError) throw e; throw new UsageError(`--patches isn't JSON: ${(e as Error).message}`); } return patchMany(cb, patches) ? 0 : 1; } if (!model.name) throw new UsageError( 'usage: tcm patch <name> --old <text> --new <text> (or --edits \'[{"old": "…", "new": "…"}]\')', ); let edits: PatchEdit[] = []; if (model.edits !== undefined) { try { edits = (JSON.parse(model.edits) as PatchEdit[]).map((e) => ({ old: String(e.old ?? ""), new: String(e.new ?? ""), })); } catch (e) { throw new UsageError(`--edits isn't JSON: ${(e as Error).message}`); } } if (model.old !== undefined) edits.push({ old: model.old, new: model.new ?? "" }); if (!edits.length) throw new UsageError("tcm patch needs --old and --new, or --edits"); let imports: PatchImport[] = []; try { imports = patchImportsOf( model.imports === undefined ? undefined : JSON.parse(model.imports), "--imports", ); } catch (e) { if (e instanceof UsageError) throw e; throw new UsageError(`--imports isn't JSON: ${(e as Error).message}`); } // --old and --new are as written: a `\n` in them (as a shell's '…' leaves it) is a backslash and an n, as it is // in code ("a\nb"); one that looks meant as a line break is said const escape = /\\[nt]/; const literally = "(--old and --new are taken as written: a \\n is a backslash and an n, not a line break; write a line break as one, inside the quotes or as $'…\\n…' in a shell, or give --edits as JSON)"; if (model.new !== undefined && escape.test(model.new) && !escape.test(model.old ?? "")) console.log( dim( "note: a \\n or \\t in --new is kept as written, a backslash and a letter (a line break is written as one, inside the quotes or as $'…\\n…' in a shell, or in --edits JSON)", ), ); try { return patch(cb, model.name, edits, model.all, imports) ? 0 : 1; } catch (e) { if (e instanceof UsageError && escape.test(model.old ?? "") && /not found/.test(e.message)) throw new UsageError(`${e.message}\n${literally}`); throw e; } }
uses
- tcmts.cli.commands.routePatch
- tcmts.cli.main.PatchEdit
- tcmts.cli.main.PatchImport
- tcmts.cli.main.execute
- tcmts.cli.main.patch
- tcmts.cli.main.patchImportsOf
- tcmts.cli.main.patchMany
- tcmts.cli.run.Context
- tcmts.cli.style.dim
- tcmts.cli.ui.UsageError