@kud/gh-ink 0.3.1 → 0.5.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
@@ -33,11 +33,18 @@ declare const healthGlyph: (h: Health) => string;
33
33
  declare const healthColor: (h: Health) => string;
34
34
  declare const healthLegend: [Health, string][];
35
35
 
36
+ type ExtensionTarget = {
37
+ item?: AnyItem;
38
+ ciJob?: string;
39
+ login: string;
40
+ };
36
41
  interface InboxExtension {
37
42
  id: string;
38
43
  title: string;
39
44
  key: string;
40
- body: (onExit: () => void, target?: string) => ReactNode;
45
+ hint?: string;
46
+ scope?: "item" | "global";
47
+ body: (onExit: () => void, target?: ExtensionTarget) => ReactNode;
41
48
  }
42
49
 
43
50
  type GHDetail = {
@@ -167,7 +174,10 @@ declare const runHere: (cmd: string) => void;
167
174
  declare const COLS: number;
168
175
  declare const topLevelCount: (s: Section) => number;
169
176
  declare const drillCmd: (item: AnyItem) => string | null;
170
- 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) => Action[];
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
+ extensions?: InboxExtension[];
179
+ onOpenExt?: (id: string, target: ExtensionTarget) => void;
180
+ }) => Action[];
171
181
  type CiStatusState = {
172
182
  kind: "loading";
173
183
  } | {
@@ -233,4 +243,4 @@ declare const writeCache: (key: string, data: {
233
243
  login: string;
234
244
  }) => void;
235
245
 
236
- export { type Action, ActionMenu, type AnyItem, App, COLS, type CiStatus, CiStatusLine, type CiStatusState, CommentsPanel, type CommentsPanelProps, type DetailContext, type ExplainSection, type GHDetail, type GHItem, HealthPanel, type HealthPanelProps, type InboxExtension, type JiraRow, type JiraTransition, type RepoHeader, type Section, type ShowLess, type ShowMore, type SubgroupHeader, buildActions, buildCheckoutCmd, clipboard, drillCmd, explainItem, filterByOrigin, filterByRepos, filterBySearch, fitCount, healthColor, healthDisplay, healthGlyph, healthLegend, insertRepoHeaders, itermRun, jumpToRepo, jumpToRepoPane, layoutGHItems, maxViewStart, moveCursor, openInTab, readCache, relativeTime, renderMarkdown, repoPriority, reposInSections, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, sortByRecency, sortItems, toCiStatusState, topLevelCount, truncate, useActionMenu, windowCount, withHeaders, withoutItem, writeCache };
246
+ export { type Action, ActionMenu, type AnyItem, App, COLS, type CiStatus, CiStatusLine, type CiStatusState, CommentsPanel, type CommentsPanelProps, type DetailContext, type ExplainSection, type ExtensionTarget, type GHDetail, type GHItem, HealthPanel, type HealthPanelProps, type InboxExtension, type JiraRow, type JiraTransition, type RepoHeader, type Section, type ShowLess, type ShowMore, type SubgroupHeader, buildActions, buildCheckoutCmd, clipboard, drillCmd, explainItem, filterByOrigin, filterByRepos, filterBySearch, fitCount, healthColor, healthDisplay, healthGlyph, healthLegend, insertRepoHeaders, itermRun, jumpToRepo, jumpToRepoPane, layoutGHItems, maxViewStart, moveCursor, openInTab, readCache, relativeTime, renderMarkdown, repoPriority, reposInSections, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, sortByRecency, sortItems, toCiStatusState, topLevelCount, truncate, useActionMenu, windowCount, withHeaders, withoutItem, writeCache };
package/dist/index.js CHANGED
@@ -622,6 +622,7 @@ var writeCache = (key, data) => {
622
622
  } catch {
623
623
  }
624
624
  };
