@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 +127 -124
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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.
|
|
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);
|