@cellajs/cli 0.6.4 → 0.6.5

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
@@ -233,7 +233,7 @@ import process6 from "process";
233
233
  // package.json
234
234
  var package_default = {
235
235
  name: "@cellajs/cli",
236
- version: "0.6.4",
236
+ version: "0.6.5",
237
237
  private: false,
238
238
  license: "MIT",
239
239
  description: "CLI for managing your monorepo and upgrading it with upstream Cella.",
@@ -1373,12 +1373,19 @@ var STARTUP_TIMEOUT_MS = 5 * 6e4;
1373
1373
  var STOP_TIMEOUT_MS = 1e4;
1374
1374
  var DATABASE = "testbed";
1375
1375
  var DATABASE_SERVICE = "db_testbed";
1376
+ var showcasePath = (forkPath) => join4(forkPath, "json/showcase.json");
1377
+ var hasShowcase = (forkPath) => existsSync4(showcasePath(forkPath));
1378
+ function showcaseAdmin(forkPath) {
1379
+ const { admin } = JSON.parse(readFileSync2(showcasePath(forkPath), "utf8"));
1380
+ if (typeof admin?.email !== "string") throw new Error("json/showcase.json names no admin email");
1381
+ return admin.email;
1382
+ }
1376
1383
  var shiftPort = (url) => {
1377
1384
  const next = new URL(url);
1378
1385
  next.port = String(Number(next.port) + PORT_SHIFT);
1379
1386
  return next.toString().replace(/\/$/, "");
1380
1387
  };
1381
- async function resolveTestbed(forkPath) {
1388
+ async function resolveTestbed(forkPath, data = "seed") {
1382
1389
  const [facts, databases] = await Promise.all([loadAppFacts(forkPath), loadLocalDatabases(forkPath)]);
1383
1390
  const databasePort = databases.port(DATABASE);
1384
1391
  if (!Number.isInteger(databasePort)) {
@@ -1398,6 +1405,7 @@ async function resolveTestbed(forkPath) {
1398
1405
  // The seed creates the admin that backend/.env names, and a command signs in as that user
1399
1406
  ...fileEnv.ADMIN_EMAIL ? { ADMIN_EMAIL: fileEnv.ADMIN_EMAIL } : {},
1400
1407
  ...getEnvSnapshot(),
1408
+ ...data === "showcase" ? { ADMIN_EMAIL: showcaseAdmin(forkPath) } : {},
1401
1409
  ...composeEnv,
1402
1410
  NODE_ENV: "development",
1403
1411
  DATABASE_URL: databases.url(DATABASE, "runtime_role"),
@@ -1411,12 +1419,22 @@ async function resolveTestbed(forkPath) {
1411
1419
  ({ port, internalPort }) => (internalPort === void 0 ? [port] : [port, internalPort]).map((value) => value + PORT_SHIFT)
1412
1420
  ),
1413
1421
  container: `${composeEnv.PROJECT_SLUG}_${DATABASE_SERVICE}`,
1422
+ data,
1414
1423
  yjs: facts.services.yjs?.enabled ?? false,
1415
1424
  stateDir: toolDir(forkPath, "testbed", "repository")
1416
1425
  };
1417
1426
  }
1418
1427
  var lockPath = (testbed) => join4(testbed.stateDir, "lock.json");
1419
1428
  var logPath = (testbed) => join4(testbed.stateDir, "testbed.log");
1429
+ var dataPath = (testbed) => join4(testbed.stateDir, "data.json");
1430
+ function heldData(testbed) {
1431
+ try {
1432
+ return JSON.parse(readFileSync2(dataPath(testbed), "utf8")).data === "showcase" ? "showcase" : "seed";
1433
+ } catch {
1434
+ return "seed";
1435
+ }
1436
+ }
1437
+ var describeData = (data) => data === "showcase" ? "the showcase" : "the seed data";
1420
1438
  function isAlive(pid) {
1421
1439
  try {
1422
1440
  process8.kill(pid, 0);
@@ -1498,7 +1516,12 @@ async function startTestbed(testbed, fresh, drop = false) {
1498
1516
  mkdirSync(testbed.stateDir, { recursive: true });
1499
1517
  writeFileSync(
1500
1518
  lockPath(testbed),
1501
- JSON.stringify({ pid: process8.pid, forkPath: testbed.forkPath, frontendUrl: testbed.frontendUrl })
1519
+ JSON.stringify({
1520
+ pid: process8.pid,
1521
+ forkPath: testbed.forkPath,
1522
+ frontendUrl: testbed.frontendUrl,
1523
+ data: testbed.data
1524
+ })
1502
1525
  );
1503
1526
  const log = openSync(logPath(testbed), "w");
1504
1527
  let stack;
@@ -1525,14 +1548,15 @@ async function startTestbed(testbed, fresh, drop = false) {
1525
1548
  };
1526
1549
  const forget = onShutdown(stop);
1527
1550
  try {
1528
- if (fresh) removeDatabase(testbed);
1551
+ if (fresh || testbed.data === "showcase" || heldData(testbed) !== testbed.data) removeDatabase(testbed);
1529
1552
  const spinner = createSpinner(`starting the database on port ${testbed.databasePort}`);
1530
1553
  if (!compose(testbed, ["up", "-d", "--wait", DATABASE_SERVICE])) {
1531
1554
  throw new Error("the testbed database did not start: is Docker running?");
1532
1555
  }
1533
1556
  const seeded = isSeeded(testbed);
1534
- spinner.text = seeded ? "migrating the database" : "migrating and seeding the database (first start only)";
1535
- const prepare = seeded ? ["--filter", "backend", "migrate"] : ["seed"];
1557
+ spinner.text = seeded ? "migrating the database" : `migrating the database and seeding ${describeData(testbed.data)}`;
1558
+ const seed = testbed.data === "showcase" ? ["seed", "showcase"] : ["seed"];
1559
+ const prepare = seeded ? ["--filter", "backend", "migrate"] : seed;
1536
1560
  const prepared = spawnSync3("pnpm", prepare, {
1537
1561
  cwd: testbed.forkPath,
1538
1562
  env: testbed.env,
@@ -1540,7 +1564,11 @@ async function startTestbed(testbed, fresh, drop = false) {
1540
1564
  });
1541
1565
  if (prepared.status !== 0) throw new Error(`\`pnpm ${prepare.join(" ")}\` failed:
1542
1566
  ${logTail(testbed)}`);
1543
- printStep("database", `${seeded ? "migrated" : "seeded"}, port ${testbed.databasePort}`);
1567
+ writeFileSync(dataPath(testbed), JSON.stringify({ data: testbed.data }));
1568
+ printStep(
1569
+ "database",
1570
+ `${seeded ? "migrated" : `seeded with ${describeData(testbed.data)}`}, port ${testbed.databasePort}`
1571
+ );
1544
1572
  const relay = testbed.yjs ? "pnpm --filter yjs-worker dev & " : "";
1545
1573
  stack = spawn("sh", ["-c", `${relay}pnpm offline`], {
1546
1574
  cwd: testbed.forkPath,
@@ -1608,14 +1636,19 @@ function ownLock(testbed) {
1608
1636
  }
1609
1637
  return lock;
1610
1638
  }
1611
- async function withTestbed(forkPath, use, { fresh = false, destructive = false } = {}) {
1612
- const testbed = await resolveTestbed(forkPath);
1639
+ async function withTestbed(forkPath, use, { fresh = false, destructive = false, data = "seed" } = {}) {
1640
+ const testbed = await resolveTestbed(forkPath, data);
1613
1641
  const lock = ownLock(testbed);
1614
1642
  if (lock && destructive) {
1615
1643
  throw new Error(
1616
1644
  `a testbed runs at ${lock.frontendUrl}: this command needs one of its own, so stop that one first (\`pnpm cella testbed stop\`)`
1617
1645
  );
1618
1646
  }
1647
+ if (lock && (lock.data ?? "seed") !== data) {
1648
+ throw new Error(
1649
+ `a testbed with ${describeData(lock.data ?? "seed")} runs at ${lock.frontendUrl}: this command needs ${describeData(data)}, so stop that one first (\`pnpm cella testbed stop\`)`
1650
+ );
1651
+ }
1619
1652
  if (lock) {
1620
1653
  await untilAnswering(
1621
1654
  testbed,
@@ -1633,10 +1666,12 @@ async function withTestbed(forkPath, use, { fresh = false, destructive = false }
1633
1666
  }
1634
1667
  async function runTestbed(forkPath, options) {
1635
1668
  if (options.job === "stop") return stopTestbed(await resolveTestbed(forkPath));
1669
+ if (options.showcase && !hasShowcase(forkPath)) throw new Error("this app keeps no json/showcase.json");
1670
+ const data = options.showcase ? "showcase" : "seed";
1636
1671
  if (options.command.length > 0) {
1637
- return withTestbed(forkPath, (testbed2) => runCommand(forkPath, testbed2.env, options.command), options);
1672
+ return withTestbed(forkPath, (testbed2) => runCommand(forkPath, testbed2.env, options.command), { ...options, data });
1638
1673
  }
1639
- const testbed = await resolveTestbed(forkPath);
1674
+ const testbed = await resolveTestbed(forkPath, data);
1640
1675
  const lock = ownLock(testbed);
1641
1676
  if (lock) {
1642
1677
  throw new Error(
@@ -1664,7 +1699,10 @@ var testbedCommand = {
1664
1699
  ["start", "start it and hold it until ctrl-c"],
1665
1700
  ["stop", "stop the testbed that runs, or one left behind"]
1666
1701
  ],
1667
- options: [["--fresh", "start from an empty database: migrate and seed it again"]],
1702
+ options: [
1703
+ ["--fresh", "start from an empty database: migrate and seed it again"],
1704
+ ["--showcase", "hold the showcase of json/showcase.json, which the screenshots shoot, for a review loop"]
1705
+ ],
1668
1706
  passthrough: [
1669
1707
  "command",
1670
1708
  "after `--`: run it against the testbed (this checkout's running one, else one started for it and stopped after)"
@@ -1672,7 +1710,7 @@ var testbedCommand = {
1672
1710
  parse: ({ job = "start", opts, passthrough }) => {
1673
1711
  if (job !== "start" && job !== "stop") throw new Error(`unknown job '${job}'. expected one of: start, stop`);
1674
1712
  if (job === "stop" && passthrough.length > 0) throw new Error("stop takes no command");
1675
- return { job, fresh: opts.fresh === true, command: passthrough };
1713
+ return { job, fresh: opts.fresh === true, showcase: opts.showcase === true, command: passthrough };
1676
1714
  },
1677
1715
  run: runTestbed
1678
1716
  };
@@ -5270,7 +5308,7 @@ var pentestCommand = {
5270
5308
 
5271
5309
  // src/tools/screenshots/shoot.ts
5272
5310
  import { spawnSync as spawnSync9 } from "child_process";
5273
- import { mkdirSync as mkdirSync7, mkdtempSync, rmSync as rmSync5, statSync as statSync3, writeFileSync as writeFileSync10 } from "fs";
5311
+ import { mkdirSync as mkdirSync7, mkdtempSync, readFileSync as readFileSync13, rmSync as rmSync5, statSync as statSync3, writeFileSync as writeFileSync10 } from "fs";
5274
5312
  import { tmpdir } from "os";
5275
5313
  import { basename as basename4, dirname as dirname7, join as join21, resolve as resolve7 } from "path";
5276
5314
 
@@ -5350,6 +5388,7 @@ async function spinnersGone(page, quiet = 1e3, cap = 45e3) {
5350
5388
  await page.waitForTimeout(100);
5351
5389
  }
5352
5390
  }
5391
+ var hasMfaScript = (forkPath) => Boolean(JSON.parse(readFileSync13(join21(forkPath, "backend/package.json"), "utf8")).scripts?.["showcase:mfa"]);
5353
5392
  async function shoot(forkPath, list2, testbed, options) {
5354
5393
  const email = options.email ?? testbed.env.ADMIN_EMAIL;
5355
5394
  if (!email) throw new Error("no shot user: pass --email, or set ADMIN_EMAIL in backend/.env");
@@ -5376,15 +5415,17 @@ async function shoot(forkPath, list2, testbed, options) {
5376
5415
  if (encoded.status !== 0) throw new Error(`cwebp could not write ${path}: ${encoded.stderr.trim()}`);
5377
5416
  };
5378
5417
  try {
5379
- const showcase = spawnSync9("pnpm", ["--silent", "--filter", "backend", "showcase:mfa", email], {
5380
- cwd: forkPath,
5381
- env: testbed.env,
5382
- encoding: "utf8"
5383
- });
5384
- if (showcase.status !== 0) throw new Error(`showcase:mfa failed:
5418
+ if (testbed.data === "seed" && hasMfaScript(forkPath)) {
5419
+ const showcase = spawnSync9("pnpm", ["--silent", "--filter", "backend", "showcase:mfa", email], {
5420
+ cwd: forkPath,
5421
+ env: testbed.env,
5422
+ encoding: "utf8"
5423
+ });
5424
+ if (showcase.status !== 0) throw new Error(`showcase:mfa failed:
5385
5425
  ${showcase.stdout}
5386
5426
  ${showcase.stderr}`);
5387
- printStep("mfa", showcase.stdout.trim().split("\n").at(-1));
5427
+ printStep("mfa", showcase.stdout.trim().split("\n").at(-1));
5428
+ }
5388
5429
  for (const prepare of list2.prepare) await prepare(signedIn(user));
5389
5430
  const values = {};
5390
5431
  for (const [name, resolve12] of Object.entries(list2.placeholders)) values[name] = await resolve12(signedIn(user));
@@ -5468,7 +5509,8 @@ async function runScreenshots(forkPath, options) {
5468
5509
  }
5469
5510
  requireEncoder(list2.format);
5470
5511
  await requireChromium(forkPath);
5471
- return withTestbed(forkPath, (testbed) => shoot(forkPath, list2, testbed, options));
5512
+ const data = hasShowcase(forkPath) ? "showcase" : "seed";
5513
+ return withTestbed(forkPath, (testbed) => shoot(forkPath, list2, testbed, options), { data });
5472
5514
  }
5473
5515
  var screenshotsCommand = {
5474
5516
  name: "screenshots",
@@ -5478,7 +5520,7 @@ var screenshotsCommand = {
5478
5520
  operands: ["[ids...]", "the shots to take (default: all)"],
5479
5521
  options: [
5480
5522
  ["--out <dir>", "write into this folder, a trial run that leaves the working tree alone"],
5481
- ["--email <address>", "the shot user (default ADMIN_EMAIL in backend/.env)"]
5523
+ ["--email <address>", "the shot user (default the showcase admin, else ADMIN_EMAIL in backend/.env)"]
5482
5524
  ],
5483
5525
  parse: ({ operands, opts }) => ({
5484
5526
  ids: operands,
@@ -5489,7 +5531,7 @@ var screenshotsCommand = {
5489
5531
  };
5490
5532
 
5491
5533
  // src/tools/style/index.ts
5492
- import { readFileSync as readFileSync15 } from "fs";
5534
+ import { readFileSync as readFileSync16 } from "fs";
5493
5535
  import { join as join27 } from "path";
5494
5536
 
5495
5537
  // src/utils/alignments.ts
@@ -6042,7 +6084,7 @@ function docFindings(file, source) {
6042
6084
  }
6043
6085
 
6044
6086
  // src/tools/style/frontend-rules.ts
6045
- import { existsSync as existsSync19, readFileSync as readFileSync13 } from "fs";
6087
+ import { existsSync as existsSync19, readFileSync as readFileSync14 } from "fs";
6046
6088
  import { extname as extname4, join as join24 } from "path";
6047
6089
  function containsJsx(node) {
6048
6090
  return ts.isJsxElement(node) || ts.isJsxFragment(node) || ts.isJsxSelfClosingElement(node) || !!ts.forEachChild(node, containsJsx);
@@ -6214,7 +6256,7 @@ function inProductModule(file) {
6214
6256
  if (!folder) return false;
6215
6257
  const queryFile = join24(repoRoot, `${folder}query.ts`);
6216
6258
  if (!productModuleFolders.has(queryFile)) {
6217
- const source = existsSync19(queryFile) ? readFileSync13(queryFile, "utf8") : "";
6259
+ const source = existsSync19(queryFile) ? readFileSync14(queryFile, "utf8") : "";
6218
6260
  productModuleFolders.set(
6219
6261
  queryFile,
6220
6262
  markCalls(ts.createSourceFile(queryFile, source, ts.ScriptTarget.Latest)).registersRangeFetch
@@ -6238,7 +6280,7 @@ function checkProductCacheWrite(file, sourceFile, report) {
6238
6280
  function frontendStores(files2) {
6239
6281
  const stores = /* @__PURE__ */ new Set();
6240
6282
  for (const file of files2.filter(isFrontendSource)) {
6241
- const source = readFileSync13(join24(repoRoot, file), "utf8");
6283
+ const source = readFileSync14(join24(repoRoot, file), "utf8");
6242
6284
  if (source.includes("zustand")) collectStores(parseSource(file, source), stores);
6243
6285
  }
6244
6286
  return stores;
@@ -6324,7 +6366,7 @@ function stampFindings(file, source) {
6324
6366
  }
6325
6367
 
6326
6368
  // src/tools/style/tailwind-class-rules.ts
6327
- import { readFileSync as readFileSync14 } from "fs";
6369
+ import { readFileSync as readFileSync15 } from "fs";
6328
6370
  import { createRequire as createRequire2 } from "module";
6329
6371
  import { dirname as dirname9, join as join25, relative as relative2 } from "path";
6330
6372
 
@@ -6392,11 +6434,11 @@ function addMatches(target, text2, pattern) {
6392
6434
  function usedClassNames(files2) {
6393
6435
  const names = /* @__PURE__ */ new Set();
6394
6436
  for (const file of files2.filter(isFrontendStylesheet)) {
6395
- const css = readFileSync14(join25(repoRoot, file), "utf8").replace(/\/\*[\s\S]*?\*\//g, "");
6437
+ const css = readFileSync15(join25(repoRoot, file), "utf8").replace(/\/\*[\s\S]*?\*\//g, "");
6396
6438
  addMatches(names, css, /(?<!\\)\.(-?[_a-zA-Z][\w-]*)/g);
6397
6439
  }
6398
6440
  for (const file of files2.filter(isFrontendScript)) {
6399
- const source = readFileSync14(join25(repoRoot, file), "utf8");
6441
+ const source = readFileSync15(join25(repoRoot, file), "utf8");
6400
6442
  for (const [chunk] of source.matchAll(/(?<![\w$)\]?.])\[[^\s'"`]*/g))
6401
6443
  addMatches(names, chunk, /(?<![a-zA-Z0-9$.)\]?!])\.(-?[_a-zA-Z][\w-]*)/g);
6402
6444
  for (const [, , text2] of source.matchAll(/(['"`])((?:\\.|(?!\1)[^\\\n])*)\1/g)) {
@@ -6412,14 +6454,14 @@ function usedClassNames(files2) {
6412
6454
  return names;
6413
6455
  }
6414
6456
  async function tailwindContext(files2, appMarkerClasses = {}) {
6415
- const entry = files2.filter(isFrontendStylesheet).find((file) => tailwindImport.test(readFileSync14(join25(repoRoot, file), "utf8")));
6457
+ const entry = files2.filter(isFrontendStylesheet).find((file) => tailwindImport.test(readFileSync15(join25(repoRoot, file), "utf8")));
6416
6458
  if (!entry) return void 0;
6417
6459
  const path = join25(repoRoot, entry);
6418
6460
  const knownClasses = usedClassNames(files2);
6419
6461
  for (const name of Object.keys({ ...markerClasses, ...appMarkerClasses })) knownClasses.add(name);
6420
6462
  const context = { entry, knownClasses, compiles: /* @__PURE__ */ new Map() };
6421
6463
  try {
6422
- context.designSystem = await (await loadTailwindNode()).__unstable__loadDesignSystem(readFileSync14(path, "utf8"), {
6464
+ context.designSystem = await (await loadTailwindNode()).__unstable__loadDesignSystem(readFileSync15(path, "utf8"), {
6423
6465
  base: dirname9(path)
6424
6466
  });
6425
6467
  } catch (error) {
@@ -6848,7 +6890,7 @@ async function runStyle(root, { paths }) {
6848
6890
  const files2 = repoFiles();
6849
6891
  const stores = frontendStores(files2);
6850
6892
  const tailwind = await tailwindContext(files2, allowlist.markerClasses);
6851
- const read = (file) => readFileSync15(join27(repoRoot, file), "utf8");
6893
+ const read = (file) => readFileSync16(join27(repoRoot, file), "utf8");
6852
6894
  const requested = files2.filter((file) => isRequested(file, paths));
6853
6895
  const findings2 = paths.filter((path) => !files2.some((file) => isRequested(file, [path]))).map((path) => ({ file: path, rule: "path-argument", message: "no file matches this path" }));
6854
6896
  findings2.push(...alignmentFindings(requested, read));
@@ -6856,7 +6898,7 @@ async function runStyle(root, { paths }) {
6856
6898
  findings2.push(...owedAlignmentFindings(await branchChanges(), read("cella/cella.config.ts")));
6857
6899
  }
6858
6900
  for (const file of requested) {
6859
- const content = readFileSync15(join27(repoRoot, file));
6901
+ const content = readFileSync16(join27(repoRoot, file));
6860
6902
  if (content.includes(0)) continue;
6861
6903
  const source = content.toString("utf8");
6862
6904
  const prose = allowlist.proseExclude?.some((prefix) => file.startsWith(prefix)) ? [] : [...docFindings(file, source), ...commentFindings(file, source)];
@@ -8999,7 +9041,7 @@ function syncStep(result) {
8999
9041
  }
9000
9042
 
9001
9043
  // src/services/audit.ts
9002
- import { readFileSync as readFileSync18 } from "fs";
9044
+ import { readFileSync as readFileSync19 } from "fs";
9003
9045
  import { basename as basename9, join as join35, relative as relative4 } from "path";
9004
9046
  import { checkbox, Separator } from "@inquirer/prompts";
9005
9047
 
@@ -9114,7 +9156,7 @@ import { delimiter, dirname as dirname13, join as join33, sep as sep2 } from "pa
9114
9156
  import { promisify as promisify3 } from "util";
9115
9157
 
9116
9158
  // src/utils/runtimes.ts
9117
- import { readFileSync as readFileSync16 } from "fs";
9159
+ import { readFileSync as readFileSync17 } from "fs";
9118
9160
  import { basename as basename8, dirname as dirname12, join as join32 } from "path";
9119
9161
  var DAY = 24 * 60 * 60 * 1e3;
9120
9162
  var FROZEN_AFTER = 180 * DAY;
@@ -9157,7 +9199,7 @@ function parseDockerfile(file, content) {
9157
9199
  async function readRuntimePins(forkPath) {
9158
9200
  let manifest = {};
9159
9201
  try {
9160
- manifest = JSON.parse(readFileSync16(join32(forkPath, "package.json"), "utf8"));
9202
+ manifest = JSON.parse(readFileSync17(join32(forkPath, "package.json"), "utf8"));
9161
9203
  } catch {
9162
9204
  }
9163
9205
  const node = manifest.engines?.node?.trim() ?? "";
@@ -9168,7 +9210,7 @@ async function readRuntimePins(forkPath) {
9168
9210
  for (const file of tracked) {
9169
9211
  let content;
9170
9212
  try {
9171
- content = readFileSync16(join32(forkPath, file), "utf8");
9213
+ content = readFileSync17(join32(forkPath, file), "utf8");
9172
9214
  } catch {
9173
9215
  continue;
9174
9216
  }
@@ -9684,14 +9726,14 @@ function writeAuditSettings(content, next) {
9684
9726
 
9685
9727
  // src/services/audit-security.ts
9686
9728
  import { spawnSync as spawnSync11 } from "child_process";
9687
- import { cpSync, existsSync as existsSync25, mkdirSync as mkdirSync9, mkdtempSync as mkdtempSync2, readFileSync as readFileSync17, rmSync as rmSync7, writeFileSync as writeFileSync12 } from "fs";
9729
+ import { cpSync, existsSync as existsSync25, mkdirSync as mkdirSync9, mkdtempSync as mkdtempSync2, readFileSync as readFileSync18, rmSync as rmSync7, writeFileSync as writeFileSync12 } from "fs";
9688
9730
  import { tmpdir as tmpdir3 } from "os";
9689
9731
  import { dirname as dirname14, join as join34, relative as relative3 } from "path";
9690
9732
  import { confirm, select as select2 } from "@inquirer/prompts";
9691
9733
  var WORKSPACE_FILE = "pnpm-workspace.yaml";
9692
9734
  var LOCK_FILE = "pnpm-lock.yaml";
9693
9735
  var RESOLUTION_FILES = ["package.json", LOCK_FILE, ".npmrc", ".pnpmfile.cjs"];
9694
- var readOr = (path, fallback = "") => existsSync25(path) ? readFileSync17(path, "utf8") : fallback;
9736
+ var readOr = (path, fallback = "") => existsSync25(path) ? readFileSync18(path, "utf8") : fallback;
9695
9737
  var count2 = (n, noun, plural2 = `${noun}s`) => `${n} ${n === 1 ? noun : plural2}`;
9696
9738
  var isBreaking = (item) => item.remedy.kind !== "none" && item.remedy.breaking;
9697
9739
  var needsDecision = (item) => item.standing === "new" && (item.remedy.kind !== "override" || item.remedy.breaking || item.direct);
@@ -10004,7 +10046,7 @@ function createDependentPkgReader() {
10004
10046
  let cached = cache.get(location);
10005
10047
  if (cached === void 0) {
10006
10048
  try {
10007
- cached = JSON.parse(readFileSync18(join35(location, "package.json"), "utf8"));
10049
+ cached = JSON.parse(readFileSync19(join35(location, "package.json"), "utf8"));
10008
10050
  } catch {
10009
10051
  cached = null;
10010
10052
  }
@@ -10176,7 +10218,7 @@ function printOutdatedResults(rows, forkPath) {
10176
10218
  function printNotes(forkPath, unchecked) {
10177
10219
  let held = [];
10178
10220
  try {
10179
- const updateConfig = readTopLevel(readFileSync18(join35(forkPath, "pnpm-workspace.yaml"), "utf8"), "updateConfig");
10221
+ const updateConfig = readTopLevel(readFileSync19(join35(forkPath, "pnpm-workspace.yaml"), "utf8"), "updateConfig");
10180
10222
  const ignored = updateConfig?.ignoreDependencies;
10181
10223
  held = Array.isArray(ignored) ? ignored.map(String) : [];
10182
10224
  } catch {
@@ -10300,7 +10342,7 @@ async function planEdits(forkPath, rows, selected, nodeImageSuffixes) {
10300
10342
  const summary = /* @__PURE__ */ new Map();
10301
10343
  const bumped = [];
10302
10344
  const edit = (file, label, item, resolves, change) => {
10303
- const entry = contents.get(file) ?? { content: readFileSync18(join35(forkPath, file), "utf8"), resolves: false };
10345
+ const entry = contents.get(file) ?? { content: readFileSync19(join35(forkPath, file), "utf8"), resolves: false };
10304
10346
  const next = change(entry.content);
10305
10347
  if (next === entry.content) return;
10306
10348
  contents.set(file, { content: next, resolves: entry.resolves || resolves });
@@ -10836,11 +10878,11 @@ function closePr(cwd, ref) {
10836
10878
  }
10837
10879
 
10838
10880
  // src/services/packages.ts
10839
- import { existsSync as existsSync27, readFileSync as readFileSync20, writeFileSync as writeFileSync13 } from "fs";
10881
+ import { existsSync as existsSync27, readFileSync as readFileSync21, writeFileSync as writeFileSync13 } from "fs";
10840
10882
  import { join as join38 } from "path";
10841
10883
 
10842
10884
  // src/services/package-usage.ts
10843
- import { existsSync as existsSync26, readFileSync as readFileSync19, statSync as statSync4 } from "fs";
10885
+ import { existsSync as existsSync26, readFileSync as readFileSync20, statSync as statSync4 } from "fs";
10844
10886
  import { join as join37 } from "path";
10845
10887
  var MAX_FILE_BYTES2 = 1024 * 1024;
10846
10888
  function escapeRegExp2(value) {
@@ -10849,7 +10891,7 @@ function escapeRegExp2(value) {
10849
10891
  function readSearchable(filePath) {
10850
10892
  try {
10851
10893
  if (statSync4(filePath).size > MAX_FILE_BYTES2) return "";
10852
- const text2 = readFileSync19(filePath, "utf8");
10894
+ const text2 = readFileSync20(filePath, "utf8");
10853
10895
  return text2.includes("\0") ? "" : text2;
10854
10896
  } catch {
10855
10897
  return "";
@@ -10869,7 +10911,7 @@ async function readScriptsAtRef(forkPath, ref, path) {
10869
10911
  async function scriptSources(forkPath, upstreamRef, baseRef, path) {
10870
10912
  let forkScripts;
10871
10913
  try {
10872
- forkScripts = JSON.parse(readFileSync19(join37(forkPath, path), "utf8")).scripts ?? {};
10914
+ forkScripts = JSON.parse(readFileSync20(join37(forkPath, path), "utf8")).scripts ?? {};
10873
10915
  } catch {
10874
10916
  return [];
10875
10917
  }
@@ -10883,7 +10925,7 @@ function binNames(forkPath, location, name) {
10883
10925
  const manifest = join37(dir, "node_modules", name, "package.json");
10884
10926
  if (!existsSync26(manifest)) continue;
10885
10927
  try {
10886
- const { bin } = JSON.parse(readFileSync19(manifest, "utf8"));
10928
+ const { bin } = JSON.parse(readFileSync20(manifest, "utf8"));
10887
10929
  if (typeof bin === "string") return [bareName];
10888
10930
  return bin && typeof bin === "object" ? Object.keys(bin) : [];
10889
10931
  } catch {
@@ -11064,7 +11106,7 @@ function setTopLevelKey(pkg, key, value) {
11064
11106
  function readPackageJson(filePath) {
11065
11107
  if (!existsSync27(filePath)) return null;
11066
11108
  try {
11067
- return JSON.parse(readFileSync20(filePath, "utf8"));
11109
+ return JSON.parse(readFileSync21(filePath, "utf8"));
11068
11110
  } catch (error) {
11069
11111
  throw new Error(`cannot parse ${filePath}: ${errorMessage(error)}`);
11070
11112
  }
@@ -11802,7 +11844,7 @@ import { readFile as readFile3 } from "fs/promises";
11802
11844
  import { join as join40 } from "path";
11803
11845
 
11804
11846
  // src/utils/coverage-utils.ts
11805
- import { existsSync as existsSync28, readFileSync as readFileSync21, statSync as statSync5 } from "fs";
11847
+ import { existsSync as existsSync28, readFileSync as readFileSync22, statSync as statSync5 } from "fs";
11806
11848
  import { join as join39, relative as relative5, sep as sep3 } from "path";
11807
11849
  var STALE_THRESHOLD_MS = 7 * 24 * 60 * 60 * 1e3;
11808
11850
  function colorPct(pct) {
@@ -11828,7 +11870,7 @@ function printCoverageSummary(forkPath) {
11828
11870
  if (existsSync28(file)) {
11829
11871
  try {
11830
11872
  mtimeMs = statSync5(file).mtimeMs;
11831
- summary = JSON.parse(readFileSync21(file, "utf8"));
11873
+ summary = JSON.parse(readFileSync22(file, "utf8"));
11832
11874
  } catch {
11833
11875
  problem2 = "could not read coverage-summary.json";
11834
11876
  }