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.
Files changed (2) hide show
  1. package/dist/cli.js +51 -32
  2. 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 cachedToken;
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. Cached per process.
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
- async function githubToken() {
117
- if (cachedToken !== void 0) return cachedToken;
118
- try {
119
- const { stdout, exitCode } = await execa("gh", ["auth", "token"], { reject: false });
120
- cachedToken = exitCode === 0 && stdout.trim() ? stdout.trim() : null;
121
- } catch {
122
- cachedToken = null;
123
- }
124
- return cachedToken;
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
- setFocusedIndex(headerIndices[(headerIndices.findIndex((h, i) => {
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: pkg.latestPublishedAt ? /* @__PURE__ */ jsx(Text, {
1368
- color: Date.now() - new Date(pkg.latestPublishedAt).getTime() < 864e5 ? "yellow" : "gray",
1369
- children: formatAge(pkg.latestPublishedAt)
1370
- }) : /* @__PURE__ */ jsx(Text, {
1371
- color: "gray",
1372
- children: " "
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("-V")) {
2703
- console.log(VERSION);
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 --help show this help
2715
- ripen --version show version
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: 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.4",
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.5",
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.16",
76
- "prettier": "3.8.3",
77
- "tsdown": "0.22.2",
78
- "typescript": "6.0.3"
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
  }