ripencli 0.2.5 → 0.2.7
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/README.md +14 -0
- package/dist/cli.js +243 -87
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
- **Global packages** — check and update global installs across all* package managers
|
|
15
15
|
- **Self-update** — notifies you when a new version of ripen is available
|
|
16
16
|
- **Major bump warnings** — highlights potentially breaking updates
|
|
17
|
+
- **Scope grouping** — optionally group scoped packages (e.g. `@heroui/*`) together
|
|
18
|
+
- **Frequency sorting** — packages you update often can be surfaced to the top
|
|
17
19
|
|
|
18
20
|
## Install
|
|
19
21
|
|
|
@@ -49,6 +51,7 @@ ripen --help
|
|
|
49
51
|
| `v` | Pick specific version |
|
|
50
52
|
| `c` | View changelog / release notes |
|
|
51
53
|
| `enter` | Update selected packages |
|
|
54
|
+
| `s` | Open settings |
|
|
52
55
|
| `esc` | Cancel / go back |
|
|
53
56
|
|
|
54
57
|
## How it works
|
|
@@ -60,6 +63,17 @@ ripen --help
|
|
|
60
63
|
5. Press `c` to see GitHub release notes between your current and target version
|
|
61
64
|
6. Select the ones you want and press enter — ripen runs the update commands for you
|
|
62
65
|
|
|
66
|
+
## Settings
|
|
67
|
+
|
|
68
|
+
Press `s` to open the settings screen. Settings are persisted at `~/.config/ripen/config.json`.
|
|
69
|
+
|
|
70
|
+
| Setting | Default | Description |
|
|
71
|
+
| ---------------------------- | ------- | ------------------------------------------------------------ |
|
|
72
|
+
| Sort by update frequency | Off | Packages you update often appear at the top |
|
|
73
|
+
| Enable scope grouping | Off | Group scoped packages under their scope prefix |
|
|
74
|
+
| Show grouped scopes on top | Off | Grouped scopes appear before ungrouped packages |
|
|
75
|
+
| Grouped scopes | — | List of scopes to group (e.g. `@heroui`, `@radix-ui`) |
|
|
76
|
+
|
|
63
77
|
When using `ripen -g`, all available package managers (npm, pnpm, yarn) are checked in parallel so you see every global package in one place. Bun is not included in global checking because it doesn't provide a JSON output for its outdated command.
|
|
64
78
|
|
|
65
79
|
## License
|
package/dist/cli.js
CHANGED
|
@@ -522,16 +522,12 @@ async function updatePackages(manager, packages, cwd, global = false, onLine) {
|
|
|
522
522
|
}
|
|
523
523
|
//#endregion
|
|
524
524
|
//#region src/config.ts
|
|
525
|
-
const DEFAULT_UNGROUP_SCOPES = ["@types", "@react-types"];
|
|
526
525
|
const DEFAULT_CONFIG = {
|
|
527
|
-
groupByScope:
|
|
528
|
-
|
|
529
|
-
|
|
526
|
+
groupByScope: false,
|
|
527
|
+
groupScopes: [],
|
|
528
|
+
groupsOnTop: false,
|
|
529
|
+
frequencySort: false
|
|
530
530
|
};
|
|
531
|
-
/** Compute the effective ungroup scopes list: (defaults - removedDefaults) + addedScopes */
|
|
532
|
-
function getEffectiveUngroupScopes(config) {
|
|
533
|
-
return [...DEFAULT_UNGROUP_SCOPES.filter((s) => !config.removedDefaults.includes(s)), ...config.addedScopes];
|
|
534
|
-
}
|
|
535
531
|
const CONFIG_DIR = join(homedir(), ".config", "ripen");
|
|
536
532
|
const CONFIG_PATH = join(CONFIG_DIR, "config.json");
|
|
537
533
|
function loadConfig() {
|
|
@@ -552,6 +548,23 @@ function saveConfig(config) {
|
|
|
552
548
|
writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
553
549
|
} catch {}
|
|
554
550
|
}
|
|
551
|
+
const FREQUENCY_PATH = join(CONFIG_DIR, "frequency.json");
|
|
552
|
+
function loadFrequency() {
|
|
553
|
+
try {
|
|
554
|
+
const raw = readFileSync(FREQUENCY_PATH, "utf-8");
|
|
555
|
+
return JSON.parse(raw);
|
|
556
|
+
} catch {
|
|
557
|
+
return {};
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
function incrementFrequency(packageNames) {
|
|
561
|
+
try {
|
|
562
|
+
const freq = loadFrequency();
|
|
563
|
+
for (const name of packageNames) freq[name] = (freq[name] ?? 0) + 1;
|
|
564
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
565
|
+
writeFileSync(FREQUENCY_PATH, JSON.stringify(freq, null, 2) + "\n", "utf-8");
|
|
566
|
+
} catch {}
|
|
567
|
+
}
|
|
555
568
|
//#endregion
|
|
556
569
|
//#region src/ui/PackageList.tsx
|
|
557
570
|
const TYPE_COLORS = {
|
|
@@ -574,7 +587,7 @@ const GROUP_CHROME = 5;
|
|
|
574
587
|
function getScope(name) {
|
|
575
588
|
return name.match(/^(@[^/]+)\//)?.[1] ?? null;
|
|
576
589
|
}
|
|
577
|
-
function buildDisplayRows(packages, groupByScope,
|
|
590
|
+
function buildDisplayRows(packages, groupByScope = false, groupScopes = [], groupsOnTop = false, frequencySort = false, frequency = {}) {
|
|
578
591
|
const grouped = /* @__PURE__ */ new Map();
|
|
579
592
|
packages.forEach((pkg, i) => {
|
|
580
593
|
if (!grouped.has(pkg.type)) grouped.set(pkg.type, []);
|
|
@@ -583,6 +596,12 @@ function buildDisplayRows(packages, groupByScope, ungroupScopes = []) {
|
|
|
583
596
|
index: i
|
|
584
597
|
});
|
|
585
598
|
});
|
|
599
|
+
const freqSort = (a, b) => {
|
|
600
|
+
const fa = frequency[a.pkg.name] ?? 0;
|
|
601
|
+
const fb = frequency[b.pkg.name] ?? 0;
|
|
602
|
+
if (fb !== fa) return fb - fa;
|
|
603
|
+
return a.pkg.name.localeCompare(b.pkg.name);
|
|
604
|
+
};
|
|
586
605
|
const rows = [];
|
|
587
606
|
for (const type of GROUP_ORDER) {
|
|
588
607
|
const items = grouped.get(type);
|
|
@@ -594,54 +613,105 @@ function buildDisplayRows(packages, groupByScope, ungroupScopes = []) {
|
|
|
594
613
|
label: GROUP_LABELS[type] ?? type,
|
|
595
614
|
packages: allPkgs
|
|
596
615
|
});
|
|
597
|
-
if (groupByScope) {
|
|
616
|
+
if (groupByScope && groupScopes.length > 0) {
|
|
598
617
|
const scopeMap = /* @__PURE__ */ new Map();
|
|
599
|
-
const
|
|
618
|
+
const ungrouped = [];
|
|
600
619
|
for (const item of items) {
|
|
601
620
|
const scope = getScope(item.pkg.name);
|
|
602
|
-
if (scope &&
|
|
621
|
+
if (scope && groupScopes.includes(scope)) {
|
|
603
622
|
if (!scopeMap.has(scope)) scopeMap.set(scope, []);
|
|
604
623
|
scopeMap.get(scope).push(item);
|
|
605
|
-
} else
|
|
624
|
+
} else ungrouped.push(item);
|
|
606
625
|
}
|
|
607
|
-
const
|
|
608
|
-
for (const
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
626
|
+
const scopeGroups = [];
|
|
627
|
+
for (const [scope, scopeItems] of scopeMap) if (scopeItems.length >= 2) scopeGroups.push({
|
|
628
|
+
scope,
|
|
629
|
+
items: scopeItems
|
|
630
|
+
});
|
|
631
|
+
else ungrouped.push(...scopeItems);
|
|
632
|
+
if (frequencySort) scopeGroups.sort((a, b) => {
|
|
633
|
+
const maxA = Math.max(...a.items.map((i) => frequency[i.pkg.name] ?? 0));
|
|
634
|
+
const maxB = Math.max(...b.items.map((i) => frequency[i.pkg.name] ?? 0));
|
|
635
|
+
if (maxB !== maxA) return maxB - maxA;
|
|
636
|
+
return a.scope.localeCompare(b.scope);
|
|
637
|
+
});
|
|
638
|
+
else scopeGroups.sort((a, b) => a.scope.localeCompare(b.scope));
|
|
639
|
+
const emitScopeGroups = () => {
|
|
640
|
+
for (const { scope, items: scopeItems } of scopeGroups) {
|
|
641
|
+
if (frequencySort) scopeItems.sort(freqSort);
|
|
642
|
+
const scopeKey = `${type}::${scope}`;
|
|
643
|
+
rows.push({
|
|
644
|
+
kind: "scope-header",
|
|
645
|
+
groupType: type,
|
|
646
|
+
scope,
|
|
647
|
+
packageIndices: scopeItems.map((si) => si.index),
|
|
648
|
+
packages: scopeItems.map((si) => si.pkg)
|
|
649
|
+
});
|
|
650
|
+
for (const si of scopeItems) rows.push({
|
|
651
|
+
kind: "package",
|
|
652
|
+
pkg: si.pkg,
|
|
653
|
+
packageIndex: si.index,
|
|
654
|
+
indented: true,
|
|
655
|
+
scopeKey
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
};
|
|
659
|
+
const emitUngrouped = () => {
|
|
660
|
+
if (frequencySort) ungrouped.sort(freqSort);
|
|
661
|
+
for (const item of ungrouped) rows.push({
|
|
631
662
|
kind: "package",
|
|
632
663
|
pkg: item.pkg,
|
|
633
664
|
packageIndex: item.index,
|
|
634
665
|
indented: false,
|
|
635
666
|
scopeKey: null
|
|
636
667
|
});
|
|
668
|
+
};
|
|
669
|
+
if (groupsOnTop || frequencySort) {
|
|
670
|
+
emitScopeGroups();
|
|
671
|
+
emitUngrouped();
|
|
672
|
+
} else {
|
|
673
|
+
const emittedScopes = /* @__PURE__ */ new Set();
|
|
674
|
+
for (const item of items) {
|
|
675
|
+
const scope = getScope(item.pkg.name);
|
|
676
|
+
const group = scope ? scopeGroups.find((g) => g.scope === scope) : void 0;
|
|
677
|
+
if (group) {
|
|
678
|
+
if (!emittedScopes.has(scope)) {
|
|
679
|
+
emittedScopes.add(scope);
|
|
680
|
+
const scopeKey = `${type}::${scope}`;
|
|
681
|
+
rows.push({
|
|
682
|
+
kind: "scope-header",
|
|
683
|
+
groupType: type,
|
|
684
|
+
scope,
|
|
685
|
+
packageIndices: group.items.map((si) => si.index),
|
|
686
|
+
packages: group.items.map((si) => si.pkg)
|
|
687
|
+
});
|
|
688
|
+
for (const si of group.items) rows.push({
|
|
689
|
+
kind: "package",
|
|
690
|
+
pkg: si.pkg,
|
|
691
|
+
packageIndex: si.index,
|
|
692
|
+
indented: true,
|
|
693
|
+
scopeKey
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
} else rows.push({
|
|
697
|
+
kind: "package",
|
|
698
|
+
pkg: item.pkg,
|
|
699
|
+
packageIndex: item.index,
|
|
700
|
+
indented: false,
|
|
701
|
+
scopeKey: null
|
|
702
|
+
});
|
|
703
|
+
}
|
|
637
704
|
}
|
|
638
|
-
} else
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
705
|
+
} else {
|
|
706
|
+
const sorted = frequencySort ? [...items].sort(freqSort) : items;
|
|
707
|
+
for (const item of sorted) rows.push({
|
|
708
|
+
kind: "package",
|
|
709
|
+
pkg: item.pkg,
|
|
710
|
+
packageIndex: item.index,
|
|
711
|
+
indented: false,
|
|
712
|
+
scopeKey: null
|
|
713
|
+
});
|
|
714
|
+
}
|
|
645
715
|
}
|
|
646
716
|
return rows;
|
|
647
717
|
}
|
|
@@ -691,12 +761,15 @@ function computeMaxPerGroup(terminalRows, groupCount) {
|
|
|
691
761
|
const perGroup = Math.floor(available / groupCount);
|
|
692
762
|
return Math.max(3, perGroup);
|
|
693
763
|
}
|
|
694
|
-
function PackageList({ packages, onToggle, onToggleGroup, onToggleMany, onSelectVersion, onViewChangelog, onConfirm, onOpenSettings, groupByScope,
|
|
764
|
+
function PackageList({ packages, onToggle, onToggleGroup, onToggleMany, onSelectVersion, onViewChangelog, onConfirm, onOpenSettings, groupByScope = false, groupScopes, groupsOnTop = false, frequencySort = false, frequency = {}, isActive = true }) {
|
|
695
765
|
const [focusedIndex, setFocusedIndex] = useState(0);
|
|
696
|
-
const allRows = useMemo(() => buildDisplayRows(packages, groupByScope,
|
|
766
|
+
const allRows = useMemo(() => buildDisplayRows(packages, groupByScope, groupScopes, groupsOnTop, frequencySort, frequency), [
|
|
697
767
|
packages,
|
|
698
768
|
groupByScope,
|
|
699
|
-
|
|
769
|
+
groupScopes,
|
|
770
|
+
groupsOnTop,
|
|
771
|
+
frequencySort,
|
|
772
|
+
frequency
|
|
700
773
|
]);
|
|
701
774
|
const allScopeKeys = useMemo(() => {
|
|
702
775
|
const keys = /* @__PURE__ */ new Set();
|
|
@@ -1625,11 +1698,13 @@ function UpdateResults({ results, onDone }) {
|
|
|
1625
1698
|
function Settings({ config, onConfigChange, onClose }) {
|
|
1626
1699
|
const [inputMode, setInputMode] = useState(false);
|
|
1627
1700
|
const [inputValue, setInputValue] = useState("");
|
|
1628
|
-
const
|
|
1701
|
+
const scopes = config.groupScopes;
|
|
1629
1702
|
const rows = [
|
|
1630
|
-
{ type: "toggle" },
|
|
1703
|
+
{ type: "toggle-frequency" },
|
|
1704
|
+
{ type: "toggle-group" },
|
|
1705
|
+
{ type: "toggle-groups-top" },
|
|
1631
1706
|
{ type: "list-header" },
|
|
1632
|
-
...
|
|
1707
|
+
...scopes.map((_, i) => ({
|
|
1633
1708
|
type: "list-item",
|
|
1634
1709
|
listItemIndex: i
|
|
1635
1710
|
}))
|
|
@@ -1638,24 +1713,16 @@ function Settings({ config, onConfigChange, onClose }) {
|
|
|
1638
1713
|
const currentRow = rows[flatCursor];
|
|
1639
1714
|
const addScope = (value) => {
|
|
1640
1715
|
const scope = value.startsWith("@") ? value : `@${value}`;
|
|
1641
|
-
if (
|
|
1642
|
-
|
|
1643
|
-
...config,
|
|
1644
|
-
removedDefaults: config.removedDefaults.filter((s) => s !== scope)
|
|
1645
|
-
});
|
|
1646
|
-
else onConfigChange({
|
|
1716
|
+
if (scopes.includes(scope)) return;
|
|
1717
|
+
onConfigChange({
|
|
1647
1718
|
...config,
|
|
1648
|
-
|
|
1719
|
+
groupScopes: [...scopes, scope]
|
|
1649
1720
|
});
|
|
1650
1721
|
};
|
|
1651
1722
|
const removeScope = (scope) => {
|
|
1652
|
-
|
|
1723
|
+
onConfigChange({
|
|
1653
1724
|
...config,
|
|
1654
|
-
|
|
1655
|
-
});
|
|
1656
|
-
else onConfigChange({
|
|
1657
|
-
...config,
|
|
1658
|
-
addedScopes: config.addedScopes.filter((s) => s !== scope)
|
|
1725
|
+
groupScopes: scopes.filter((s) => s !== scope)
|
|
1659
1726
|
});
|
|
1660
1727
|
};
|
|
1661
1728
|
useInput((input, key) => {
|
|
@@ -1682,10 +1749,18 @@ function Settings({ config, onConfigChange, onClose }) {
|
|
|
1682
1749
|
if (key.upArrow) setFlatCursor((c) => Math.max(0, c - 1));
|
|
1683
1750
|
if (key.downArrow) setFlatCursor((c) => Math.min(rows.length - 1, c + 1));
|
|
1684
1751
|
if (input === " " || key.return) {
|
|
1685
|
-
if (currentRow?.type === "toggle") onConfigChange({
|
|
1752
|
+
if (currentRow?.type === "toggle-frequency") onConfigChange({
|
|
1753
|
+
...config,
|
|
1754
|
+
frequencySort: !config.frequencySort
|
|
1755
|
+
});
|
|
1756
|
+
else if (currentRow?.type === "toggle-group") onConfigChange({
|
|
1686
1757
|
...config,
|
|
1687
1758
|
groupByScope: !config.groupByScope
|
|
1688
1759
|
});
|
|
1760
|
+
else if (currentRow?.type === "toggle-groups-top") onConfigChange({
|
|
1761
|
+
...config,
|
|
1762
|
+
groupsOnTop: !config.groupsOnTop
|
|
1763
|
+
});
|
|
1689
1764
|
else if (currentRow?.type === "list-header") {
|
|
1690
1765
|
setInputMode(true);
|
|
1691
1766
|
setInputValue("");
|
|
@@ -1696,14 +1771,16 @@ function Settings({ config, onConfigChange, onClose }) {
|
|
|
1696
1771
|
setInputValue("");
|
|
1697
1772
|
}
|
|
1698
1773
|
if ((key.backspace || key.delete) && currentRow?.type === "list-item" && currentRow.listItemIndex !== void 0) {
|
|
1699
|
-
const scope =
|
|
1774
|
+
const scope = scopes[currentRow.listItemIndex];
|
|
1700
1775
|
removeScope(scope);
|
|
1701
1776
|
if (flatCursor >= rows.length - 1) setFlatCursor(Math.max(0, flatCursor - 1));
|
|
1702
1777
|
}
|
|
1703
1778
|
if (key.escape || input === "s") onClose();
|
|
1704
1779
|
});
|
|
1705
|
-
const
|
|
1706
|
-
const
|
|
1780
|
+
const freqToggleFocused = currentRow?.type === "toggle-frequency";
|
|
1781
|
+
const groupToggleFocused = currentRow?.type === "toggle-group";
|
|
1782
|
+
const groupsTopFocused = currentRow?.type === "toggle-groups-top";
|
|
1783
|
+
const listHeaderFocused = currentRow?.type === "list-header";
|
|
1707
1784
|
return /* @__PURE__ */ jsxs(Box, {
|
|
1708
1785
|
flexDirection: "column",
|
|
1709
1786
|
children: [
|
|
@@ -1731,7 +1808,39 @@ function Settings({ config, onConfigChange, onClose }) {
|
|
|
1731
1808
|
children: [
|
|
1732
1809
|
/* @__PURE__ */ jsx(Text, {
|
|
1733
1810
|
color: "greenBright",
|
|
1734
|
-
children:
|
|
1811
|
+
children: freqToggleFocused ? ">" : " "
|
|
1812
|
+
}),
|
|
1813
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
1814
|
+
color: config.frequencySort ? "greenBright" : "gray",
|
|
1815
|
+
children: [
|
|
1816
|
+
"[",
|
|
1817
|
+
config.frequencySort ? "x" : " ",
|
|
1818
|
+
"]"
|
|
1819
|
+
]
|
|
1820
|
+
}),
|
|
1821
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1822
|
+
bold: freqToggleFocused,
|
|
1823
|
+
color: freqToggleFocused ? "whiteBright" : "white",
|
|
1824
|
+
children: "Sort by update frequency"
|
|
1825
|
+
})
|
|
1826
|
+
]
|
|
1827
|
+
}), /* @__PURE__ */ jsx(Box, {
|
|
1828
|
+
marginLeft: 6,
|
|
1829
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
1830
|
+
color: "gray",
|
|
1831
|
+
children: "Packages you update often appear at the top"
|
|
1832
|
+
})
|
|
1833
|
+
})]
|
|
1834
|
+
}),
|
|
1835
|
+
/* @__PURE__ */ jsxs(Box, {
|
|
1836
|
+
flexDirection: "column",
|
|
1837
|
+
marginBottom: 1,
|
|
1838
|
+
children: [/* @__PURE__ */ jsxs(Box, {
|
|
1839
|
+
gap: 1,
|
|
1840
|
+
children: [
|
|
1841
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1842
|
+
color: "greenBright",
|
|
1843
|
+
children: groupToggleFocused ? ">" : " "
|
|
1735
1844
|
}),
|
|
1736
1845
|
/* @__PURE__ */ jsxs(Text, {
|
|
1737
1846
|
color: config.groupByScope ? "greenBright" : "gray",
|
|
@@ -1742,16 +1851,52 @@ function Settings({ config, onConfigChange, onClose }) {
|
|
|
1742
1851
|
]
|
|
1743
1852
|
}),
|
|
1744
1853
|
/* @__PURE__ */ jsx(Text, {
|
|
1745
|
-
bold:
|
|
1746
|
-
color:
|
|
1747
|
-
children: "
|
|
1854
|
+
bold: groupToggleFocused,
|
|
1855
|
+
color: groupToggleFocused ? "whiteBright" : "white",
|
|
1856
|
+
children: "Enable scope grouping"
|
|
1748
1857
|
})
|
|
1749
1858
|
]
|
|
1750
1859
|
}), /* @__PURE__ */ jsx(Box, {
|
|
1751
1860
|
marginLeft: 6,
|
|
1752
1861
|
children: /* @__PURE__ */ jsx(Text, {
|
|
1753
1862
|
color: "gray",
|
|
1754
|
-
children: "
|
|
1863
|
+
children: "Group scoped packages listed below under their scope prefix"
|
|
1864
|
+
})
|
|
1865
|
+
})]
|
|
1866
|
+
}),
|
|
1867
|
+
/* @__PURE__ */ jsxs(Box, {
|
|
1868
|
+
flexDirection: "column",
|
|
1869
|
+
marginBottom: 1,
|
|
1870
|
+
children: [/* @__PURE__ */ jsxs(Box, {
|
|
1871
|
+
gap: 1,
|
|
1872
|
+
children: [
|
|
1873
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1874
|
+
dimColor: !config.groupByScope,
|
|
1875
|
+
color: "greenBright",
|
|
1876
|
+
children: groupsTopFocused ? ">" : " "
|
|
1877
|
+
}),
|
|
1878
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
1879
|
+
dimColor: !config.groupByScope,
|
|
1880
|
+
color: config.groupsOnTop && config.groupByScope ? "greenBright" : "gray",
|
|
1881
|
+
children: [
|
|
1882
|
+
"[",
|
|
1883
|
+
config.groupsOnTop ? "x" : " ",
|
|
1884
|
+
"]"
|
|
1885
|
+
]
|
|
1886
|
+
}),
|
|
1887
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1888
|
+
dimColor: !config.groupByScope,
|
|
1889
|
+
bold: groupsTopFocused,
|
|
1890
|
+
color: !config.groupByScope ? "gray" : groupsTopFocused ? "whiteBright" : "white",
|
|
1891
|
+
children: "Show grouped scopes on top"
|
|
1892
|
+
})
|
|
1893
|
+
]
|
|
1894
|
+
}), /* @__PURE__ */ jsx(Box, {
|
|
1895
|
+
marginLeft: 6,
|
|
1896
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
1897
|
+
dimColor: !config.groupByScope,
|
|
1898
|
+
color: "gray",
|
|
1899
|
+
children: "Grouped scope packages appear before ungrouped ones"
|
|
1755
1900
|
})
|
|
1756
1901
|
})]
|
|
1757
1902
|
}),
|
|
@@ -1765,43 +1910,44 @@ function Settings({ config, onConfigChange, onClose }) {
|
|
|
1765
1910
|
children: [/* @__PURE__ */ jsxs(Box, {
|
|
1766
1911
|
gap: 1,
|
|
1767
1912
|
children: [/* @__PURE__ */ jsx(Text, {
|
|
1913
|
+
dimColor: !config.groupByScope,
|
|
1768
1914
|
color: "greenBright",
|
|
1769
1915
|
children: listHeaderFocused ? ">" : " "
|
|
1770
1916
|
}), /* @__PURE__ */ jsx(Text, {
|
|
1917
|
+
dimColor: !config.groupByScope,
|
|
1771
1918
|
bold: listHeaderFocused,
|
|
1772
|
-
color: listHeaderFocused ? "whiteBright" : "white",
|
|
1773
|
-
children: "
|
|
1919
|
+
color: !config.groupByScope ? "gray" : listHeaderFocused ? "whiteBright" : "white",
|
|
1920
|
+
children: "Grouped scopes"
|
|
1774
1921
|
})]
|
|
1775
1922
|
}), /* @__PURE__ */ jsx(Box, {
|
|
1776
1923
|
marginLeft: 4,
|
|
1777
1924
|
children: /* @__PURE__ */ jsx(Text, {
|
|
1925
|
+
dimColor: !config.groupByScope,
|
|
1778
1926
|
color: "gray",
|
|
1779
|
-
children: "
|
|
1927
|
+
children: "Scoped packages (@scope/*) listed here will be sub-grouped together"
|
|
1780
1928
|
})
|
|
1781
1929
|
})]
|
|
1782
1930
|
}),
|
|
1783
|
-
|
|
1784
|
-
const itemFocused = flatCursor ===
|
|
1785
|
-
const isDefault = DEFAULT_UNGROUP_SCOPES.includes(scope);
|
|
1931
|
+
scopes.map((scope, i) => {
|
|
1932
|
+
const itemFocused = flatCursor === 4 + i;
|
|
1786
1933
|
return /* @__PURE__ */ jsxs(Box, {
|
|
1787
1934
|
marginLeft: 4,
|
|
1788
1935
|
gap: 1,
|
|
1789
1936
|
children: [
|
|
1790
1937
|
/* @__PURE__ */ jsx(Text, {
|
|
1938
|
+
dimColor: !config.groupByScope,
|
|
1791
1939
|
color: "greenBright",
|
|
1792
1940
|
children: itemFocused ? ">" : " "
|
|
1793
1941
|
}),
|
|
1794
1942
|
/* @__PURE__ */ jsx(Text, {
|
|
1795
|
-
|
|
1943
|
+
dimColor: !config.groupByScope,
|
|
1944
|
+
color: !config.groupByScope ? "gray" : itemFocused ? "whiteBright" : "white",
|
|
1796
1945
|
children: scope
|
|
1797
1946
|
}),
|
|
1798
|
-
|
|
1947
|
+
itemFocused && /* @__PURE__ */ jsxs(Text, {
|
|
1948
|
+
dimColor: !config.groupByScope,
|
|
1799
1949
|
color: "gray",
|
|
1800
|
-
children: "
|
|
1801
|
-
}),
|
|
1802
|
-
itemFocused && /* @__PURE__ */ jsx(Text, {
|
|
1803
|
-
color: "gray",
|
|
1804
|
-
children: " delete to remove"
|
|
1950
|
+
children: [" ", "delete to remove"]
|
|
1805
1951
|
})
|
|
1806
1952
|
]
|
|
1807
1953
|
}, scope);
|
|
@@ -1962,6 +2108,7 @@ function App({ project, global, version, installManager }) {
|
|
|
1962
2108
|
const [selfUpdateError, setSelfUpdateError] = useState(null);
|
|
1963
2109
|
const [selfUpdating, setSelfUpdating] = useState(false);
|
|
1964
2110
|
const [config, setConfig] = useState(() => loadConfig());
|
|
2111
|
+
const [frequency, setFrequency] = useState(() => loadFrequency());
|
|
1965
2112
|
const [packages, setPackages] = useState([]);
|
|
1966
2113
|
const [activeIndex, setActiveIndex] = useState(0);
|
|
1967
2114
|
const [results, setResults] = useState([]);
|
|
@@ -2094,8 +2241,14 @@ function App({ project, global, version, installManager }) {
|
|
|
2094
2241
|
const onLine = (line) => {
|
|
2095
2242
|
setOutputLines((prev) => [...prev.slice(-(MAX_TERMINAL_LINES - 1)), line]);
|
|
2096
2243
|
};
|
|
2097
|
-
|
|
2244
|
+
const res = await updatePackages(project.manager, selected, project.cwd, global, onLine);
|
|
2245
|
+
setResults(res);
|
|
2098
2246
|
setScreen("results");
|
|
2247
|
+
const successNames = res.filter((r) => r.success).map((r) => r.name);
|
|
2248
|
+
if (successNames.length > 0) {
|
|
2249
|
+
incrementFrequency(successNames);
|
|
2250
|
+
setFrequency(loadFrequency());
|
|
2251
|
+
}
|
|
2099
2252
|
};
|
|
2100
2253
|
if (screen === "self-update-check") return /* @__PURE__ */ jsxs(Box, {
|
|
2101
2254
|
flexDirection: "column",
|
|
@@ -2313,7 +2466,10 @@ function App({ project, global, version, installManager }) {
|
|
|
2313
2466
|
onConfirm: handleConfirm,
|
|
2314
2467
|
onOpenSettings: () => setScreen("settings"),
|
|
2315
2468
|
groupByScope: config.groupByScope,
|
|
2316
|
-
|
|
2469
|
+
groupScopes: config.groupScopes,
|
|
2470
|
+
groupsOnTop: config.groupsOnTop,
|
|
2471
|
+
frequencySort: config.frequencySort,
|
|
2472
|
+
frequency,
|
|
2317
2473
|
isActive: isListActive
|
|
2318
2474
|
})
|
|
2319
2475
|
})
|