@cellajs/cli 0.5.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -57,7 +57,7 @@ import { z as z2 } from "zod";
57
57
 
58
58
  // src/config/types.ts
59
59
  import { z } from "zod";
60
- var PACKAGE_JSON_SYNC_KEYS = [
60
+ var PACKAGE_JSON_KEYS = [
61
61
  "dependencies",
62
62
  "devDependencies",
63
63
  "peerDependencies",
@@ -75,7 +75,9 @@ var cellaConfigSchema = z.object({
75
75
  upstreamBranch: z.string().min(1).optional(),
76
76
  upstreamTrack: z.enum(["release", "branch"]).optional(),
77
77
  releaseBase: z.string().min(1).optional(),
78
- packageJsonSync: z.array(z.enum(PACKAGE_JSON_SYNC_KEYS)).optional(),
78
+ packageJsonKeys: z.array(z.enum(PACKAGE_JSON_KEYS)).optional(),
79
+ mergePackageJson: z.boolean().optional(),
80
+ packageJsonSync: z.array(z.enum(PACKAGE_JSON_KEYS)).optional(),
79
81
  syncWithPackages: z.boolean().optional(),
80
82
  fileLinkMode: z.enum(["commit", "file"]).optional()
81
83
  }).strict(),
@@ -156,13 +158,18 @@ function resolveAppModuleFolders(repoPath) {
156
158
  // src/utils/config.ts
157
159
  var DEFAULT_UPSTREAM_REMOTE = "cella-upstream";
158
160
  var DEFAULT_BRANCH = "main";
159
- var DEFAULT_SYNC_PREFIX = "cella/sync";
160
- var DEFAULT_PACKAGE_JSON_SYNC = ["dependencies", "devDependencies"];
161
+ var UPGRADE_BRANCH_PREFIX = "cella/upgrade";
162
+ var TEMPORARY_BRANCH_PREFIXES = [UPGRADE_BRANCH_PREFIX, "cella/sync"];
163
+ var DEFAULT_PACKAGE_JSON_KEYS = ["dependencies", "devDependencies"];
164
+ var RENAMED_SETTINGS = { packageJsonSync: "packageJsonKeys", syncWithPackages: "mergePackageJson" };
165
+ function renamedSettingWarnings(config) {
166
+ return Object.entries(RENAMED_SETTINGS).filter(([old]) => old in config.settings).map(([old, current]) => `settings.${old} is renamed to ${current}: rename it in ${CONFIG_FILE}`);
167
+ }
161
168
  function isUpstreamRepo(repoPath) {
162
169
  return JSON.parse(readFileSync(join2(repoPath, "package.json"), "utf8")).name === "cella";
163
170
  }
164
171
  function isTemporarySyncBranch(branch) {
165
- return branch.startsWith(`${DEFAULT_SYNC_PREFIX}/`);
172
+ return TEMPORARY_BRANCH_PREFIXES.some((prefix) => branch.startsWith(`${prefix}/`));
166
173
  }
167
174
  function resolveReleaseBase(settings) {
168
175
  return settings.releaseBase ?? DEFAULT_BRANCH;
@@ -171,7 +178,7 @@ function buildTemporarySyncBranch() {
171
178
  const now = /* @__PURE__ */ new Date();
172
179
  const pad2 = (n) => String(n).padStart(2, "0");
173
180
  const stamp = `${now.getFullYear()}${pad2(now.getMonth() + 1)}${pad2(now.getDate())}-${pad2(now.getHours())}${pad2(now.getMinutes())}`;
174
- return `${DEFAULT_SYNC_PREFIX}/${stamp}`;
181
+ return `${UPGRADE_BRANCH_PREFIX}/${stamp}`;
175
182
  }
176
183
  function resolveUpstream(settings) {
177
184
  const track = settings.upstreamTrack ?? "release";
@@ -201,6 +208,8 @@ async function loadConfig(forkPath) {
201
208
  ${z2.prettifyError(result.error)}`);
202
209
  }
203
210
  const config = result.data;
211
+ config.settings.packageJsonKeys ??= config.settings.packageJsonSync;
212
+ config.settings.mergePackageJson ??= config.settings.syncWithPackages;
204
213
  const appModuleFolders = resolveAppModuleFolders(realForkPath);
205
214
  if (appModuleFolders.length > 0) {
206
215
  const existing = config.overrides?.ignored ?? [];
@@ -219,10 +228,10 @@ import process5 from "process";
219
228
  // package.json
220
229
  var package_default = {
221
230
  name: "@cellajs/cli",
222
- version: "0.5.0",
231
+ version: "0.6.1",
223
232
  private: false,
224
233
  license: "MIT",
225
- description: "CLI for managing your monorepo and syncing with upstream Cella.",
234
+ description: "CLI for managing your monorepo and upgrading it with upstream Cella.",
226
235
  repository: {
227
236
  type: "git",
228
237
  url: "https://github.com/cellajs/cella-cli"
@@ -746,16 +755,25 @@ async function cleanupEmptyParentDirs(cwd, relativePath) {
746
755
  } catch {
747
756
  }
748
757
  }
758
+ var LAST_UPGRADE_REF = "refs/cella/last-upgrade";
759
+ var LEGACY_LAST_UPGRADE_REF = "refs/cella/last-sync";
749
760
  async function storeLastSyncRef(cwd, upstreamHash) {
750
- await git(["update-ref", "refs/cella/last-sync", upstreamHash], cwd);
761
+ await git(["update-ref", LAST_UPGRADE_REF, upstreamHash], cwd);
751
762
  const head = await revParse(cwd, "HEAD");
752
- if (head) await git(["update-ref", "refs/cella/last-sync-head", head], cwd);
763
+ if (head) await git(["update-ref", `${LAST_UPGRADE_REF}-head`, head], cwd);
753
764
  }
754
765
  async function stagePath(cwd, path) {
755
766
  await git(["add", "--", path], cwd, { ignoreErrors: true });
756
767
  }
768
+ async function readStoredSyncRefs(cwd) {
769
+ for (const name of [LAST_UPGRADE_REF, LEGACY_LAST_UPGRADE_REF]) {
770
+ const ref = await revParse(cwd, name);
771
+ if (ref) return { ref, head: await revParse(cwd, `${name}-head`) };
772
+ }
773
+ return null;
774
+ }
757
775
  async function getStoredSyncRef(cwd) {
758
- return revParse(cwd, "refs/cella/last-sync");
776
+ return (await readStoredSyncRefs(cwd))?.ref ?? null;
759
777
  }
760
778
  async function readManifestAtRef(cwd, ref) {
761
779
  const raw = await git(["show", `${ref}:${MANIFEST_FILE}`], cwd, { ignoreErrors: true });
@@ -804,11 +822,11 @@ async function unshallowRepository(cwd) {
804
822
  ${error.message}` : "";
805
823
  throw new Error(
806
824
  `this is a shallow clone and its full history could not be restored automatically.
807
- Sync needs the complete history to find the common ancestor with upstream. Restore it with:
825
+ An upgrade needs the complete history to find the common ancestor with upstream. Restore it with:
808
826
 
809
827
  git fetch --unshallow
810
828
 
811
- then re-run sync.${detail}`
829
+ then re-run the upgrade.${detail}`
812
830
  );
813
831
  }
814
832
  }
@@ -834,20 +852,20 @@ async function ensureSyncBase(cwd, headRef, upstreamRef) {
834
852
  }
835
853
  if (!baseSha) {
836
854
  throw new Error(
837
- `no common ancestor between the fork and '${upstreamRef}', and no sync base could be determined.
855
+ `no common ancestor between the fork and '${upstreamRef}', and no upgrade base could be determined.
838
856
 
839
857
  This fork has unrelated history with upstream (typical for a create-cella scaffold, or after
840
858
  upstream squashed its history) and no recorded base commit exists after fetching
841
- upstream. Seed it manually with the upstream commit the fork was created from, then re-run sync:
859
+ upstream. Seed it manually with the upstream commit the fork was created from, then re-run the upgrade:
842
860
 
843
- git update-ref refs/cella/last-sync <upstream-sha>
861
+ git update-ref ${LAST_UPGRADE_REF} <upstream-sha>
844
862
  `
845
863
  );
846
864
  }
847
865
  const root = await getRootCommit(cwd, headRef);
848
- if (!root) throw new Error("could not determine the fork's root commit to bootstrap sync ancestry");
866
+ if (!root) throw new Error("could not determine the fork's root commit to bootstrap upgrade ancestry");
849
867
  await git(["replace", "-f", "--graft", root, baseSha], cwd);
850
- await git(["update-ref", "refs/cella/last-sync", baseSha], cwd);
868
+ await git(["update-ref", LAST_UPGRADE_REF, baseSha], cwd);
851
869
  }
852
870
  async function isAncestor(cwd, ancestor, descendant) {
853
871
  try {
@@ -858,14 +876,13 @@ async function isAncestor(cwd, ancestor, descendant) {
858
876
  }
859
877
  }
860
878
  async function getLegacySyncRef(cwd, headRef) {
861
- const storedRef = await getStoredSyncRef(cwd);
862
- if (!storedRef) return null;
863
- const storedHead = await revParse(cwd, "refs/cella/last-sync-head");
864
- if (storedHead) {
879
+ const stored = await readStoredSyncRefs(cwd);
880
+ if (!stored) return null;
881
+ if (stored.head) {
865
882
  const currentHead = await revParse(cwd, headRef);
866
- if (currentHead && currentHead === storedHead) return null;
883
+ if (currentHead && currentHead === stored.head) return null;
867
884
  }
868
- return storedRef;
885
+ return stored.ref;
869
886
  }
870
887
  async function getEffectiveMergeBase(cwd, headRef, upstreamRef) {
871
888
  const gitBase = await getMergeBase(cwd, headRef, upstreamRef);
@@ -1044,7 +1061,7 @@ ${colors_default.dim(forkPath)}`;
1044
1061
  }
1045
1062
  function formatUpstreamStep(upstream) {
1046
1063
  const { label, sha, baseSha, pinned, commitCount, commits, githubUrl } = upstream;
1047
- const since = commitCount === 0 ? "no new commits since the last sync" : `${plural(commitCount, "new commit")} since the last sync at ${baseSha}`;
1064
+ const since = commitCount === 0 ? "no new commits since the last upgrade" : `${plural(commitCount, "new commit")} since the last upgrade at ${baseSha}`;
1048
1065
  return [
1049
1066
  `${label} @ ${sha}${colors_default.dim(`${pinned ? " \xB7 --ref" : ""} \xB7 ${since}`)}`,
1050
1067
  ...formatUpstreamCommits(commitCount, commits, githubUrl)
@@ -1111,7 +1128,7 @@ function formatMergeInProgressDetail(conflictCount, autoMergedFiles, linkOptions
1111
1128
  return lines.join("\n");
1112
1129
  }
1113
1130
  var statusConfig = {
1114
- behind: { icon: colors_default.cyan("\u2193"), label: "behind", color: colors_default.cyan, description: "upstream changed, will sync" },
1131
+ behind: { icon: colors_default.cyan("\u2193"), label: "behind", color: colors_default.cyan, description: "upstream changed, will update" },
1115
1132
  diverged: { icon: colors_default.magenta("\u21C5"), label: "diverged", color: colors_default.magenta, description: "both changed, will merge" },
1116
1133
  drifted: { icon: colors_default.yellow("!"), label: "drifted", color: colors_default.yellow, description: "fork changed (at risk)" },
1117
1134
  ahead: { icon: colors_default.blue("\u2191"), label: "ahead", color: colors_default.blue, description: "fork changed (protected)" },
@@ -1162,7 +1179,7 @@ function findProtectedBehindUpstream(result) {
1162
1179
  const ignoredOnly = new Set((result.ignoredUpstreamChanges ?? []).flatMap((group) => group.paths));
1163
1180
  return [...findProtectedBehind(result.files), ...result.files.filter((file) => ignoredOnly.has(file.path))];
1164
1181
  }
1165
- var PROTECTED_BEHIND_HINT = "pinned/ignored files where upstream also changed since the last sync; the fork side wins on conflict, so review what upstream changed and adopt what you need.";
1182
+ var PROTECTED_BEHIND_HINT = "pinned/ignored files where upstream also changed since the last upgrade; the fork side wins on conflict, so review what upstream changed and adopt what you need.";
1166
1183
  function protectionIcon(file) {
1167
1184
  return file.isIgnored ? statusConfig.ignored.icon : statusConfig.pinned.icon;
1168
1185
  }
@@ -1178,13 +1195,13 @@ function printSyncComplete(result, options = {}) {
1178
1195
  const counts = `${plural(updated, "file")} updated, ${merged} auto-merged, ${plural(conflicts, "conflict")}`;
1179
1196
  console.info();
1180
1197
  if (options.stagedBranch) {
1181
- console.info(`${checkMark} sync merge staged on '${options.stagedBranch}'`);
1198
+ console.info(`${checkMark} upgrade merge staged on '${options.stagedBranch}'`);
1182
1199
  console.info(colors_default.dim(` ${counts}. committing next...`));
1183
1200
  } else if (conflicts > 0) {
1184
- console.info(`${warningMark} sync merge staged with conflicts`);
1201
+ console.info(`${warningMark} upgrade merge staged with conflicts`);
1185
1202
  console.info(colors_default.dim(` ${counts}`));
1186
1203
  } else {
1187
- console.info(`${checkMark} sync complete`);
1204
+ console.info(`${checkMark} upgrade merge complete`);
1188
1205
  console.info(colors_default.dim(` ${counts}`));
1189
1206
  }
1190
1207
  printProtectedConflicts(result);
@@ -1224,31 +1241,33 @@ function printIgnoredUpstreamChanges(result) {
1224
1241
  if (group.deleted > 0) counts.push(`${group.deleted} deleted`);
1225
1242
  console.info(` ${statusConfig.ignored.icon} ${group.entry} ${colors_default.dim(`\xB7 ${counts.join(", ")}`)}`);
1226
1243
  }
1227
- console.info(colors_default.dim(" the fork left these untouched and ignored paths never sync: review and adopt what you need."));
1244
+ console.info(
1245
+ colors_default.dim(" the fork left these untouched and ignored paths never merge: review and adopt what you need.")
1246
+ );
1228
1247
  }
1229
1248
  function printUpstreamOverrideChanges(result) {
1230
1249
  const report = result.upstreamOverrides;
1231
1250
  if (!report) return;
1232
1251
  console.info();
1233
1252
  if (report.kind === "unreadable") {
1234
- const side = report.side === "base" ? "the last sync point" : "the incoming ref";
1253
+ const side = report.side === "base" ? "the last upgrade" : "the incoming ref";
1235
1254
  console.info(
1236
- colors_default.dim(`upstream sync config not compared: upstream ${CONFIG_FILE} is missing or unreadable at ${side}`)
1255
+ colors_default.dim(`upstream CLI config not compared: upstream ${CONFIG_FILE} is missing or unreadable at ${side}`)
1237
1256
  );
1238
1257
  return;
1239
1258
  }
1240
1259
  const lines = [];
1241
- for (const list of ["pinned", "ignored", "packageJsonSync"]) {
1260
+ for (const list of ["pinned", "ignored", "packageJsonKeys"]) {
1242
1261
  for (const entry of report[list].added) lines.push(` ${colors_default.green("+")} ${list}: ${entry}`);
1243
1262
  for (const entry of report[list].removed) {
1244
1263
  lines.push(` ${colors_default.red("\u2212")} ${list}: ${entry}${colors_default.dim(" \xB7 dropped upstream, still in your config")}`);
1245
1264
  }
1246
1265
  }
1247
1266
  console.info(
1248
- `${warningMark} ${colors_default.yellow(`upstream changed its sync config \xB7 ${plural(lines.length, "entry", "entries")} to review`)}`
1267
+ `${warningMark} ${colors_default.yellow(`upstream changed its CLI config \xB7 ${plural(lines.length, "entry", "entries")} to review`)}`
1249
1268
  );
1250
1269
  for (const line of lines) console.info(line);
1251
- console.info(colors_default.dim(` ${CONFIG_FILE} never syncs: add or drop these by hand where they fit your app.`));
1270
+ console.info(colors_default.dim(` ${CONFIG_FILE} never merges: add or drop these by hand where they fit your app.`));
1252
1271
  }
1253
1272
  function findMaskingPins(files) {
1254
1273
  return files.filter(
@@ -1327,7 +1346,8 @@ function parseAlignment(id, source, fileNames) {
1327
1346
  id,
1328
1347
  title: title || id,
1329
1348
  summary,
1330
- syncBreaking: meta.get("syncBreaking") === "true",
1349
+ // `syncBreaking` is the field's name in alignments up to cella 0.27
1350
+ breaking: (meta.get("breaking") ?? meta.get("syncBreaking")) === "true",
1331
1351
  clientCacheBump: meta.get("clientCacheBump") === "true",
1332
1352
  caughtBy,
1333
1353
  generate: meta.get("generate") === "true",
@@ -1532,7 +1552,7 @@ var forkOption = ["--fork <name>", "pre-select a fork by name (skips the fork se
1532
1552
  var serviceDefinitions = [
1533
1553
  {
1534
1554
  name: "analyze",
1535
- description: "dry run to see what would change on sync",
1555
+ description: "dry run to see what would change on upgrade",
1536
1556
  options: [
1537
1557
  ["--list", "non-interactive output for tooling (one file per line)"],
1538
1558
  jsonOption,
@@ -1545,12 +1565,13 @@ var serviceDefinitions = [
1545
1565
  includeInMenu: (context) => !context.isUpstreamRepo
1546
1566
  },
1547
1567
  {
1548
- name: "sync",
1549
- description: "merge upstream changes onto a fresh branch, sync package.json and open a squash-merge PR",
1568
+ name: "upgrade",
1569
+ description: "merge upstream changes onto a fresh branch, merge package.json and open a squash-merge PR",
1570
+ aliases: ["sync"],
1550
1571
  options: [
1551
1572
  trackOption,
1552
1573
  refOption,
1553
- ["--keep-config", "merge with your sync config as it stands when upstream changed its own"],
1574
+ ["--keep-config", "merge with your CLI config as it stands when upstream changed its own"],
1554
1575
  unpinnedOption
1555
1576
  ],
1556
1577
  includeInMenu: (context) => !context.isUpstreamRepo
@@ -1579,10 +1600,10 @@ var serviceDefinitions = [
1579
1600
  },
1580
1601
  {
1581
1602
  name: "forks",
1582
- description: "run normal sync inside local fork repositories",
1603
+ description: "run the upgrade inside local fork repositories",
1583
1604
  options: [
1584
1605
  forkOption,
1585
- ["--keep-config", "merge with the fork's sync config as it stands when upstream changed its own"]
1606
+ ["--keep-config", "merge with the fork's CLI config as it stands when upstream changed its own"]
1586
1607
  ],
1587
1608
  includeInMenu: (context) => context.hasForks
1588
1609
  },
@@ -1621,17 +1642,21 @@ function buildServiceChoices(context) {
1621
1642
  ];
1622
1643
  }
1623
1644
  function addServiceCommand(program, definition, setSelection) {
1624
- const command = program.command(definition.name).description(definition.description);
1625
- for (const option of definition.options ?? []) command.option(...option);
1626
- if (definition.operands) command.argument(...definition.operands);
1627
- command.action((...args) => {
1628
- const operands = definition.operands ? args[0] : [];
1629
- const opts = definition.operands ? args[1] : args[0];
1630
- setSelection({
1631
- service: definition.name,
1632
- options: readOptions(opts, operands)
1645
+ for (const name of [definition.name, ...definition.aliases ?? []]) {
1646
+ const renamedFrom = name === definition.name ? void 0 : name;
1647
+ const command = program.command(name, { hidden: !!renamedFrom }).description(definition.description);
1648
+ for (const option of definition.options ?? []) command.option(...option);
1649
+ if (definition.operands) command.argument(...definition.operands);
1650
+ command.action((...args) => {
1651
+ const operands = definition.operands ? args[0] : [];
1652
+ const opts = definition.operands ? args[1] : args[0];
1653
+ setSelection({
1654
+ service: definition.name,
1655
+ renamedFrom,
1656
+ options: readOptions(opts, operands)
1657
+ });
1633
1658
  });
1634
- });
1659
+ }
1635
1660
  }
1636
1661
  function buildProgram(setSelection) {
1637
1662
  const program = new Command("cella").version(VERSION, "-v, --version", "output the current version").usage("[service] [options]").helpOption("-h, --help", "display help for a command").showHelpAfterError().addHelpText(
@@ -1641,8 +1666,8 @@ function buildProgram(setSelection) {
1641
1666
  "Examples:",
1642
1667
  " $ cella analyze",
1643
1668
  " $ cella analyze --json --scope risk",
1644
- " $ cella sync --track branch",
1645
- " $ cella sync --ref 4f7d87c",
1669
+ " $ cella upgrade --track branch",
1670
+ " $ cella upgrade --ref 4f7d87c",
1646
1671
  " $ cella align --run 20261001T2116-tailwind-class-conventions -- rewrite frontend/src",
1647
1672
  " $ cella align --mark 20261002T0614-config-switch",
1648
1673
  " $ cella audit --list",
@@ -1689,7 +1714,13 @@ async function parseCli(userConfig, forkPath) {
1689
1714
  if (selection.options.json || selection.options.md || machineList) setJsonMode(true);
1690
1715
  printHeader();
1691
1716
  const { branchRef } = resolveUpstream(userConfig.settings);
1692
- const warnings = await validateOverrides(userConfig, forkPath, branchRef);
1717
+ const warnings = [
1718
+ ...renamedSettingWarnings(userConfig),
1719
+ ...await validateOverrides(userConfig, forkPath, branchRef)
1720
+ ];
1721
+ if (selection.renamedFrom) {
1722
+ warnings.unshift(`\`cella ${selection.renamedFrom}\` is renamed to \`cella ${selection.service}\``);
1723
+ }
1693
1724
  for (const warning of warnings) console.info(`${warningMark} ${warning}`);
1694
1725
  if (warnings.length > 0) console.info();
1695
1726
  if (!selection.service) {
@@ -1778,7 +1809,7 @@ function cliVersionMismatch(running, range) {
1778
1809
  const current = parseComparableVersion(running);
1779
1810
  if (!required || !current || compareVersions(current, required) >= 0) return null;
1780
1811
  return [
1781
- `upstream needs ${CLI_PACKAGE} ${range}, this is ${running}: an older CLI misses fixes to the sync itself.`,
1812
+ `upstream needs ${CLI_PACKAGE} ${range}, this is ${running}: an older CLI misses fixes to the upgrade itself.`,
1782
1813
  ` update it, commit, then rerun: pnpm add -D -w '${CLI_PACKAGE}@${range}'`
1783
1814
  ].join("\n");
1784
1815
  }
@@ -1832,12 +1863,13 @@ function readStringEntries(node) {
1832
1863
  }
1833
1864
  return entries;
1834
1865
  }
1835
- function readPackageJsonSync(config, sourceFile) {
1866
+ function readPackageJsonKeys(config, sourceFile) {
1836
1867
  const settings = readProperty(config, "settings", sourceFile);
1837
- if (settings === void 0) return [...DEFAULT_PACKAGE_JSON_SYNC];
1868
+ if (settings === void 0) return [...DEFAULT_PACKAGE_JSON_KEYS];
1838
1869
  if (!settings || !Node.isObjectLiteralExpression(settings)) return null;
1839
- const keys = readProperty(settings, "packageJsonSync", sourceFile);
1840
- if (keys === void 0) return [...DEFAULT_PACKAGE_JSON_SYNC];
1870
+ const current = readProperty(settings, "packageJsonKeys", sourceFile);
1871
+ const keys = current === void 0 ? readProperty(settings, "packageJsonSync", sourceFile) : current;
1872
+ if (keys === void 0) return [...DEFAULT_PACKAGE_JSON_KEYS];
1841
1873
  return keys ? readStringEntries(keys) : null;
1842
1874
  }
1843
1875
  function parseOverrideLists(source) {
@@ -1849,7 +1881,7 @@ function parseOverrideLists(source) {
1849
1881
  const lists = {
1850
1882
  pinned: [],
1851
1883
  ignored: [],
1852
- packageJsonSync: readPackageJsonSync(config, sourceFile)
1884
+ packageJsonKeys: readPackageJsonKeys(config, sourceFile)
1853
1885
  };
1854
1886
  const overrides = readProperty(config, "overrides", sourceFile);
1855
1887
  if (overrides === void 0) return lists;
@@ -1877,14 +1909,14 @@ function diffOverrideLists(base, incoming, fork) {
1877
1909
  };
1878
1910
  };
1879
1911
  const diffKeys = () => {
1880
- const [baseKeys, incomingKeys, forkKeys] = [base.packageJsonSync, incoming.packageJsonSync, fork.packageJsonSync];
1912
+ const [baseKeys, incomingKeys, forkKeys] = [base.packageJsonKeys, incoming.packageJsonKeys, fork.packageJsonKeys];
1881
1913
  if (!baseKeys || !incomingKeys || !forkKeys) return { added: [], removed: [] };
1882
1914
  return {
1883
1915
  added: [...new Set(incomingKeys)].filter((key) => !baseKeys.includes(key) && !forkKeys.includes(key)),
1884
1916
  removed: [...new Set(baseKeys)].filter((key) => !incomingKeys.includes(key) && forkKeys.includes(key))
1885
1917
  };
1886
1918
  };
1887
- return { pinned: diff("pinned"), ignored: diff("ignored"), packageJsonSync: diffKeys() };
1919
+ return { pinned: diff("pinned"), ignored: diff("ignored"), packageJsonKeys: diffKeys() };
1888
1920
  }
1889
1921
  async function compareUpstreamOverrides(repoPath, mergeBaseRef, incomingRef, forkConfig) {
1890
1922
  const [baseSource, incomingSource] = await Promise.all(
@@ -1898,7 +1930,7 @@ async function compareUpstreamOverrides(repoPath, mergeBaseRef, incomingRef, for
1898
1930
  const fork = {
1899
1931
  pinned: forkConfig.overrides?.pinned ?? [],
1900
1932
  ignored: forkConfig.overrides?.ignored ?? [],
1901
- packageJsonSync: forkConfig.settings.packageJsonSync ?? DEFAULT_PACKAGE_JSON_SYNC
1933
+ packageJsonKeys: forkConfig.settings.packageJsonKeys ?? DEFAULT_PACKAGE_JSON_KEYS
1902
1934
  };
1903
1935
  const changes = diffOverrideLists(base, incoming, fork);
1904
1936
  const count3 = Object.values(changes).reduce((n, list) => n + list.added.length + list.removed.length, 0);
@@ -2094,7 +2126,7 @@ var UpstreamConfigChangedError = class extends Error {
2094
2126
  constructor(report) {
2095
2127
  super(
2096
2128
  [
2097
- "upstream changed its sync config and yours does not follow it: stopped before the merge, nothing changed.",
2129
+ "upstream changed its CLI config and yours does not follow it: stopped before the merge, nothing changed.",
2098
2130
  ` add or drop the entries that fit your app in ${CONFIG_FILE}, commit, then rerun.`,
2099
2131
  " to merge with your config as it stands, rerun with --keep-config."
2100
2132
  ].join("\n")
@@ -2254,7 +2286,7 @@ async function resolvePinnedRef(forkPath, config, remoteName, branchRef, ref) {
2254
2286
  }
2255
2287
  if (!await isPublishedUpstream(forkPath, remoteName, branchRef, resolved.sha)) {
2256
2288
  throw new Error(
2257
- `--ref '${ref}' (${resolved.sha.slice(0, 7)}) is not on ${branchRef} or in an upstream release. Sync only to commits upstream has published there.`
2289
+ `--ref '${ref}' (${resolved.sha.slice(0, 7)}) is not on ${branchRef} or in an upstream release. Upgrade only to commits upstream has published there.`
2258
2290
  );
2259
2291
  }
2260
2292
  return resolved.release ? { ref: resolved.release.ref, releaseTag: resolved.release.tag } : { ref: resolved.sha };
@@ -2310,9 +2342,9 @@ async function prepareUpstream(config, onProgress, onStep) {
2310
2342
  getShortSha(forkPath, upstreamCommit.hash),
2311
2343
  getShortSha(forkPath, mergeBase)
2312
2344
  ]);
2313
- const hint2 = config.ref ? "Pick a newer --ref." : releaseTag ? `Nothing to sync until a release past ${syncShort}; to follow the tip instead, run with --track branch.` : `Nothing to sync until '${branchRef}' moves past ${syncShort}.`;
2345
+ const hint2 = config.ref ? "Pick a newer --ref." : releaseTag ? `Nothing to upgrade until a release past ${syncShort}; to follow the tip instead, run with --track branch.` : `Nothing to upgrade until '${branchRef}' moves past ${syncShort}.`;
2314
2346
  throw new BehindSyncPointError(
2315
- `upstream ${upstreamLabel} (${upstreamShort2}) is behind the last sync point ${syncShort}: the fork already has it, and syncing it would revert the upstream changes after it.
2347
+ `upstream ${upstreamLabel} (${upstreamShort2}) is behind the last upgrade at ${syncShort}: the fork already has it, and merging it would revert the upstream changes after it.
2316
2348
  ${hint2}`
2317
2349
  );
2318
2350
  }
@@ -2422,7 +2454,7 @@ async function runSyncMerge(config, ctx, onProgress, onStep) {
2422
2454
  commit: upstreamCommit.hash,
2423
2455
  release: releaseTag ?? null,
2424
2456
  url: upstreamGitHubUrl ? releaseTag ? `${upstreamGitHubUrl}/releases/tag/${releaseTag}` : `${upstreamGitHubUrl}/commit/${upstreamCommit.hash}` : void 0,
2425
- syncedAt: (/* @__PURE__ */ new Date()).toISOString()
2457
+ upgradedAt: (/* @__PURE__ */ new Date()).toISOString()
2426
2458
  }
2427
2459
  };
2428
2460
  const recordSyncPoint = async () => {
@@ -2441,10 +2473,10 @@ async function runSyncMerge(config, ctx, onProgress, onStep) {
2441
2473
  } else if (totalResolved > 0) {
2442
2474
  const label = synced > 0 ? `${synced} files from upstream` : "upstream changes";
2443
2475
  await recordSyncPoint();
2444
- onStep?.("synced", `${label} (staged, commit to finish)`);
2476
+ onStep?.("upgraded", `${label} (staged, commit to finish)`);
2445
2477
  } else {
2446
2478
  await mergeAbort(forkPath);
2447
- onStep?.("up to date", "no upstream changes to sync");
2479
+ onStep?.("up to date", "no upstream changes to merge");
2448
2480
  }
2449
2481
  return {
2450
2482
  success: remainingConflicts.length === 0,
@@ -2529,7 +2561,7 @@ var STEP_ROWS_MAX = 5;
2529
2561
  function alignmentTags(alignment) {
2530
2562
  return [
2531
2563
  alignment.codemod ? "codemod" : "manual",
2532
- alignment.syncBreaking ? "sync-breaking" : "not sync-breaking",
2564
+ alignment.breaking ? "breaking" : "not breaking",
2533
2565
  alignment.caughtBy ? `caught by ${alignment.caughtBy}` : null
2534
2566
  ].filter(Boolean).join(" \xB7 ");
2535
2567
  }
@@ -2538,7 +2570,7 @@ async function alignmentsStep(config, view) {
2538
2570
  const open = view.open.filter((id) => !arriving.includes(id));
2539
2571
  const arrived = (view.arrived ?? []).filter((id) => open.includes(id));
2540
2572
  if (arriving.length === 0 && open.length === 0) return void 0;
2541
- const line = arriving.length > 0 ? `${plural(arriving.length, "alignment")} ${arriving.length === 1 ? "arrives" : "arrive"} with this sync${open.length > 0 ? colors_default.dim(` \xB7 ${open.length} open`) : ""}` : `${plural(open.length, "alignment")} open${arrived.length > 0 ? colors_default.dim(` \xB7 ${arrived.length} arrived with this sync`) : ""}`;
2573
+ const line = arriving.length > 0 ? `${plural(arriving.length, "alignment")} ${arriving.length === 1 ? "arrives" : "arrive"} with this upgrade${open.length > 0 ? colors_default.dim(` \xB7 ${open.length} open`) : ""}` : `${plural(open.length, "alignment")} open${arrived.length > 0 ? colors_default.dim(` \xB7 ${arrived.length} arrived with this upgrade`) : ""}`;
2542
2574
  const githubUrl = getGitHubBaseUrl(config.settings.upstreamUrl) ?? void 0;
2543
2575
  const ids = [...arriving, ...open];
2544
2576
  const details = [];
@@ -2549,7 +2581,7 @@ async function alignmentsStep(config, view) {
2549
2581
  if (!process7.stdout.isTTY) details.push(colors_default.dim(` id ${id}`));
2550
2582
  }
2551
2583
  if (ids.length > STEP_ROWS_MAX) details.push(colors_default.dim(`+ ${ids.length - STEP_ROWS_MAX} more`));
2552
- details.push(`${arriving.length > 0 ? colors_default.dim("after the sync: ") : ""}pnpm cella align`);
2584
+ details.push(`${arriving.length > 0 ? colors_default.dim("after the upgrade: ") : ""}pnpm cella align`);
2553
2585
  return { label: "align", line, details };
2554
2586
  }
2555
2587
  async function readForkView(config, ref) {
@@ -2592,7 +2624,7 @@ function grepSummary(alignment) {
2592
2624
  function printAlignment(index, alignment) {
2593
2625
  const tags = [
2594
2626
  alignment.codemod ? "codemod" : "manual",
2595
- alignment.syncBreaking ? "sync-breaking" : null,
2627
+ alignment.breaking ? "breaking" : null,
2596
2628
  alignment.clientCacheBump ? "cache-bump" : null,
2597
2629
  alignment.caughtBy ? `caught by: ${alignment.caughtBy}` : null,
2598
2630
  alignment.generate ? "generate" : null
@@ -2634,7 +2666,7 @@ async function showAlignment(config, ref, pending, id) {
2634
2666
  alignment,
2635
2667
  pending.includes(id)
2636
2668
  );
2637
- if (readRef !== ref) console.info(colors_default.dim(`not at the sync point ${ref.slice(0, 7)}: read at ${upstreamBranch}`));
2669
+ if (readRef !== ref) console.info(colors_default.dim(`not at the last upgrade ${ref.slice(0, 7)}: read at ${upstreamBranch}`));
2638
2670
  if (described.url) console.info(colors_default.dim(described.url));
2639
2671
  console.info(source);
2640
2672
  console.info();
@@ -2731,7 +2763,7 @@ async function runAlign(config) {
2731
2763
  const { forkPath } = config;
2732
2764
  const ref = await resolveAlignmentsRef(config);
2733
2765
  if (!ref) {
2734
- console.info(colors_default.dim("no sync point recorded yet: alignments start with the first `pnpm cella sync`."));
2766
+ console.info(colors_default.dim("no upgrade recorded yet: alignments start with the first `pnpm cella upgrade`."));
2735
2767
  return;
2736
2768
  }
2737
2769
  const pending = await readPending(forkPath);
@@ -2746,7 +2778,7 @@ async function runAlign(config) {
2746
2778
  id: ids[i],
2747
2779
  title: `${ids[i]} (no longer upstream)`,
2748
2780
  summary: "",
2749
- syncBreaking: false,
2781
+ breaking: false,
2750
2782
  clientCacheBump: false,
2751
2783
  caughtBy: null,
2752
2784
  generate: false,
@@ -3167,30 +3199,30 @@ function reviewSections(result, command) {
3167
3199
  const [base, upstream] = result.upstreamDiffRange?.split("..") ?? [];
3168
3200
  if (!base || !upstream) return [];
3169
3201
  const sinceSync = `${base}..${upstream}`;
3170
- const sections = command === "sync" ? [
3202
+ const sections = command === "upgrade" ? [
3171
3203
  {
3172
3204
  title: "protected files kept the fork version",
3173
- hint: "What upstream changed in these files since the last sync. The fork kept its own version, so none of it arrived: adopt what you need.",
3205
+ hint: "What upstream changed in these files since the last upgrade. The fork kept its own version, so none of it arrived: adopt what you need.",
3174
3206
  range: sinceSync,
3175
3207
  paths: result.protectedConflicts ?? []
3176
3208
  },
3177
3209
  {
3178
3210
  title: "ignored paths changed upstream",
3179
- hint: "What upstream changed under ignored paths since the last sync. The fork left these files untouched, and ignored paths never sync.",
3211
+ hint: "What upstream changed under ignored paths since the last upgrade. The fork left these files untouched, and ignored paths never merge.",
3180
3212
  range: sinceSync,
3181
3213
  paths: (result.ignoredUpstreamChanges ?? []).flatMap((group) => group.paths)
3182
3214
  }
3183
3215
  ] : [
3184
3216
  {
3185
3217
  title: "protected but behind upstream",
3186
- hint: "What upstream changed in these files since the last sync. They are pinned or ignored, so the sync keeps the fork version and none of it arrives: adopt what you need.",
3218
+ hint: "What upstream changed in these files since the last upgrade. They are pinned or ignored, so the upgrade keeps the fork version and none of it arrives: adopt what you need.",
3187
3219
  range: sinceSync,
3188
3220
  paths: findProtectedBehindUpstream(result).map((file) => file.path)
3189
3221
  }
3190
3222
  ];
3191
3223
  sections.push({
3192
3224
  title: "pinned files that match the previous upstream",
3193
- hint: "What upstream changed in these files since the last sync. The fork copy still equals the previous upstream, so the pin only drops these changes: unpin to take them.",
3225
+ hint: "What upstream changed in these files since the last upgrade. The fork copy still equals the previous upstream, so the pin only drops these changes: unpin to take them.",
3194
3226
  range: sinceSync,
3195
3227
  paths: findMaskingPins(result.files).map((file) => file.path)
3196
3228
  });
@@ -3198,13 +3230,13 @@ function reviewSections(result, command) {
3198
3230
  sections.push(
3199
3231
  {
3200
3232
  title: "protected in fork, upstream lines absent",
3201
- hint: "The fork's version against upstream's, both as they are now: added lines are upstream content the fork does not have, dropped by an earlier sync or removed on purpose.",
3233
+ hint: "The fork's version against upstream's, both as they are now: added lines are upstream content the fork does not have, dropped by an earlier upgrade or removed on purpose.",
3202
3234
  range: `HEAD..${upstream}`,
3203
3235
  paths: filesWithStatus(result.files, "ahead").filter((file) => (file.upstreamLinesAbsent ?? 0) > 0).map((file) => file.path)
3204
3236
  },
3205
3237
  {
3206
3238
  title: "drifted from upstream",
3207
- hint: "What the fork changed in these files since the last sync. They are not pinned or ignored, so upstream changes still merge into them.",
3239
+ hint: "What the fork changed in these files since the last upgrade. They are not pinned or ignored, so upstream changes still merge into them.",
3208
3240
  range: `${base}..HEAD`,
3209
3241
  paths: filesWithStatus(result.files, "drifted").map((file) => file.path)
3210
3242
  }
@@ -3253,7 +3285,7 @@ async function writeReviewPage(forkPath, sections, meta, limits = PAGE_LIMITS) {
3253
3285
  const shown = pageSections.filter((section) => section.files.length > 0 || section.omitted.length > 0);
3254
3286
  const page = await writeDiffPage(
3255
3287
  shown,
3256
- { title: `${meta.command} review`, note: `${basename3(forkPath)} \xB7 last sync ${base} \u2192 upstream ${upstream}` },
3288
+ { title: `${meta.command} review`, note: `${basename3(forkPath)} \xB7 last upgrade ${base} \u2192 upstream ${upstream}` },
3257
3289
  forkPath,
3258
3290
  `${meta.command}-review`
3259
3291
  );
@@ -3273,21 +3305,21 @@ async function reportReviewPage(forkPath, result, command) {
3273
3305
  spinnerSuccess();
3274
3306
  }
3275
3307
  if (!page) {
3276
- if (command === "sync") removeSyncReviewPage(forkPath);
3308
+ if (command === "upgrade") removeSyncReviewPage(forkPath);
3277
3309
  return void 0;
3278
3310
  }
3279
- const opened = command === "sync" && process9.stdout.isTTY === true && openInBrowser(page.path);
3311
+ const opened = command === "upgrade" && process9.stdout.isTTY === true && openInBrowser(page.path);
3280
3312
  return { ...page, command, opened };
3281
3313
  }
3282
3314
  function removeSyncReviewPage(forkPath) {
3283
3315
  try {
3284
- rmSync(diffPagePath(forkPath, "sync-review"), { force: true });
3316
+ rmSync(diffPagePath(forkPath, "upgrade-review"), { force: true });
3285
3317
  } catch {
3286
3318
  }
3287
3319
  }
3288
3320
  function existingSyncReviewPage(forkPath) {
3289
3321
  try {
3290
- const path = diffPagePath(forkPath, "sync-review");
3322
+ const path = diffPagePath(forkPath, "upgrade-review");
3291
3323
  return existsSync7(path) ? path : void 0;
3292
3324
  } catch {
3293
3325
  return void 0;
@@ -3296,9 +3328,9 @@ function existingSyncReviewPage(forkPath) {
3296
3328
  function reviewStep(page) {
3297
3329
  const path = typeof page === "string" ? page : page.path;
3298
3330
  const url = pathToFileURL(path).href;
3299
- let detail = colors_default.dim("upstream changes the sync did not bring in, from the merge run");
3331
+ let detail = colors_default.dim("upstream changes the upgrade did not bring in, from the merge run");
3300
3332
  if (typeof page !== "string") {
3301
- const what = page.command === "sync" ? `${plural(page.diffs, "diff")} of upstream changes that did not arrive` : `${plural(page.diffs, "diff")} in ${plural(page.sections, "section")}`;
3333
+ const what = page.command === "upgrade" ? `${plural(page.diffs, "diff")} of upstream changes that did not arrive` : `${plural(page.diffs, "diff")} in ${plural(page.sections, "section")}`;
3302
3334
  const notes = [
3303
3335
  page.listed > 0 ? `${page.listed} listed without a diff` : "",
3304
3336
  page.opened ? "opened in the browser" : ""
@@ -3340,8 +3372,8 @@ async function runAnalyze(config) {
3340
3372
  upstreamChangedLines: f.upstreamChangedLines ?? null,
3341
3373
  upstreamLinesAbsent: f.upstreamLinesAbsent ?? null,
3342
3374
  upstreamOnly: f.upstreamOnly ?? false,
3343
- // Only on the sync config: upstream override entries and packageJsonSync keys the fork config does not follow
3344
- upstreamOverrides: overrides && f.path === CONFIG_FILE ? { pinned: overrides.pinned, ignored: overrides.ignored, packageJsonSync: overrides.packageJsonSync } : null
3375
+ // Only on the CLI config: upstream override entries and packageJsonKeys the fork config does not follow
3376
+ upstreamOverrides: overrides && f.path === CONFIG_FILE ? { pinned: overrides.pinned, ignored: overrides.ignored, packageJsonKeys: overrides.packageJsonKeys } : null
3345
3377
  }));
3346
3378
  writeStdout(JSON.stringify(out, null, 2));
3347
3379
  return result;
@@ -3389,11 +3421,11 @@ function syncStep(result) {
3389
3421
  renamed > 0 ? `${renamed} rename` : ""
3390
3422
  ].filter(Boolean);
3391
3423
  return {
3392
- label: "sync",
3393
- line: "pnpm cella sync",
3424
+ label: "upgrade",
3425
+ line: "pnpm cella upgrade",
3394
3426
  details: [
3395
3427
  colors_default.dim(
3396
- `commits on a fresh branch, a rerun opens the PR \xB7 ${changes.length > 0 ? changes.join(", ") : "no synced file changes"}`
3428
+ `commits on a fresh branch, a rerun opens the PR \xB7 ${changes.length > 0 ? changes.join(", ") : "no file changes"}`
3397
3429
  )
3398
3430
  ]
3399
3431
  };
@@ -4434,8 +4466,9 @@ async function runAudit(config) {
4434
4466
  }
4435
4467
  const runtimes = planRuntimeUpdates(pins, feeds, { releaseAgeMinutes, now });
4436
4468
  const localTools = planLocalTools(machine, { releaseAgeMinutes, now });
4469
+ const advisories = auditResult ? advisoriesFromAudit(auditResult) : null;
4437
4470
  const rows = [
4438
- ...packageRows(outdated, auditResult ? advisoriesFromAudit(auditResult) : []),
4471
+ ...packageRows(outdated, advisories ?? []),
4439
4472
  ...runtimes.updates.map(runtimeRow)
4440
4473
  ];
4441
4474
  if (rows.length === 0) {
@@ -4455,6 +4488,7 @@ async function runAudit(config) {
4455
4488
  await runSecurityPass(forkPath, { apply: false, releaseAgeMinutes });
4456
4489
  return;
4457
4490
  }
4491
+ printReported(advisories);
4458
4492
  const selected = await promptForUpdates(rows);
4459
4493
  if (!selected) return;
4460
4494
  const { edits, bumped } = await planEdits(forkPath, rows, selected, pins.nodeImageSuffixes);
@@ -4463,8 +4497,8 @@ async function runAudit(config) {
4463
4497
  spinner.stop();
4464
4498
  }
4465
4499
  }
4500
+ var worstSeverity = (advisories, name) => SEVERITIES.find((severity) => advisories.some((a) => a.module === name && a.severity === severity)) ?? null;
4466
4501
  function packageRows(outdated, advisories) {
4467
- const severityOf = (name) => SEVERITIES.find((severity) => advisories.some((a) => a.module === name && a.severity === severity)) ?? null;
4468
4502
  const readDependentPkg = createDependentPkgReader();
4469
4503
  const rows = Object.entries(outdated).map(([key, pkg]) => {
4470
4504
  const name = outdatedPackageName(key);
@@ -4488,7 +4522,7 @@ function packageRows(outdated, advisories) {
4488
4522
  pinnedIn,
4489
4523
  repoUrl,
4490
4524
  releasesUrl: getReleasesUrl(repoUrl),
4491
- severity: severityOf(name)
4525
+ severity: worstSeverity(advisories, name)
4492
4526
  };
4493
4527
  });
4494
4528
  return rows.sort((a, b) => inText(a).localeCompare(inText(b)) || a.name.localeCompare(b.name));
@@ -4594,6 +4628,40 @@ function printLocalTools(checks) {
4594
4628
  }
4595
4629
  console.info();
4596
4630
  }
4631
+ function printReported(advisories) {
4632
+ if (!advisories) {
4633
+ console.info(`${warningMark} pnpm audit gave no answer: a row in the table can lack its dot`);
4634
+ console.info();
4635
+ return;
4636
+ }
4637
+ if (advisories.length === 0) {
4638
+ console.info(`${checkMark} pnpm audit reports nothing ${colors_default.dim("\xB7 with the current overrides and ignores")}`);
4639
+ console.info();
4640
+ return;
4641
+ }
4642
+ const modules = [...new Set(advisories.map((a) => a.module))].map((name) => {
4643
+ const own = advisories.filter((a) => a.module === name);
4644
+ return {
4645
+ name,
4646
+ severity: worstSeverity(own, name) ?? own[0].severity,
4647
+ installed: [...new Set(own.flatMap((a) => a.installed))].join(", "),
4648
+ via: formatDependents([...new Set(own.flatMap((a) => a.via))]),
4649
+ direct: own.some((a) => a.direct)
4650
+ };
4651
+ });
4652
+ modules.sort((a, b) => SEVERITIES.indexOf(a.severity) - SEVERITIES.indexOf(b.severity));
4653
+ const nameWidth = Math.min(30, Math.max(...modules.map((m) => m.name.length)));
4654
+ const versionWidth = Math.max(...modules.map((m) => m.installed.length));
4655
+ console.info(`${colors_default.bold("pnpm audit")} ${colors_default.dim("\xB7 with the current overrides and ignores")}`);
4656
+ for (const m of modules) {
4657
+ const name = colors_default.white(middleTruncate(m.name, nameWidth).padEnd(nameWidth));
4658
+ const source = `${m.via}${m.direct ? " (direct)" : ""}`;
4659
+ console.info(
4660
+ `${getVulnIcon(m.severity)} ${name} ${m.severity.padEnd(8)} ${m.installed.padEnd(versionWidth)} ${colors_default.dim(source)}`
4661
+ );
4662
+ }
4663
+ console.info();
4664
+ }
4597
4665
  function buildUpdateChoices(rows) {
4598
4666
  const makeChoice = (row) => {
4599
4667
  const devTag = row.isDev ? colors_default.dim(" (dev)") : "";
@@ -5162,7 +5230,7 @@ import { resolve as resolve6 } from "path";
5162
5230
  import process10 from "process";
5163
5231
  import { Separator as Separator2, select as select5 } from "@inquirer/prompts";
5164
5232
 
5165
- // src/services/sync.ts
5233
+ // src/services/upgrade.ts
5166
5234
  import { spawnSync as spawnSync4 } from "child_process";
5167
5235
  import { select as select4 } from "@inquirer/prompts";
5168
5236
 
@@ -5176,7 +5244,7 @@ function runGh(cwd, args) {
5176
5244
  const output = `${result.stdout ?? ""}${result.stderr ?? ""}`.trim();
5177
5245
  return { ok: result.status === 0, output };
5178
5246
  }
5179
- function listOpenSyncPrs(cwd, prefix) {
5247
+ function listOpenSyncPrs(cwd, prefixes) {
5180
5248
  const { ok, output } = runGh(cwd, [
5181
5249
  "pr",
5182
5250
  "list",
@@ -5194,7 +5262,7 @@ function listOpenSyncPrs(cwd, prefix) {
5194
5262
  } catch {
5195
5263
  return [];
5196
5264
  }
5197
- return parsed.filter((pr) => pr.headRefName.startsWith(`${prefix}/`)).sort((a, b) => b.number - a.number);
5265
+ return parsed.filter((pr) => prefixes.some((prefix) => pr.headRefName.startsWith(`${prefix}/`))).sort((a, b) => b.number - a.number);
5198
5266
  }
5199
5267
  function createPr(cwd, repoSlug, pr) {
5200
5268
  const repo = repoSlug ?? "{owner}/{repo}";
@@ -5564,8 +5632,8 @@ async function syncPackageJson(config, baseRef, usage, relativePath, keysToSync)
5564
5632
  return { updated, changes, kept };
5565
5633
  }
5566
5634
  async function runPackages(config, options = {}) {
5567
- createSpinner("syncing package.json files...");
5568
- const keysToSync = config.settings.packageJsonSync || DEFAULT_PACKAGE_JSON_SYNC;
5635
+ createSpinner("merging package.json files...");
5636
+ const keysToSync = config.settings.packageJsonKeys || DEFAULT_PACKAGE_JSON_KEYS;
5569
5637
  const conflictedSet = new Set(options.conflictedFiles ?? []);
5570
5638
  const baseRef = await resolveMergeBase(config.forkPath, config.upstreamRef);
5571
5639
  const usage = baseRef ? await loadForkUsage(config.forkPath, config.upstreamRef, baseRef) : null;
@@ -5578,12 +5646,15 @@ async function runPackages(config, options = {}) {
5578
5646
  skipped.push(pkgRelPath);
5579
5647
  continue;
5580
5648
  }
5581
- spinnerText(`syncing ${location || "root"}/package.json...`);
5649
+ spinnerText(`merging ${location || "root"}/package.json...`);
5582
5650
  const { updated, changes, kept: kept2 } = await syncPackageJson(config, baseRef, usage, location, keysToSync);
5583
5651
  if (updated || kept2.length > 0) reports.push({ path: pkgRelPath, changes, kept: kept2 });
5584
5652
  }
5585
5653
  const changedCount = reports.filter(({ changes }) => changes.length > 0).length;
5586
- spinnerSuccess("package sync complete", `${plural(changedCount, "package.json was", "package.jsons were")} changed`);
5654
+ spinnerSuccess(
5655
+ "package.json merge complete",
5656
+ `${plural(changedCount, "package.json was", "package.jsons were")} changed`
5657
+ );
5587
5658
  for (const { path, changes } of reports) {
5588
5659
  if (changes.length === 0) continue;
5589
5660
  console.info(` ${path}`);
@@ -5593,7 +5664,7 @@ async function runPackages(config, options = {}) {
5593
5664
  const them = kept.length === 1 ? "it" : "them";
5594
5665
  printWarnList(`kept ${plural(kept.length, "entry", "entries")} upstream dropped, the fork still uses ${them}:`, kept);
5595
5666
  printWarnList(
5596
- `skipped ${skipped.length} conflicted package.json file(s): resolve the conflicts, commit the merge, then rerun \`pnpm cella sync\`:`,
5667
+ `skipped ${skipped.length} conflicted package.json file(s): resolve the conflicts, commit the merge, then rerun \`pnpm cella upgrade\`:`,
5597
5668
  skipped
5598
5669
  );
5599
5670
  }
@@ -5604,7 +5675,7 @@ function printWarnList(header, entries) {
5604
5675
  for (const entry of entries) console.info(` ${colors_default.dim("\u2192")} ${entry}`);
5605
5676
  }
5606
5677
 
5607
- // src/services/sync.ts
5678
+ // src/services/upgrade.ts
5608
5679
  async function resolveCycleStart(forkPath, base, currentBranch) {
5609
5680
  if (!await branchExists(forkPath, base)) {
5610
5681
  await fetchRemote(forkPath, "origin").catch(() => {
@@ -5620,7 +5691,7 @@ async function resolveCycleStart(forkPath, base, currentBranch) {
5620
5691
  if (ahead > 0 && behind > 0) {
5621
5692
  throw new Error(
5622
5693
  `'${base}' has diverged from '${upstream}' (${ahead} ahead, ${behind} behind).
5623
- Reconcile '${base}' with '${upstream}' first (e.g. rebase or reset it), then re-run sync.`
5694
+ Reconcile '${base}' with '${upstream}' first (e.g. rebase or reset it), then re-run the upgrade.`
5624
5695
  );
5625
5696
  }
5626
5697
  if (behind > 0) {
@@ -5649,7 +5720,7 @@ async function setupTemporarySyncBranch(config) {
5649
5720
  console.info(colors_default.dim(`updating '${base}'...`));
5650
5721
  const startPoint = await resolveCycleStart(forkPath, base, startBranch);
5651
5722
  const temporaryBranch = buildTemporarySyncBranch();
5652
- console.info(colors_default.dim(`creating temporary sync branch '${temporaryBranch}' from '${startPoint}'...`));
5723
+ console.info(colors_default.dim(`creating temporary upgrade branch '${temporaryBranch}' from '${startPoint}'...`));
5653
5724
  console.info();
5654
5725
  await createBranchFrom(forkPath, temporaryBranch, startPoint);
5655
5726
  return { temporaryBranch, base, startBranch, startCommit };
@@ -5673,7 +5744,7 @@ async function returnToBase(forkPath, base) {
5673
5744
  return `back on '${base}'`;
5674
5745
  }
5675
5746
  async function runSync(config, options) {
5676
- createSpinner("starting sync...");
5747
+ createSpinner("starting upgrade...");
5677
5748
  let result;
5678
5749
  try {
5679
5750
  result = await runEngineWithSpinner(config, true);
@@ -5688,7 +5759,7 @@ async function runSync(config, options) {
5688
5759
  if (result.success) {
5689
5760
  spinnerSuccess();
5690
5761
  } else {
5691
- spinnerFail("sync completed with conflicts");
5762
+ spinnerFail("upgrade merge completed with conflicts");
5692
5763
  }
5693
5764
  printEngineReports(result, "merge summary");
5694
5765
  if (config.unpinned) {
@@ -5698,7 +5769,7 @@ async function runSync(config, options) {
5698
5769
  const staged = result.files.some((file) => SYNC_APPLIED_STATUSES.includes(file.status));
5699
5770
  const stagedBranch = options?.stagedBranch && result.conflicts.length === 0 && staged ? options.stagedBranch : void 0;
5700
5771
  printSyncComplete(result, { stagedBranch });
5701
- const reviewPage = await reportReviewPage(config.forkPath, result, "sync");
5772
+ const reviewPage = await reportReviewPage(config.forkPath, result, "upgrade");
5702
5773
  return { ...result, reviewPage };
5703
5774
  }
5704
5775
  var CONFLICTS_LISTED = 10;
@@ -5725,9 +5796,9 @@ async function conflictSteps(config, conflicts, run) {
5725
5796
  },
5726
5797
  {
5727
5798
  label: "finish",
5728
- line: "pnpm cella sync",
5799
+ line: "pnpm cella upgrade",
5729
5800
  details: [
5730
- colors_default.dim("commits the sync and stops for drift triage"),
5801
+ colors_default.dim("commits the upgrade and stops for drift triage"),
5731
5802
  colors_default.dim("let the rerun commit: a manual `git commit` records a merge commit that bloats the PR")
5732
5803
  ]
5733
5804
  },
@@ -5736,13 +5807,13 @@ async function conflictSteps(config, conflicts, run) {
5736
5807
  ];
5737
5808
  return steps.filter((step) => !!step);
5738
5809
  }
5739
- var SYNC_PR_TITLE = "chore: sync upstream cella";
5810
+ var UPGRADE_PR_TITLE = "chore: upgrade cella";
5740
5811
  async function buildSyncCommitMessage(forkPath, upstreamRef) {
5741
5812
  const shortSha = await getShortSha(forkPath, upstreamRef).catch(() => "");
5742
- if (!shortSha) return SYNC_PR_TITLE;
5813
+ if (!shortSha) return UPGRADE_PR_TITLE;
5743
5814
  const manifest = await readSyncManifest(forkPath);
5744
5815
  const version = manifest?.upstream.release ?? await readPackageVersionAtRef(forkPath, upstreamRef).catch(() => null);
5745
- return version ? `${SYNC_PR_TITLE} v${version.replace(/^v/, "")} (${shortSha})` : `${SYNC_PR_TITLE} ${shortSha}`;
5816
+ return version ? `${UPGRADE_PR_TITLE} to v${version.replace(/^v/, "")} (${shortSha})` : `${UPGRADE_PR_TITLE} to ${shortSha}`;
5746
5817
  }
5747
5818
  function qualifyPrRefs(subject, repoSlug) {
5748
5819
  if (!repoSlug) return subject;
@@ -5755,10 +5826,14 @@ function buildSyncPrBody(input) {
5755
5826
  const commitRef = (sha) => githubUrl ? `[\`${short(sha)}\`](${githubUrl}/commit/${sha})` : `\`${short(sha)}\``;
5756
5827
  const upstreamName = githubUrl ? `[${repoSlug}](${githubUrl})` : "cella";
5757
5828
  const versionSuffix = version ? ` (v${version.replace(/^v/, "")})` : "";
5758
- const lines = [`Syncs upstream ${upstreamName} to ${commitRef(toSha)}${versionSuffix}.`];
5829
+ const lines = [`Upgrades ${upstreamName} to ${commitRef(toSha)}${versionSuffix}.`];
5759
5830
  if (totalCount > 0 && fromSha) {
5760
5831
  const compare = githubUrl ? ` ([compare](${githubUrl}/compare/${short(fromSha)}...${short(toSha)}))` : "";
5761
- lines.push("", `**${totalCount} upstream commit${totalCount === 1 ? "" : "s"} since last sync**${compare}:`, "");
5832
+ lines.push(
5833
+ "",
5834
+ `**${totalCount} upstream commit${totalCount === 1 ? "" : "s"} since the last upgrade**${compare}:`,
5835
+ ""
5836
+ );
5762
5837
  if (totalCount > commits.length) lines.push(`- \u2026${totalCount - commits.length} earlier commit(s) not shown`);
5763
5838
  for (const commit of commits) {
5764
5839
  lines.push(`- ${commitRef(commit.hash)} ${qualifyPrRefs(commit.message, repoSlug)}`);
@@ -5813,7 +5888,7 @@ async function readPrBodyAlignments(forkPath, toSha, repoSlug) {
5813
5888
  );
5814
5889
  return { total: ids.length, open };
5815
5890
  }
5816
- function printPrCreateStep(branch, base, title = SYNC_PR_TITLE) {
5891
+ function printPrCreateStep(branch, base, title = UPGRADE_PR_TITLE) {
5817
5892
  console.info(colors_default.dim(` gh pr create --base ${base} --head ${branch} --title "${title}" --fill`));
5818
5893
  }
5819
5894
  async function flattenSyncBranch(forkPath, branch, base) {
@@ -5837,7 +5912,7 @@ async function shipSyncBranch(config, branch) {
5837
5912
  let prUrl;
5838
5913
  let prOpened = false;
5839
5914
  const upstreamCommit = (await readSyncManifest(forkPath))?.upstream.commit;
5840
- const prTitle = upstreamCommit ? await buildSyncCommitMessage(forkPath, upstreamCommit) : SYNC_PR_TITLE;
5915
+ const prTitle = upstreamCommit ? await buildSyncCommitMessage(forkPath, upstreamCommit) : UPGRADE_PR_TITLE;
5841
5916
  console.info(colors_default.dim(`pushing '${branch}' to origin...`));
5842
5917
  try {
5843
5918
  await pushBranch(forkPath, "origin", branch, { forceWithLease: flattened });
@@ -5866,17 +5941,17 @@ async function shipSyncBranch(config, branch) {
5866
5941
  const position = await returnToBase(forkPath, base);
5867
5942
  console.info();
5868
5943
  if (prUrl) {
5869
- console.info(`${checkMark} sync pull request ${prOpened ? "opened" : "ready"}`);
5944
+ console.info(`${checkMark} upgrade pull request ${prOpened ? "opened" : "ready"}`);
5870
5945
  console.info(colors_default.dim(` ${prUrl} \xB7 branch pushed, ${position}`));
5871
5946
  } else {
5872
- console.info(`${checkMark} sync branch pushed`);
5947
+ console.info(`${checkMark} upgrade branch pushed`);
5873
5948
  console.info(colors_default.dim(` '${branch}' is on origin, ${position}`));
5874
5949
  }
5875
5950
  const steps = [
5876
5951
  prUrl ? {
5877
5952
  label: "merge",
5878
5953
  line: hyperlink(colors_default.cyan(prUrl), prUrl),
5879
- details: [colors_default.dim(`squash-merge it into '${base}'; the next sync offers to while it is open`)]
5954
+ details: [colors_default.dim(`squash-merge it into '${base}'; the next upgrade offers to while it is open`)]
5880
5955
  } : void 0,
5881
5956
  await syncAlignmentsStep(config)
5882
5957
  ];
@@ -5916,7 +5991,7 @@ async function runSyncCycle(config) {
5916
5991
  }
5917
5992
  throw error;
5918
5993
  }
5919
- if (config.settings.syncWithPackages !== false) {
5994
+ if (config.settings.mergePackageJson !== false) {
5920
5995
  await runPackages(config, { conflictedFiles: result.conflicts });
5921
5996
  }
5922
5997
  if (result.conflicts.length > 0) return { status: "conflicts", branch, result };
@@ -5941,7 +6016,11 @@ async function commitSyncMerge(config, branch, run) {
5941
6016
  printStep("checks", "`pnpm install` or `pnpm check` failed", warningMark);
5942
6017
  printNextSteps([
5943
6018
  { label: "fix", line: "what failed above", details: [colors_default.dim(`the merge stays staged on '${branch}'`)] },
5944
- { label: "finish", line: "pnpm cella sync", details: [colors_default.dim("commits the sync and stops for drift triage")] }
6019
+ {
6020
+ label: "finish",
6021
+ line: "pnpm cella upgrade",
6022
+ details: [colors_default.dim("commits the upgrade and stops for drift triage")]
6023
+ }
5945
6024
  ]);
5946
6025
  return;
5947
6026
  }
@@ -5959,7 +6038,7 @@ ${colors_default.dim(`on '${branch}', not pushed`)}`);
5959
6038
  details: [colors_default.dim("drift triage: commit any follow-ups on this branch")]
5960
6039
  },
5961
6040
  await syncAlignmentsStep(config, run),
5962
- { label: "ship", line: "pnpm cella sync", details: [colors_default.dim("pushes the branch and opens the squash-merge PR")] }
6041
+ { label: "ship", line: "pnpm cella upgrade", details: [colors_default.dim("pushes the branch and opens the squash-merge PR")] }
5963
6042
  ];
5964
6043
  printNextSteps(steps.filter((step) => !!step));
5965
6044
  }
@@ -5972,7 +6051,7 @@ async function mergeOpenSyncPrs(config, open) {
5972
6051
  const merged = mergePrSquash(forkPath, newest.number, { deleteBranch: true });
5973
6052
  if (!merged.ok) {
5974
6053
  console.info();
5975
- console.info(colors_default.yellow(`could not merge #${newest.number}: resolve it first, then re-run \`pnpm cella sync\`:`));
6054
+ console.info(colors_default.yellow(`could not merge #${newest.number}: resolve it first, then re-run \`pnpm cella upgrade\`:`));
5976
6055
  if (merged.output) console.info(colors_default.dim(merged.output.replace(/^/gm, " ")));
5977
6056
  console.info(colors_default.dim(` ${newest.url}`));
5978
6057
  return "cancel";
@@ -5989,25 +6068,27 @@ async function mergeOpenSyncPrs(config, open) {
5989
6068
  async function guardAgainstOpenSyncPr(config) {
5990
6069
  const { forkPath } = config;
5991
6070
  if (!ghAvailable() || !process.stdout.isTTY) return "continue";
5992
- const open = listOpenSyncPrs(forkPath, DEFAULT_SYNC_PREFIX);
6071
+ const open = listOpenSyncPrs(forkPath, TEMPORARY_BRANCH_PREFIXES);
5993
6072
  if (open.length === 0) return "continue";
5994
6073
  const many = open.length > 1;
5995
6074
  console.info();
5996
6075
  console.info(
5997
- `${warningMark} ${colors_default.yellow(`${many ? `${open.length} earlier sync PRs are` : "an earlier sync PR is"} still open and unmerged:`)}`
6076
+ `${warningMark} ${colors_default.yellow(`${many ? `${open.length} earlier upgrade PRs are` : "an earlier upgrade PR is"} still open and unmerged:`)}`
5998
6077
  );
5999
6078
  for (const pr of open) {
6000
6079
  console.info(colors_default.dim(` #${pr.number} ${pr.title}`));
6001
6080
  console.info(colors_default.dim(` ${pr.url}`));
6002
6081
  }
6003
- console.info(colors_default.dim(` starting a new sync now produces a PR that re-includes ${many ? "these" : "those"} changes.`));
6082
+ console.info(
6083
+ colors_default.dim(` starting a new upgrade now produces a PR that re-includes ${many ? "these" : "those"} changes.`)
6084
+ );
6004
6085
  console.info();
6005
6086
  const choice = await select4({
6006
6087
  message: "how do you want to proceed?",
6007
6088
  choices: [
6008
6089
  {
6009
6090
  value: "merge",
6010
- name: `merge ${many ? "them" : `#${open[0].number}`} first, then sync ${colors_default.dim("(recommended)")}`
6091
+ name: `merge ${many ? "them" : `#${open[0].number}`} first, then upgrade ${colors_default.dim("(recommended)")}`
6011
6092
  },
6012
6093
  { value: "continue", name: `continue anyway ${colors_default.dim("(new PR will re-include the unmerged changes)")}` },
6013
6094
  { value: "cancel", name: colors_default.red("cancel") }
@@ -6018,7 +6099,7 @@ async function guardAgainstOpenSyncPr(config) {
6018
6099
  if (choice === "continue") return "continue";
6019
6100
  return mergeOpenSyncPrs(config, open);
6020
6101
  }
6021
- async function runSyncCommand(config) {
6102
+ async function runUpgradeCommand(config) {
6022
6103
  const { forkPath } = config;
6023
6104
  const currentBranch = await getCurrentBranch(forkPath);
6024
6105
  const onSyncBranch = isTemporarySyncBranch(currentBranch);
@@ -6031,7 +6112,7 @@ async function runSyncCommand(config) {
6031
6112
  console.info();
6032
6113
  console.info(
6033
6114
  colors_default.yellow(
6034
- `sync branch '${currentBranch}' has uncommitted changes.
6115
+ `upgrade branch '${currentBranch}' has uncommitted changes.
6035
6116
  commit them first (\`git commit --amend --no-edit\` or a new commit).`
6036
6117
  )
6037
6118
  );
@@ -6041,17 +6122,17 @@ commit them first (\`git commit --amend --no-edit\` or a new commit).`
6041
6122
  return;
6042
6123
  }
6043
6124
  if (!await isClean(forkPath)) {
6044
- throw new Error("working directory has uncommitted changes. please commit or stash before syncing.");
6125
+ throw new Error("working directory has uncommitted changes. please commit or stash before upgrading.");
6045
6126
  }
6046
6127
  if (await guardAgainstOpenSyncPr(config) === "cancel") return;
6047
6128
  const outcome = await runSyncCycle(config);
6048
6129
  if (outcome.status === "noop") {
6049
6130
  console.info();
6050
6131
  if (outcome.behind) {
6051
- console.info(colors_default.green("nothing to sync: the last sync already went past this upstream point."));
6132
+ console.info(colors_default.green("nothing to upgrade: the last upgrade already went past this upstream point."));
6052
6133
  for (const line of outcome.behind.split("\n")) console.info(colors_default.dim(` ${line}`));
6053
6134
  } else {
6054
- console.info(colors_default.green("already up to date with upstream, nothing to sync."));
6135
+ console.info(colors_default.green("already up to date with upstream, nothing to upgrade."));
6055
6136
  }
6056
6137
  const align = await syncAlignmentsStep(config, outcome.result);
6057
6138
  if (align) printNextSteps([align]);
@@ -6089,7 +6170,7 @@ function formatForkChoice(name, status) {
6089
6170
  syncPart = colors_default.dim(`${status.lastSync.date}`);
6090
6171
  if (msg) syncPart += colors_default.dim(` '${msg}'`);
6091
6172
  } else {
6092
- syncPart = colors_default.dim("never synced");
6173
+ syncPart = colors_default.dim("never upgraded");
6093
6174
  }
6094
6175
  const dirtyPart = status.dirty > 0 ? colors_default.yellow(`${status.dirty} uncommitted`) : "";
6095
6176
  const parts = [name, colors_default.dim(`[${status.branch}]`), syncPart];
@@ -6121,15 +6202,15 @@ async function buildForkChoices(forks, basePath) {
6121
6202
  }
6122
6203
  async function syncFork(config, fork, forkPath) {
6123
6204
  console.info();
6124
- console.info(colors_default.cyan(`syncing to ${fork.name}...`));
6205
+ console.info(colors_default.cyan(`upgrading ${fork.name}...`));
6125
6206
  console.info(colors_default.dim(`path: ${forkPath}`));
6126
6207
  console.info();
6127
6208
  const forkConfig = await loadConfig(forkPath);
6128
- await runSyncCommand({
6209
+ await runUpgradeCommand({
6129
6210
  ...forkConfig,
6130
6211
  forkPath,
6131
6212
  upstreamRef: resolveUpstream(forkConfig.settings).branchRef,
6132
- service: "sync",
6213
+ service: "upgrade",
6133
6214
  list: false,
6134
6215
  json: false,
6135
6216
  verbose: false,
@@ -6156,7 +6237,7 @@ async function runForks(config) {
6156
6237
  const choices = await buildForkChoices(forks, forkBasePath);
6157
6238
  const forkChoices = [...choices, new Separator2(MENU_DIVIDER), { value: "_exit", name: colors_default.dim("exit") }];
6158
6239
  const selectedPath = await select5({
6159
- message: "select fork to sync:",
6240
+ message: "select fork to upgrade:",
6160
6241
  choices: forkChoices,
6161
6242
  loop: false
6162
6243
  });
@@ -6620,7 +6701,7 @@ function preflight(forkPath) {
6620
6701
  }
6621
6702
  var services = {
6622
6703
  analyze: runAnalyze,
6623
- sync: runSyncCommand,
6704
+ upgrade: runUpgradeCommand,
6624
6705
  align: runAlign,
6625
6706
  audit: runAudit,
6626
6707
  forks: runForks,