@kud/gh-ink 0.7.1 → 0.8.0

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.d.ts CHANGED
@@ -177,6 +177,14 @@ declare const drillCmd: (item: AnyItem) => string | null;
177
177
  declare const buildActions: (item: AnyItem, login: string, showFlash: (msg: string) => void, jiraBase?: string, jiraKeyRe?: RegExp, jiraTransitions?: JiraTransition[], onRefresh?: () => void, onRemove?: (item: GHItem) => void, onOpenView?: (item: AnyItem) => boolean, ext?: {
178
178
  extensions?: InboxExtension[];
179
179
  onOpenExt?: (id: string, target: ExtensionTarget) => void;
180
+ /**
181
+ * A mutation landed. Drops the cached glance now and schedules the refresh,
182
+ * replacing a bare `setTimeout(onRefresh, 1500)` at each call site.
183
+ *
184
+ * Both halves matter and only one is visible: the delay lets GitHub settle,
185
+ * the drop stops the pre-action cache outliving a quit inside that window.
186
+ */
187
+ onActed?: () => void;
180
188
  }) => Action[];
181
189
  type CiStatusState = {
182
190
  kind: "loading";
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import { isPassCheck, isFailCheck, resolveThread, unresolveThread, replyToThread
5
5
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
6
6
  import { $ } from 'zx';
7
7
  import { spawn } from 'child_process';
8
- import { readFileSync, mkdirSync, writeFileSync, existsSync, readdirSync, statSync } from 'fs';
8
+ import { readFileSync, mkdirSync, writeFileSync, existsSync, readdirSync, statSync, rmSync } from 'fs';
9
9
  import { join } from 'path';
10
10
  import { homedir } from 'os';
11
11
 
@@ -604,21 +604,34 @@ var healthLegend = [
604
604
  ["merged", "Merged"],
605
605
  ["closed", "Closed"]
606
606
  ];
607
+ var CACHE_TTL_MS = 12e4;
608
+ var CACHE_VERSION = 1;
607
609
  var cacheDir = () => join(process.env.XDG_CACHE_HOME || join(homedir(), ".cache"), "ambre");
608
610
  var cacheFile = (key) => join(cacheDir(), `${key.replace(/[^a-z0-9._-]/gi, "-")}.json`);
609
611
  var readCache = (key) => {
610
612
  try {
611
613
  const raw = JSON.parse(readFileSync(cacheFile(key), "utf8"));
614
+ if (raw?.version !== CACHE_VERSION) return null;
612
615
  if (!Array.isArray(raw?.sections)) return null;
613
616
  return { sections: raw.sections, login: raw.login ?? "", at: raw.at ?? 0 };
614
617
  } catch {
615
618
  return null;
616
619
  }
617
620
  };
621
+ var isFresh = (cached, now = Date.now()) => !!cached && now - cached.at < CACHE_TTL_MS;
618
622
  var writeCache = (key, data) => {
619
623
  try {
620
624
  mkdirSync(cacheDir(), { recursive: true });
621
- writeFileSync(cacheFile(key), JSON.stringify({ ...data, at: Date.now() }));
625
+ writeFileSync(
626
+ cacheFile(key),
627
+ JSON.stringify({ version: CACHE_VERSION, ...data, at: Date.now() })
628
+ );
629
+ } catch {
630
+ }
631
+ };
632
+ var invalidateCache = (key) => {
633
+ try {
634
+ rmSync(cacheFile(key), { force: true });
622
635
  } catch {
623
636
  }
624
637
  };
@@ -1121,7 +1134,7 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
1121
1134
  showFlash(`\u22EF ${label} \xB7 ${resolution}\u2026`);
1122
1135
  void quietly`jira issue move ${item.key} ${state} --resolution ${resolution}`.then(() => {
1123
1136
  showFlash(`\u2713 ${label} \xB7 ${resolution}`);
1124
- setTimeout(() => onRefresh?.(), 1500);
1137
+ ext?.onActed?.();
1125
1138
  }).catch(() => showFlash(`\u2717 Move to ${label} failed`));
1126
1139
  }
1127
1140
  }))
@@ -1132,7 +1145,7 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
1132
1145
  showFlash(`\u22EF Moving to ${label}\u2026`);
