ripencli 1.2.4 → 1.2.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/cli.js +51 -32
- package/package.json +6 -6
package/dist/cli.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Box, Text, render, useApp, useInput, useWindowSize } from "ink";
|
|
3
|
-
import { createRequire } from "module";
|
|
4
3
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
5
4
|
import { join } from "path";
|
|
6
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
7
5
|
import { execa } from "execa";
|
|
6
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
8
7
|
import { homedir } from "os";
|
|
9
8
|
import { exec, execSync } from "child_process";
|
|
10
9
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -106,22 +105,34 @@ function parseBaseVersion(range) {
|
|
|
106
105
|
}
|
|
107
106
|
//#endregion
|
|
108
107
|
//#region src/registry.ts
|
|
109
|
-
let
|
|
108
|
+
let tokenPromise;
|
|
110
109
|
/**
|
|
111
110
|
* Get a GitHub token from the `gh` CLI (`gh auth token`). Unauthenticated
|
|
112
111
|
* requests are limited to 60/hour per IP and are easily exhausted; an
|
|
113
112
|
* authenticated request raises the limit to 5,000/hour. Returns null when
|
|
114
|
-
* `gh` is not installed or the user is not logged in.
|
|
113
|
+
* `gh` is not installed or the user is not logged in.
|
|
114
|
+
*
|
|
115
|
+
* Spawning `gh` is slow, so the *promise* is cached (not just the resolved
|
|
116
|
+
* value): the first call kicks off one `gh` process and every later caller —
|
|
117
|
+
* including a fire-and-forget prewarm at startup — shares that same result.
|
|
118
|
+
* Call `prewarmGitHubToken()` when the app boots so the token is ready by the
|
|
119
|
+
* time the user opens a changelog.
|
|
115
120
|
*/
|
|
116
|
-
|
|
117
|
-
if (
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
121
|
+
function githubToken() {
|
|
122
|
+
if (tokenPromise) return tokenPromise;
|
|
123
|
+
tokenPromise = (async () => {
|
|
124
|
+
try {
|
|
125
|
+
const { stdout, exitCode } = await execa("gh", ["auth", "token"], { reject: false });
|
|
126
|
+
return exitCode === 0 && stdout.trim() ? stdout.trim() : null;
|
|
127
|
+
} catch {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
})();
|
|
131
|
+
return tokenPromise;
|
|
132
|
+
}
|
|
133
|
+
/** Fire-and-forget: warm the `gh auth token` cache without blocking. */
|
|
134
|
+
function prewarmGitHubToken() {
|
|
135
|
+
githubToken();
|
|
125
136
|
}
|
|
126
137
|
async function fetchVersions(packageName) {
|
|
127
138
|
try {
|
|
@@ -1032,10 +1043,11 @@ function PackageList({ packages, onToggle, onToggleMany, onSelectVersion, onView
|
|
|
1032
1043
|
if (key.pageDown) setFocusedIndex(Math.min(visibleRows.length - 1, focusedIndex + maxVisible));
|
|
1033
1044
|
if (key.tab) {
|
|
1034
1045
|
const headerIndices = groups.map((g) => g.headerVisibleIndex);
|
|
1035
|
-
|
|
1046
|
+
const nextIdx = (headerIndices.findIndex((h, i) => {
|
|
1036
1047
|
const nextHeader = headerIndices[i + 1] ?? visibleRows.length;
|
|
1037
1048
|
return focusedIndex >= h && focusedIndex < nextHeader;
|
|
1038
|
-
}) + 1) % headerIndices.length
|
|
1049
|
+
}) + 1) % headerIndices.length;
|
|
1050
|
+
setFocusedIndex(headerIndices[nextIdx]);
|
|
1039
1051
|
return;
|
|
1040
1052
|
}
|
|
1041
1053
|
const focused = visibleRows[focusedIndex];
|
|
@@ -1364,13 +1376,16 @@ function PackageGroupBox({ group, focusedIndex, collapsedScopes, scrollOffset, m
|
|
|
1364
1376
|
}),
|
|
1365
1377
|
/* @__PURE__ */ jsx(Box, {
|
|
1366
1378
|
width: 5,
|
|
1367
|
-
children:
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1379
|
+
children: (() => {
|
|
1380
|
+
const agePublishedAt = pkg.targetPublishedAt ?? pkg.latestPublishedAt;
|
|
1381
|
+
return agePublishedAt ? /* @__PURE__ */ jsx(Text, {
|
|
1382
|
+
color: Date.now() - new Date(agePublishedAt).getTime() < 864e5 ? "yellow" : "gray",
|
|
1383
|
+
children: formatAge(agePublishedAt)
|
|
1384
|
+
}) : /* @__PURE__ */ jsx(Text, {
|
|
1385
|
+
color: "gray",
|
|
1386
|
+
children: " "
|
|
1387
|
+
});
|
|
1388
|
+
})()
|
|
1374
1389
|
}),
|
|
1375
1390
|
/* @__PURE__ */ jsx(Box, {
|
|
1376
1391
|
width: 9,
|
|
@@ -1425,7 +1440,7 @@ function VersionPicker({ pkg, onSelect, onCancel }) {
|
|
|
1425
1440
|
setCursor(next);
|
|
1426
1441
|
if (next >= scroll + PAGE) setScroll(next - PAGE + 1);
|
|
1427
1442
|
}
|
|
1428
|
-
if (key.return && versions[cursor]) onSelect(versions[cursor].version);
|
|
1443
|
+
if (key.return && versions[cursor]) onSelect(versions[cursor].version, versions[cursor].date);
|
|
1429
1444
|
});
|
|
1430
1445
|
const visible = versions.slice(scroll, scroll + PAGE);
|
|
1431
1446
|
return /* @__PURE__ */ jsxs(Box, {
|
|
@@ -2443,10 +2458,11 @@ function usePackages() {
|
|
|
2443
2458
|
} : p);
|
|
2444
2459
|
});
|
|
2445
2460
|
}, []),
|
|
2446
|
-
chooseVersion: useCallback((activeIndex, version) => {
|
|
2461
|
+
chooseVersion: useCallback((activeIndex, version, publishedAt) => {
|
|
2447
2462
|
setPackages((prev) => prev.map((p, i) => i === activeIndex ? {
|
|
2448
2463
|
...p,
|
|
2449
2464
|
targetVersion: version,
|
|
2465
|
+
targetPublishedAt: publishedAt,
|
|
2450
2466
|
selected: true
|
|
2451
2467
|
} : p));
|
|
2452
2468
|
}, [])
|
|
@@ -2649,8 +2665,8 @@ function App({ project, global, showAll, version, installManager, onCancelled, o
|
|
|
2649
2665
|
padding: 1,
|
|
2650
2666
|
children: /* @__PURE__ */ jsx(VersionPicker, {
|
|
2651
2667
|
pkg: packages[activeIndex],
|
|
2652
|
-
onSelect: (v) => {
|
|
2653
|
-
chooseVersion(activeIndex, v);
|
|
2668
|
+
onSelect: (v, publishedAt) => {
|
|
2669
|
+
chooseVersion(activeIndex, v, publishedAt);
|
|
2654
2670
|
setScreen("list");
|
|
2655
2671
|
},
|
|
2656
2672
|
onCancel: () => setScreen("list")
|
|
@@ -2693,14 +2709,16 @@ function App({ project, global, showAll, version, installManager, onCancelled, o
|
|
|
2693
2709
|
] });
|
|
2694
2710
|
}
|
|
2695
2711
|
//#endregion
|
|
2712
|
+
//#region package.json
|
|
2713
|
+
var version = "1.2.5";
|
|
2714
|
+
//#endregion
|
|
2696
2715
|
//#region src/cli.tsx
|
|
2697
|
-
const { version: VERSION } = createRequire(import.meta.url)("../package.json");
|
|
2698
2716
|
const args = process.argv.slice(2);
|
|
2699
2717
|
const isGlobal = args.includes("--global") || args.includes("-g");
|
|
2700
2718
|
const showAll = args.includes("--all") || args.includes("-a");
|
|
2701
2719
|
const showHelp = args.includes("--help") || args.includes("-h");
|
|
2702
|
-
if (args.includes("--version") || args.includes("-
|
|
2703
|
-
console.log(
|
|
2720
|
+
if (args.includes("--version") || args.includes("-v")) {
|
|
2721
|
+
console.log(version);
|
|
2704
2722
|
process.exit(0);
|
|
2705
2723
|
}
|
|
2706
2724
|
if (showHelp) {
|
|
@@ -2711,8 +2729,8 @@ if (showHelp) {
|
|
|
2711
2729
|
ripen check current project
|
|
2712
2730
|
ripen -g check global packages
|
|
2713
2731
|
ripen -a show all packages, not just outdated ones
|
|
2714
|
-
ripen
|
|
2715
|
-
ripen
|
|
2732
|
+
ripen -h show this help
|
|
2733
|
+
ripen -v show version
|
|
2716
2734
|
|
|
2717
2735
|
Controls (inside TUI):
|
|
2718
2736
|
↑ ↓ navigate packages
|
|
@@ -2731,6 +2749,7 @@ if (!isGlobal && !hasPackageJson(cwd)) {
|
|
|
2731
2749
|
process.exit(1);
|
|
2732
2750
|
}
|
|
2733
2751
|
const project = getProjectInfo(cwd);
|
|
2752
|
+
prewarmGitHubToken();
|
|
2734
2753
|
const installManager = detectGlobalInstallManager();
|
|
2735
2754
|
let wasCancelled = false;
|
|
2736
2755
|
let copiedCommands = [];
|
|
@@ -2738,7 +2757,7 @@ const { waitUntilExit } = render(/* @__PURE__ */ jsx(App, {
|
|
|
2738
2757
|
project,
|
|
2739
2758
|
global: isGlobal,
|
|
2740
2759
|
showAll,
|
|
2741
|
-
version
|
|
2760
|
+
version,
|
|
2742
2761
|
installManager,
|
|
2743
2762
|
onCancelled: () => {
|
|
2744
2763
|
wasCancelled = true;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ripencli",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.5",
|
|
4
4
|
"description": "Interactive dependency updater for npm, pnpm, yarn, and bun",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -66,15 +66,15 @@
|
|
|
66
66
|
],
|
|
67
67
|
"dependencies": {
|
|
68
68
|
"execa": "9.6.1",
|
|
69
|
-
"ink": "7.0
|
|
69
|
+
"ink": "7.1.0",
|
|
70
70
|
"ink-scroll-view": "0.3.7",
|
|
71
71
|
"react": "19.2.7"
|
|
72
72
|
},
|
|
73
73
|
"devDependencies": {
|
|
74
74
|
"@types/node": "24.12.2",
|
|
75
|
-
"@types/react": "19.2.
|
|
76
|
-
"prettier": "3.
|
|
77
|
-
"tsdown": "0.22.
|
|
78
|
-
"typescript": "
|
|
75
|
+
"@types/react": "19.2.17",
|
|
76
|
+
"prettier": "3.9.4",
|
|
77
|
+
"tsdown": "0.22.4",
|
|
78
|
+
"typescript": "7.0.2"
|
|
79
79
|
}
|
|
80
80
|
}
|