@cellajs/cli 0.6.1 → 0.6.2

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
@@ -228,7 +228,7 @@ import process5 from "process";
228
228
  // package.json
229
229
  var package_default = {
230
230
  name: "@cellajs/cli",
231
- version: "0.6.1",
231
+ version: "0.6.2",
232
232
  private: false,
233
233
  license: "MIT",
234
234
  description: "CLI for managing your monorepo and upgrading it with upstream Cella.",
@@ -1436,6 +1436,129 @@ function formatAlignmentsLine(total, open) {
1436
1436
  return `alignments: ${parts.join(" \xB7 ")}`;
1437
1437
  }
1438
1438
 
1439
+ // src/utils/upstream-overrides.ts
1440
+ import { Node, Project as Project2, SyntaxKind as SyntaxKind2 } from "ts-morph";
1441
+ var LIST_KEYS = ["pinned", "ignored"];
1442
+ function resolveExpression(node, sourceFile, depth = 0) {
1443
+ if (!node || depth > 8) return node;
1444
+ if (Node.isParenthesizedExpression(node) || Node.isAsExpression(node) || Node.isSatisfiesExpression(node)) {
1445
+ return resolveExpression(node.getExpression(), sourceFile, depth + 1);
1446
+ }
1447
+ if (Node.isIdentifier(node)) {
1448
+ return resolveExpression(
1449
+ sourceFile.getVariableDeclaration(node.getText())?.getInitializer(),
1450
+ sourceFile,
1451
+ depth + 1
1452
+ );
1453
+ }
1454
+ return node;
1455
+ }
1456
+ function findConfigObject(sourceFile) {
1457
+ for (const call of sourceFile.getDescendantsOfKind(SyntaxKind2.CallExpression)) {
1458
+ if (call.getExpression().getText() !== "defineConfig") continue;
1459
+ const arg = resolveExpression(call.getArguments()[0], sourceFile);
1460
+ if (Node.isObjectLiteralExpression(arg)) return arg;
1461
+ }
1462
+ const exported = sourceFile.getExportAssignment((assignment) => !assignment.isExportEquals());
1463
+ const value = resolveExpression(exported?.getExpression(), sourceFile);
1464
+ return Node.isObjectLiteralExpression(value) ? value : void 0;
1465
+ }
1466
+ function readProperty(object, name, sourceFile) {
1467
+ for (const property of object.getProperties()) {
1468
+ if (Node.isPropertyAssignment(property)) {
1469
+ if (property.getName().replace(/^['"`]|['"`]$/g, "") !== name) continue;
1470
+ return resolveExpression(property.getInitializer(), sourceFile) ?? null;
1471
+ }
1472
+ if (Node.isShorthandPropertyAssignment(property) && property.getName() === name) {
1473
+ return resolveExpression(property.getNameNode(), sourceFile) ?? null;
1474
+ }
1475
+ }
1476
+ return void 0;
1477
+ }
1478
+ function readStringEntries(node) {
1479
+ if (!Node.isArrayLiteralExpression(node)) return null;
1480
+ const entries = [];
1481
+ for (const element of node.getElements()) {
1482
+ if (Node.isStringLiteral(element) || Node.isNoSubstitutionTemplateLiteral(element)) {
1483
+ entries.push(element.getLiteralValue());
1484
+ }
1485
+ }
1486
+ return entries;
1487
+ }
1488
+ function readPackageJsonKeys(config, sourceFile) {
1489
+ const settings = readProperty(config, "settings", sourceFile);
1490
+ if (settings === void 0) return [...DEFAULT_PACKAGE_JSON_KEYS];
1491
+ if (!settings || !Node.isObjectLiteralExpression(settings)) return null;
1492
+ const current = readProperty(settings, "packageJsonKeys", sourceFile);
1493
+ const keys = current === void 0 ? readProperty(settings, "packageJsonSync", sourceFile) : current;
1494
+ if (keys === void 0) return [...DEFAULT_PACKAGE_JSON_KEYS];
1495
+ return keys ? readStringEntries(keys) : null;
1496
+ }
1497
+ function parseOverrideLists(source) {
1498
+ try {
1499
+ const project = new Project2({ useInMemoryFileSystem: true, skipLoadingLibFiles: true });
1500
+ const sourceFile = project.createSourceFile("cella.config.ts", source);
1501
+ const config = findConfigObject(sourceFile);
1502
+ if (!config) return null;
1503
+ const lists = {
1504
+ pinned: [],
1505
+ ignored: [],
1506
+ packageJsonKeys: readPackageJsonKeys(config, sourceFile)
1507
+ };
1508
+ const overrides = readProperty(config, "overrides", sourceFile);
1509
+ if (overrides === void 0) return lists;
1510
+ if (!overrides || !Node.isObjectLiteralExpression(overrides)) return null;
1511
+ for (const key of LIST_KEYS) {
1512
+ const list = readProperty(overrides, key, sourceFile);
1513
+ if (list === void 0) continue;
1514
+ const entries = list ? readStringEntries(list) : null;
1515
+ if (!entries) return null;
1516
+ lists[key] = entries;
1517
+ }
1518
+ return lists;
1519
+ } catch {
1520
+ return null;
1521
+ }
1522
+ }
1523
+ function diffOverrideLists(base, incoming, fork) {
1524
+ const diff = (key) => {
1525
+ const baseSet = new Set(base[key].map(normalizeEntry).filter(Boolean));
1526
+ const incomingSet = new Set(incoming[key].map(normalizeEntry).filter(Boolean));
1527
+ const forkEntries = fork[key].map(normalizeEntry).filter(Boolean);
1528
+ return {
1529
+ added: [...incomingSet].filter((entry) => !baseSet.has(entry) && !isUnderAnyFolder(entry, forkEntries)),
1530
+ removed: [...baseSet].filter((entry) => !incomingSet.has(entry) && forkEntries.includes(entry))
1531
+ };
1532
+ };
1533
+ const diffKeys = () => {
1534
+ const [baseKeys, incomingKeys, forkKeys] = [base.packageJsonKeys, incoming.packageJsonKeys, fork.packageJsonKeys];
1535
+ if (!baseKeys || !incomingKeys || !forkKeys) return { added: [], removed: [] };
1536
+ return {
1537
+ added: [...new Set(incomingKeys)].filter((key) => !baseKeys.includes(key) && !forkKeys.includes(key)),
1538
+ removed: [...new Set(baseKeys)].filter((key) => !incomingKeys.includes(key) && forkKeys.includes(key))
1539
+ };
1540
+ };
1541
+ return { pinned: diff("pinned"), ignored: diff("ignored"), packageJsonKeys: diffKeys() };
1542
+ }
1543
+ async function compareUpstreamOverrides(repoPath, mergeBaseRef, incomingRef, forkConfig) {
1544
+ const [baseSource, incomingSource] = await Promise.all(
1545
+ [mergeBaseRef, incomingRef].map((ref) => git(["show", `${ref}:${CONFIG_FILE}`], repoPath, { ignoreErrors: true }))
1546
+ );
1547
+ if (baseSource === incomingSource) return void 0;
1548
+ const base = baseSource ? parseOverrideLists(baseSource) : null;
1549
+ if (!base) return { kind: "unreadable", side: "base" };
1550
+ const incoming = incomingSource ? parseOverrideLists(incomingSource) : null;
1551
+ if (!incoming) return { kind: "unreadable", side: "incoming" };
1552
+ const fork = {
1553
+ pinned: forkConfig.overrides?.pinned ?? [],
1554
+ ignored: forkConfig.overrides?.ignored ?? [],
1555
+ packageJsonKeys: forkConfig.settings.packageJsonKeys ?? DEFAULT_PACKAGE_JSON_KEYS
1556
+ };
1557
+ const changes = diffOverrideLists(base, incoming, fork);
1558
+ const count3 = Object.values(changes).reduce((n, list) => n + list.added.length + list.removed.length, 0);
1559
+ return count3 > 0 ? { kind: "changes", ...changes } : void 0;
1560
+ }
1561
+
1439
1562
  // src/utils/overrides.ts
1440
1563
  function normalizeEntry(entry) {
1441
1564
  return entry.trim().replace(/^\.\//, "").replace(/\/+$/, "");
@@ -1491,8 +1614,11 @@ async function validateOverrides(config, forkPath, upstreamRef) {
1491
1614
  }
1492
1615
  if (upstream && pinsUpstreamHas.length > 0) {
1493
1616
  const differs = await listChangedSinceRef(forkPath, upstream, pinsUpstreamHas.map(normalizeEntry));
1617
+ const upstreamSource = await git(["show", `${upstream}:${CONFIG_FILE}`], forkPath, { ignoreErrors: true });
1618
+ const upstreamPins = upstreamSource && parseOverrideLists(upstreamSource)?.pinned.map(normalizeEntry) || [];
1494
1619
  for (const entry of pinsUpstreamHas) {
1495
1620
  if (differs.some((changed) => isUnderAnyFolder(changed, [entry]))) continue;
1621
+ if (upstreamPins.includes(normalizeEntry(entry))) continue;
1496
1622
  warnings.push(`pin is identical to upstream, it only drops upstream's next change: ${entry}`);
1497
1623
  }
1498
1624
  }
@@ -1814,129 +1940,6 @@ function cliVersionMismatch(running, range) {
1814
1940
  ].join("\n");
1815
1941
  }
1816
1942
 
1817
- // src/utils/upstream-overrides.ts
1818
- import { Node, Project as Project2, SyntaxKind as SyntaxKind2 } from "ts-morph";
1819
- var LIST_KEYS = ["pinned", "ignored"];
1820
- function resolveExpression(node, sourceFile, depth = 0) {
1821
- if (!node || depth > 8) return node;
1822
- if (Node.isParenthesizedExpression(node) || Node.isAsExpression(node) || Node.isSatisfiesExpression(node)) {
1823
- return resolveExpression(node.getExpression(), sourceFile, depth + 1);
1824
- }
1825
- if (Node.isIdentifier(node)) {
1826
- return resolveExpression(
1827
- sourceFile.getVariableDeclaration(node.getText())?.getInitializer(),
1828
- sourceFile,
1829
- depth + 1
1830
- );
1831
- }
1832
- return node;
1833
- }
1834
- function findConfigObject(sourceFile) {
1835
- for (const call of sourceFile.getDescendantsOfKind(SyntaxKind2.CallExpression)) {
1836
- if (call.getExpression().getText() !== "defineConfig") continue;
1837
- const arg = resolveExpression(call.getArguments()[0], sourceFile);
1838
- if (Node.isObjectLiteralExpression(arg)) return arg;
1839
- }
1840
- const exported = sourceFile.getExportAssignment((assignment) => !assignment.isExportEquals());
1841
- const value = resolveExpression(exported?.getExpression(), sourceFile);
1842
- return Node.isObjectLiteralExpression(value) ? value : void 0;
1843
- }
1844
- function readProperty(object, name, sourceFile) {
1845
- for (const property of object.getProperties()) {
1846
- if (Node.isPropertyAssignment(property)) {
1847
- if (property.getName().replace(/^['"`]|['"`]$/g, "") !== name) continue;
1848
- return resolveExpression(property.getInitializer(), sourceFile) ?? null;
1849
- }
1850
- if (Node.isShorthandPropertyAssignment(property) && property.getName() === name) {
1851
- return resolveExpression(property.getNameNode(), sourceFile) ?? null;
1852
- }
1853
- }
1854
- return void 0;
1855
- }
1856
- function readStringEntries(node) {
1857
- if (!Node.isArrayLiteralExpression(node)) return null;
1858
- const entries = [];
1859
- for (const element of node.getElements()) {
1860
- if (Node.isStringLiteral(element) || Node.isNoSubstitutionTemplateLiteral(element)) {
1861
- entries.push(element.getLiteralValue());
1862
- }
1863
- }
1864
- return entries;
1865
- }
1866
- function readPackageJsonKeys(config, sourceFile) {
1867
- const settings = readProperty(config, "settings", sourceFile);
1868
- if (settings === void 0) return [...DEFAULT_PACKAGE_JSON_KEYS];
1869
- if (!settings || !Node.isObjectLiteralExpression(settings)) return null;
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];
1873
- return keys ? readStringEntries(keys) : null;
1874
- }
1875
- function parseOverrideLists(source) {
1876
- try {
1877
- const project = new Project2({ useInMemoryFileSystem: true, skipLoadingLibFiles: true });
1878
- const sourceFile = project.createSourceFile("cella.config.ts", source);
1879
- const config = findConfigObject(sourceFile);
1880
- if (!config) return null;
1881
- const lists = {
1882
- pinned: [],
1883
- ignored: [],
1884
- packageJsonKeys: readPackageJsonKeys(config, sourceFile)
1885
- };
1886
- const overrides = readProperty(config, "overrides", sourceFile);
1887
- if (overrides === void 0) return lists;
1888
- if (!overrides || !Node.isObjectLiteralExpression(overrides)) return null;
1889
- for (const key of LIST_KEYS) {
1890
- const list = readProperty(overrides, key, sourceFile);
1891
- if (list === void 0) continue;
1892
- const entries = list ? readStringEntries(list) : null;
1893
- if (!entries) return null;
1894
- lists[key] = entries;
1895
- }
1896
- return lists;
1897
- } catch {
1898
- return null;
1899
- }
1900
- }
1901
- function diffOverrideLists(base, incoming, fork) {
1902
- const diff = (key) => {
1903
- const baseSet = new Set(base[key].map(normalizeEntry).filter(Boolean));
1904
- const incomingSet = new Set(incoming[key].map(normalizeEntry).filter(Boolean));
1905
- const forkEntries = fork[key].map(normalizeEntry).filter(Boolean);
1906
- return {
1907
- added: [...incomingSet].filter((entry) => !baseSet.has(entry) && !isUnderAnyFolder(entry, forkEntries)),
1908
- removed: [...baseSet].filter((entry) => !incomingSet.has(entry) && forkEntries.includes(entry))
1909
- };
1910
- };
1911
- const diffKeys = () => {
1912
- const [baseKeys, incomingKeys, forkKeys] = [base.packageJsonKeys, incoming.packageJsonKeys, fork.packageJsonKeys];
1913
- if (!baseKeys || !incomingKeys || !forkKeys) return { added: [], removed: [] };
1914
- return {
1915
- added: [...new Set(incomingKeys)].filter((key) => !baseKeys.includes(key) && !forkKeys.includes(key)),
1916
- removed: [...new Set(baseKeys)].filter((key) => !incomingKeys.includes(key) && forkKeys.includes(key))
1917
- };
1918
- };
1919
- return { pinned: diff("pinned"), ignored: diff("ignored"), packageJsonKeys: diffKeys() };
1920
- }
1921
- async function compareUpstreamOverrides(repoPath, mergeBaseRef, incomingRef, forkConfig) {
1922
- const [baseSource, incomingSource] = await Promise.all(
1923
- [mergeBaseRef, incomingRef].map((ref) => git(["show", `${ref}:${CONFIG_FILE}`], repoPath, { ignoreErrors: true }))
1924
- );
1925
- if (baseSource === incomingSource) return void 0;
1926
- const base = baseSource ? parseOverrideLists(baseSource) : null;
1927
- if (!base) return { kind: "unreadable", side: "base" };
1928
- const incoming = incomingSource ? parseOverrideLists(incomingSource) : null;
1929
- if (!incoming) return { kind: "unreadable", side: "incoming" };
1930
- const fork = {
1931
- pinned: forkConfig.overrides?.pinned ?? [],
1932
- ignored: forkConfig.overrides?.ignored ?? [],
1933
- packageJsonKeys: forkConfig.settings.packageJsonKeys ?? DEFAULT_PACKAGE_JSON_KEYS
1934
- };
1935
- const changes = diffOverrideLists(base, incoming, fork);
1936
- const count3 = Object.values(changes).reduce((n, list) => n + list.added.length + list.removed.length, 0);
1937
- return count3 > 0 ? { kind: "changes", ...changes } : void 0;
1938
- }
1939
-
1940
1943
  // src/services/analyze-core.ts
1941
1944
  function isReportableIgnored(filePath) {
1942
1945
  return !isManagedFile(filePath) && !isGeneratedFile(filePath);