1133
1146
  void quietly`jira issue move ${item.key} ${state}`.then(() => {
1134
1147
  showFlash(`\u2713 Moved to ${label}`);
1135
- setTimeout(() => onRefresh?.(), 1500);
1148
+ ext?.onActed?.();
1136
1149
  }).catch(() => showFlash(`\u2717 Move to ${label} failed`));
1137
1150
  }
1138
1151
  }
@@ -1673,6 +1686,7 @@ var BrowseScreen = ({
1673
1686
  jiraKeyRe,
1674
1687
  jiraTransitions,
1675
1688
  onRefresh,
1689
+ onActed,
1676
1690
  refreshing,
1677
1691
  hasPending,
1678
1692
  fetchedAt,
@@ -1807,7 +1821,7 @@ var BrowseScreen = ({
1807
1821
  onRefresh,
1808
1822
  removeItemFromSections,
1809
1823
  openDrillView,
1810
- { extensions, onOpenExt }
1824
+ { extensions, onOpenExt, onActed }
1811
1825
  );
1812
1826
  menu.open(actions);
1813
1827
  };
@@ -2037,7 +2051,7 @@ var BrowseScreen = ({
2037
2051
  showFlash(`\u22EF ${label} \xB7 ${resolution}\u2026`);
2038
2052
  quietly`jira issue move ${jiraKey} ${state} --resolution ${resolution}`.then(() => {
2039
2053
  showFlash(`\u2713 ${label} \xB7 ${resolution}`);
2040
- setTimeout(() => onRefresh?.(), 1500);
2054
+ onActed?.();
2041
2055
  }).catch(() => showFlash(`\u2717 Move to ${label} failed`));
2042
2056
  }
2043
2057
  }))
@@ -2049,7 +2063,7 @@ var BrowseScreen = ({
2049
2063
  showFlash(`\u22EF Moving to ${label}\u2026`);
2050
2064
  quietly`jira issue move ${jiraKey} ${state}`.then(() => {
2051
2065
  showFlash(`\u2713 Moved to ${label}`);
2052
- setTimeout(() => onRefresh?.(), 1500);
2066
+ onActed?.();
2053
2067
  }).catch(() => showFlash(`\u2717 Move to ${label} failed`));
2054
2068
  }
2055
2069
  }
@@ -2280,9 +2294,14 @@ var App = ({
2280
2294
  if (pending) showData(pending.sections, pending.login);
2281
2295
  else revalidate(true);
2282
2296
  };
2297
+ const onActed = () => {
2298
+ if (cacheKey) invalidateCache(cacheKey);
2299
+ setTimeout(() => applyOrRefresh(), 1500);
2300
+ };
2283
2301
  useEffect(() => {
2284
2302
  const cached = cacheKey ? readCache(cacheKey) : null;
2285
- if (cached && cached.sections.length > 0) {
2303
+ const painted = !!cached && cached.sections.length > 0;
2304
+ if (painted && cached) {
2286
2305
  displayedKey.current = signatureOf(cached.sections);
2287
2306
  setFetchedAt(cached.at);
2288
2307
  setState({
@@ -2291,7 +2310,7 @@ var App = ({
2291
2310
  login: cached.login
2292
2311
  });
2293
2312
  }
2294
- revalidate();
2313
+ if (!painted || !isFresh(cached)) revalidate();
2295
2314
  }, []);
2296
2315
  useEffect(() => {
2297
2316
  if (!hasCiStatus || !ciFetcher) return;
@@ -2358,6 +2377,7 @@ var App = ({
2358
2377
  jiraKeyRe,
2359
2378
  jiraTransitions,
2360
2379
  onRefresh: applyOrRefresh,
2380
+ onActed,
2361
2381
  refreshing,
2362
2382
  hasPending: pending !== null,
2363
2383
  fetchedAt,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kud/gh-ink",
3
- "version": "0.7.1",
3
+ "version": "0.8.0",
4
4
  "description": "Ink components for rendering GitHub PR review comments and health — controlled, presentation-only, built on @kud/ink-ui and fed by @kud/gh.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -48,7 +48,7 @@
48
48
  "react": ">=19"
49
49
  },
50
50
  "dependencies": {
51
- "@kud/gh": "0.5.0",
51
+ "@kud/gh": "0.5.1",
52
52
  "@kud/ink-ui": "0.14.0",
53
53
  "zx": "8.8.5"
54
54
  },