625
+ var quietly = $({ quiet: true });
625
626
  var relativeTime = (iso) => {
626
627
  const diff = (Date.now() - new Date(iso).getTime()) / 1e3;
627
628
  if (diff < 3600) return `${Math.floor(diff / 60)}m`;
@@ -1064,14 +1065,14 @@ var drillLabel = (item) => {
1064
1065
  if (item.kind === "pr") return "Open PR";
1065
1066
  return "Drill in";
1066
1067
  };
1067
- var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions, onRefresh, onRemove, onOpenView) => {
1068
+ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions, onRefresh, onRemove, onOpenView, ext) => {
1068
1069
  if (item.kind === "repo-header" || item.kind === "subgroup-header" || item.kind === "show-more" || item.kind === "show-less")
1069
1070
  return [];
1070
1071
  const open = {
1071
1072
  label: "Open in browser",
1072
1073
  hint: "o",
1073
1074
  run: () => {
1074
- $`open ${item.url}`.catch(() => {
1075
+ quietly`open ${item.url}`.catch(() => {
1075
1076
  });
1076
1077
  showFlash("\u2197 Opened in browser");
1077
1078
  }
@@ -1118,7 +1119,7 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
1118
1119
  hint: "",
1119
1120
  run: () => {
1120
1121
  showFlash(`\u22EF ${label} \xB7 ${resolution}\u2026`);
1121
- void $`jira issue move ${item.key} ${state} --resolution ${resolution}`.then(() => {
1122
+ void quietly`jira issue move ${item.key} ${state} --resolution ${resolution}`.then(() => {
1122
1123
  showFlash(`\u2713 ${label} \xB7 ${resolution}`);
1123
1124
  setTimeout(() => onRefresh?.(), 1500);
1124
1125
  }).catch(() => showFlash(`\u2717 Move to ${label} failed`));
@@ -1129,7 +1130,7 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
1129
1130
  hint: "",
1130
1131
  run: () => {
1131
1132
  showFlash(`\u22EF Moving to ${label}\u2026`);
1132
- void $`jira issue move ${item.key} ${state}`.then(() => {
1133
+ void quietly`jira issue move ${item.key} ${state}`.then(() => {
1133
1134
  showFlash(`\u2713 Moved to ${label}`);
1134
1135
  setTimeout(() => onRefresh?.(), 1500);
1135
1136
  }).catch(() => showFlash(`\u2717 Move to ${label} failed`));
@@ -1210,7 +1211,7 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
1210
1211
  run: () => {
1211
1212
  onRemove?.(item);
1212
1213
  showFlash(`\u2713 Closed #${item.number}`);
1213
- void $`gh issue close ${item.number} --repo ${item.repo}`.catch(
1214
+ void quietly`gh issue close ${item.number} --repo ${item.repo}`.catch(
1214
1215
  () => {
1215
1216
  showFlash(`\u2717 Close failed \u2014 restoring #${item.number}`);
1216
1217
  onRefresh?.();
@@ -1247,7 +1248,7 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
1247
1248
  label: `Open ${jiraKey} in Jira`,
1248
1249
  hint: "t",
1249
1250
  run: () => {
1250
- $`open ${jiraBase}/${jiraKey}`.catch(() => {
1251
+ quietly`open ${jiraBase}/${jiraKey}`.catch(() => {
1251
1252
  });
1252
1253
  showFlash(`\u2197 Opened ${jiraKey} in Jira`);
1253
1254
  }
@@ -1266,10 +1267,12 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
1266
1267
  run: () => {
1267
1268
  onRemove?.(item);
1268
1269
  showFlash(`\u2713 Closed #${item.number}`);
1269
- void $`gh pr close ${item.number} --repo ${item.repo}`.catch(() => {
1270
- showFlash(`\u2717 Close failed \u2014 restoring #${item.number}`);
1271
- onRefresh?.();
1272
- });
1270
+ void quietly`gh pr close ${item.number} --repo ${item.repo}`.catch(
1271
+ () => {
1272
+ showFlash(`\u2717 Close failed \u2014 restoring #${item.number}`);
1273
+ onRefresh?.();
1274
+ }
1275
+ );
1273
1276
  }
1274
1277
  },
1275
1278
  { label: "Cancel", hint: "", run: () => {
@@ -1289,8 +1292,8 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
1289
1292
  run: () => {
1290
1293
  onRemove?.(item);
1291
1294
  showFlash(`\u2713 Closed #${item.number} and deleted ${item.branch}`);
1292
- void $`gh pr close ${item.number} --repo ${item.repo}`.then(
1293
- () => $`gh api -X DELETE ${`repos/${item.repo}/git/refs/heads/${item.branch}`}`
1295
+ void quietly`gh pr close ${item.number} --repo ${item.repo}`.then(
1296
+ () => quietly`gh api -X DELETE ${`repos/${item.repo}/git/refs/heads/${item.branch}`}`
1294
1297
  ).catch(() => {
1295
1298
  showFlash(`\u2717 Close + delete failed \u2014 restoring`);
1296
1299
  onRefresh?.();
@@ -1303,6 +1306,12 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
1303
1306
  });
1304
1307
  }
1305
1308
  }
1309
+ for (const e of itemExtensions(ext?.extensions))
1310
+ actions.push({
1311
+ label: e.title,
1312
+ hint: e.key,
1313
+ run: () => ext?.onOpenExt?.(e.id, { item, login })
1314
+ });
1306
1315
  return actions;
1307
1316
  };
1308
1317
  var agoText = (ms) => {
@@ -1521,7 +1530,7 @@ var TURN_LEGEND = [
1521
1530
  ];
1522
1531
  var HelpModal = ({
1523
1532
  workToggle,
1524
- hasCi,
1533
+ extensions,
1525
1534
  hasJira,
1526
1535
  tabHelp
1527
1536
  }) => {
@@ -1542,7 +1551,7 @@ var HelpModal = ({
1542
1551
  ["f", "filter by repo"],
1543
1552
  ["r", "refresh"],
1544
1553
  ...workToggle ? [["w", "toggle work / home"]] : [],
1545
- ...hasCi ? [["J", "Jenkins explorer"]] : [],
1554
+ ...extensionLegend(extensions),
1546
1555
  ["?", "this help"],
1547
1556
  ["q", "quit"]
1548
1557
  ];
@@ -1654,6 +1663,10 @@ var RepoPicker = ({
1654
1663
  }
1655
1664
  );
1656
1665
  };
1666
+ var extensionFor = (input, extensions) => input ? extensions?.find((e) => e.key === input) : void 0;
1667
+ var extensionHints = (extensions) => (extensions ?? []).map((e) => [e.key, e.hint ?? e.title.toLowerCase()]);
1668
+ var extensionLegend = (extensions) => (extensions ?? []).map((e) => [e.key, e.title]);
1669
+ var itemExtensions = (extensions) => (extensions ?? []).filter((e) => e.scope === "item");
1657
1670
  var BrowseScreen = ({
1658
1671
  sections,
1659
1672
  login,
@@ -1669,6 +1682,7 @@ var BrowseScreen = ({
1669
1682
  onOpenPr,
1670
1683
  onOpenIssue,
1671
1684
  onOpenExt,
1685
+ extensions,
1672
1686
  ciStatusState,
1673
1687
  ciJob,
1674
1688
  tabHelp,
@@ -1789,7 +1803,8 @@ var BrowseScreen = ({
1789
1803
  jiraTransitions,
1790
1804
  onRefresh,
1791
1805
  removeItemFromSections,
1792
- openDrillView
1806
+ openDrillView,
1807
+ { extensions, onOpenExt }
1793
1808
  );
1794
1809
  menu.open(actions);
1795
1810
  };
@@ -1889,8 +1904,13 @@ var BrowseScreen = ({
1889
1904
  if (keptIdx >= 0) setTabIdx(keptIdx);
1890
1905
  return;
1891
1906
  }
1892
- if (input === "J" && ciStatus) {
1893
- onOpenExt?.("jenkins", ciStatus.job);
1907
+ const ext = extensionFor(input, extensions);
1908
+ if (ext) {
1909
+ onOpenExt?.(ext.id, {
1910
+ item: activeItem ?? void 0,
1911
+ ciJob: ciStatus?.job,
1912
+ login
1913
+ });
1894
1914
  return;
1895
1915
  }
1896
1916
  if (!activeItem || activeItem.kind === "repo-header" || activeItem.kind === "subgroup-header")
@@ -1946,7 +1966,7 @@ var BrowseScreen = ({
1946
1966
  return;
1947
1967
  }
1948
1968
  if (input === "o") {
1949
- $`open ${activeItem.url}`.catch(() => {
1969
+ quietly`open ${activeItem.url}`.catch(() => {
1950
1970
  });
1951
1971
  const label = activeItem.kind === "jira" ? activeItem.key : `#${activeItem.number}`;
1952
1972
  showFlash(`\u2197 Opened ${label}`);
@@ -2012,7 +2032,7 @@ var BrowseScreen = ({
2012
2032
  run: () => {
2013
2033
  menu.close();
2014
2034
  showFlash(`\u22EF ${label} \xB7 ${resolution}\u2026`);
2015
- $`jira issue move ${jiraKey} ${state} --resolution ${resolution}`.then(() => {
2035
+ quietly`jira issue move ${jiraKey} ${state} --resolution ${resolution}`.then(() => {
2016
2036
  showFlash(`\u2713 ${label} \xB7 ${resolution}`);
2017
2037
  setTimeout(() => onRefresh?.(), 1500);
2018
2038
  }).catch(() => showFlash(`\u2717 Move to ${label} failed`));
@@ -2024,7 +2044,7 @@ var BrowseScreen = ({
2024
2044
  run: () => {
2025
2045
  menu.close();
2026
2046
  showFlash(`\u22EF Moving to ${label}\u2026`);
2027
- $`jira issue move ${jiraKey} ${state}`.then(() => {
2047
+ quietly`jira issue move ${jiraKey} ${state}`.then(() => {
2028
2048
  showFlash(`\u2713 Moved to ${label}`);
2029
2049
  setTimeout(() => onRefresh?.(), 1500);
2030
2050
  }).catch(() => showFlash(`\u2717 Move to ${label} failed`));
@@ -2043,7 +2063,7 @@ var BrowseScreen = ({
2043
2063
  ["/", "search"],
2044
2064
  ["f", "filter"],
2045
2065
  ["r", "refresh"],
2046
- ...ciStatus ? [["J", "jenkins"]] : [],
2066
+ ...extensionHints(extensions),
2047
2067
  ["?", "help"],
2048
2068
  ["q", "quit"]
2049
2069
  ];
@@ -2112,7 +2132,7 @@ var BrowseScreen = ({
2112
2132
  HelpModal,
2113
2133
  {
2114
2134
  workToggle,
2115
- hasCi: ciStatus != null,
2135
+ extensions,
2116
2136
  hasJira: !!jiraBase,
2117
2137
  tabHelp
2118
2138
  }
@@ -2364,7 +2384,8 @@ var App = ({
2364
2384
  target,
2365
2385
  sections: state.sections,
2366
2386
  login: state.login
2367
- })
2387
+ }),
2388
+ extensions
2368
2389
  }
2369
2390
  ),
2370
2391
  (overlay?.kind === "pr" || overlay?.kind === "issue") && detailFor?.({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kud/gh-ink",
3
- "version": "0.3.1",
3
+ "version": "0.5.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",