generatedNotes

tcmts.cli.releases.generatedNotes · #fmksdr25 · term · runs on the server

uses tcmts.cli.releases.contributionsIn, which uses tcmts.cli.manifests.packagesIn, which uses tcmts.cli.config.configValue, which uses node:path

The generated part of a release's notes.

import type { Codebase } from "#codebase/tcmts/cli/codebase";
import { code, contributionsIn } from "#codebase/tcmts/cli/releases";
import type { Plan } from "#codebase/tcmts/cli/releases";
import { levelOf, LINTS } from "#codebase/tcmts/cli/semver_checks";
import type { Finding } from "#codebase/tcmts/cli/semver_checks";
import type { Contribution } from "#codebase/tcmts/store";

export function generatedNotes(cb: Codebase, plan: Plan, contributions: Contribution[]): string {
  const lines: string[] = [];
  const section = (title: string, items: string[]) => items.length && lines.push(`### ${title}`, "", ...items.map((i) => `- ${i}`), "");
  if (!plan.report) {
    const subs = [...new Set(plan.now.exported.values())].sort();
    lines.push(`The first release: ${plan.now.exported.size} definition(s)${subs.length > 1 ? `, from ${subs.map(code).join(", ")}` : ""}.`, "");
  } else {
    const { findings, summaries, signatures } = plan.report;
    const line = (f: Finding) => {
      if (f.lint === "definition_removed") return `${code(f.path)} removed`;
      if (f.lint === "definition_renamed") return `${code(f.path)} renamed to ${code(f.detail!)}`;
      if (f.lint === "bin_removed" || f.lint === "bin_added") return `the ${code(f.path)} command ${f.lint === "bin_removed" ? "removed" : "added"}`;
      if (f.lint === "definition_added") return `${code(f.path)}${signatures.has(f.path) ? ` ${code(signatures.get(f.path)!)}` : ""}${summaries.has(f.path) ? `: ${summaries.get(f.path)}` : ""}`;
      if (f.lint === "implementation_changed") return `${code(f.path)}${summaries.has(f.path) ? `: ${summaries.get(f.path)}` : ""} (new implementation, same API)`;
      return `${code(f.path)} ${LINTS[f.lint].summary}${f.detail ? `: ${code(f.detail)}` : ""}`;
    };
    section("Breaking changes", findings.filter((f) => levelOf(f) === "major").map(line));
    section("Added", findings.filter((f) => f.lint === "definition_added" || f.lint === "bin_added").map(line));
    section("Extended", findings.filter((f) => levelOf(f) === "minor" && f.lint !== "definition_added" && f.lint !== "bin_added").map(line));
    section("Changed", findings.filter((f) => levelOf(f) === "patch").map(line));
    if (!findings.length) lines.push(`No changes to the API since ${plan.prev!.version}.`, "");
  }
  section("Contributions", contributionsIn(cb, contributions, plan).map((c) => `#${c.id} ${c.title} (${c.author})`));
  while (lines.at(-1) === "") lines.pop();
  return lines.join("\n");
}

uses

used by