@kud/gh-cockpit 0.2.2 → 0.3.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.
@@ -1,34 +1,16 @@
1
1
  import { useWindowSize, Box, Text, useInput } from 'ink';
2
2
  import { Panel, colors, FooterHints, useListCursor } from '@kud/ink-ui';
3
3
  import { jsx, jsxs } from 'react/jsx-runtime';
4
- import * as gh_ink_star from '@kud/gh-ink';
5
- import { relativeTime, inboxConfig } from '@kud/gh-ink';
4
+ import { relativeTime, inboxConfig, clipboard, buildCheckoutCmd, runHere, openInTab, runInPane, runInPaneHorizontal } from '@kud/gh-ink';
5
+ export { ActionMenu, App, COLS, CiStatusLine, CommentsPanel, HealthPanel, PIN_MARK, budgetNotice, buildActions, buildCheckoutCmd, checkoutDirs, clipboard, configureInbox, drillCmd, explainGhAction, explainItem, filterByOrigin, filterByRepos, filterBySearch, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, inboxConfig, insertRepoHeaders, itermRun, jumpToRepo, jumpToRepoPane, layoutGHItems, matchesFilter, maxViewStart, moveCursor, openInTab, parsePatterns, profileOf, readCache, relativeTime, renderMarkdown, repoPriority, reposInSections, resetInboxConfig, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, signatureOf, sortByRecency, sortItems, toCiStatusState, topLevelCount, truncate, useActionMenu, whoseMove, windowCount, withHeaders, withoutItem, writeCache } from '@kud/gh-ink';
6
6
  import { mkdirSync } from 'fs';
7
7
  import { homedir } from 'os';
8
8
  import { join } from 'path';
9
- import { mergeInboxData, buildInboxQuery, buildInboxQueries, computeHealth as computeHealth$1, latestChecks, isPendingCheck, isFailCheck, isPassCheck } from '@kud/gh';
9
+ import { computeHealth as computeHealth$1, latestChecks, isPendingCheck, isFailCheck, isPassCheck } from '@kud/gh';
10
10
  export { buildInboxQueries, buildInboxQuery, mergeInboxData } from '@kud/gh';
11
11
  import { $ } from 'zx';
12
12
  import { useRef, useEffect, useState } from 'react';
13
13
 
14
- var __defProp = Object.defineProperty;
15
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
16
- var __getOwnPropNames = Object.getOwnPropertyNames;
17
- var __hasOwnProp = Object.prototype.hasOwnProperty;
18
- var __export = (target, all) => {
19
- for (var name in all)
20
- __defProp(target, name, { get: all[name], enumerable: true });
21
- };
22
- var __copyProps = (to, from, except, desc) => {
23
- if (from && typeof from === "object" || typeof from === "function") {
24
- for (let key of __getOwnPropNames(from))
25
- if (!__hasOwnProp.call(to, key) && key !== except)
26
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
27
- }
28
- return to;
29
- };
30
- var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
31
-
32
14
  // src/prompts.ts
33
15
  var registered = {};
34
16
  var registerPrompts = (forms) => {
@@ -55,19 +37,6 @@ var DrillView = ({
55
37
  /* @__PURE__ */ jsx(FooterHints, { hints })
56
38
  ] }) });
57
39
  };
58
-
59
- // src/lib.ts
60
- var lib_exports = {};
61
- __export(lib_exports, {
62
- buildInboxQueries: () => buildInboxQueries,
63
- buildInboxQuery: () => buildInboxQuery,
64
- computeHealth: () => computeHealth,
65
- mergeInboxData: () => mergeInboxData,
66
- signalPath: () => signalPath,
67
- toGHItem: () => toGHItem,
68
- withRetry: () => withRetry
69
- });
70
- __reExport(lib_exports, gh_ink_star);
71
40
  var withRetry = async (fn, attempts = 3, delayMs = 1e3) => {
72
41
  for (let i = 0; i < attempts; i++) {
73
42
  try {
@@ -91,6 +60,9 @@ var computeHealth = (node) => computeHealth$1({
91
60
  (t) => t && !t.isResolved
92
61
  ).length
93
62
  });
63
+ var viewerReacted = (n, content) => (n?.reactionGroups ?? []).some(
64
+ (g) => g?.content === content && g?.viewerHasReacted
65
+ );
94
66
  var conversationOf = (node) => {
95
67
  const events = [];
96
68
  let count = node.comments?.totalCount ?? 0;
@@ -99,7 +71,8 @@ var conversationOf = (node) => {
99
71
  events.push({
100
72
  at: c.createdAt,
101
73
  login: c.author?.login,
102
- bot: isBot(c.author)
74
+ bot: isBot(c.author),
75
+ acked: viewerReacted(c, "EYES")
103
76
  });
104
77
  for (const r of node.reviews?.nodes ?? [])
105
78
  if (r.state !== "PENDING")
@@ -119,8 +92,13 @@ var conversationOf = (node) => {
119
92
  }
120
93
  const last = events.filter((e) => e.at).sort((a, b) => a.at.localeCompare(b.at)).pop();
121
94
  const pushedAt = node.commits?.nodes?.[0]?.commit?.committedDate;
122
- if (last?.bot && pushedAt && pushedAt > last.at)
123
- return { count, lastActor: node.author?.login, lastEventAt: pushedAt };
95
+ const answeredByPush = Boolean(last?.bot && pushedAt && pushedAt > last.at);
96
+ if (answeredByPush || last?.acked)
97
+ return {
98
+ count,
99
+ lastActor: node.author?.login,
100
+ lastEventAt: answeredByPush ? pushedAt : last?.at
101
+ };
124
102
  return { count, lastActor: last?.login, lastEventAt: last?.at };
125
103
  };
126
104
  var detailOf = (node, lastEventAt) => {
@@ -167,6 +145,17 @@ var toGHItem = (node, opts = {}) => {
167
145
  ).length,
168
146
  conversation: convo.count,
169
147
  lastActor: convo.lastActor,
148
+ // 👍 on the PR BODY, and the anchor is load-bearing rather than incidental.
149
+ // Scoped to a comment this would quietly evaporate on the next bot comment,
150
+ // which is exactly backwards for something meant to persist — anchoring it
151
+ // on the PR makes it PR-scoped by construction, with no bookkeeping to get
152
+ // wrong. It also reads distinctly on GitHub itself: an eye down in the
153
+ // thread, a thumb at the top.
154
+ //
155
+ // Precedence over 👀 comes for free: the pin is read by whoseMove, which
156
+ // answers before anything derived from lastActor is consulted. Nobody pins
157
+ // by accident, so the pin wins.
158
+ pinned: viewerReacted(node, "THUMBS_UP"),
170
159
  labels: (node.labels?.nodes ?? []).map((l) => l?.name).filter((n) => typeof n === "string"),
171
160
  detail: detailOf(node, convo.lastEventAt),
172
161
  indent: opts.indent ?? false
@@ -201,7 +190,7 @@ var CopyPromptNotice = ({
201
190
  const back = useRef(onBack);
202
191
  back.current = onBack;
203
192
  useEffect(() => {
204
- (0, lib_exports.clipboard)(prompt);
193
+ clipboard(prompt);
205
194
  const timer = setTimeout(() => back.current(), 1400);
206
195
  return () => clearTimeout(timer);
207
196
  }, [prompt]);
@@ -249,16 +238,16 @@ var AiLauncher = ({
249
238
  const launch = async (a, placement) => {
250
239
  setNote(`\u22EF opening ${a.label}\u2026`);
251
240
  try {
252
- const base = await (0, lib_exports.buildCheckoutCmd)(item.repo, item.branch ?? "", login);
241
+ const base = await buildCheckoutCmd(item.repo, item.branch ?? "", login);
253
242
  const run = prompt && a.acceptsPrompt ? `${a.cmd} ${shellQuote(prompt)}` : a.cmd;
254
243
  const full = a.cmd ? `${base} && ${run}` : base;
255
244
  if (placement === "here") {
256
- (0, lib_exports.runHere)(full);
245
+ runHere(full);
257
246
  process.exit(0);
258
247
  }
259
- if (placement === "tab") await (0, lib_exports.openInTab)(full);
260
- if (placement === "vpane") await (0, lib_exports.runInPane)(full);
261
- if (placement === "hpane") await (0, lib_exports.runInPaneHorizontal)(full);
248
+ if (placement === "tab") await openInTab(full);
249
+ if (placement === "vpane") await runInPane(full);
250
+ if (placement === "hpane") await runInPaneHorizontal(full);
262
251
  setNote(`\u2197 ${a.label} launched${item.branch ? ` \xB7 ${item.branch}` : ""}`);
263
252
  setTimeout(onBack, 900);
264
253
  } catch (e) {
@@ -316,4 +305,4 @@ var AiLauncher = ({
316
305
  );
317
306
  };
318
307
 
319
- export { AiLauncher, CopyPromptNotice, DrillView, __export, __reExport, computeHealth, lib_exports, registerPrompts, seedPromptFor, signalPath, toGHItem, withRetry };
308
+ export { AiLauncher, CopyPromptNotice, DrillView, computeHealth, registerPrompts, seedPromptFor, signalPath, toGHItem, withRetry };
@@ -1,4 +1,4 @@
1
- import { AiLauncher, seedPromptFor, CopyPromptNotice } from '../chunk-E7DTQQX6.js';
1
+ import { AiLauncher, seedPromptFor, CopyPromptNotice } from '../chunk-LLKZMQJY.js';
2
2
  import { useEffect } from 'react';
3
3
  import { jsx } from 'react/jsx-runtime';
4
4
 
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import React, { ReactNode } from 'react';
2
2
  import { GHItem, RepoFilter, InboxExtension, DetailContext } from '@kud/gh-ink';
3
3
  export * from '@kud/gh-ink';
4
+ export { ActionMenu, App, COLS, CiStatusLine, CommentsPanel, HealthPanel, PIN_MARK, budgetNotice, buildActions, buildCheckoutCmd, checkoutDirs, clipboard, configureInbox, drillCmd, explainGhAction, explainItem, filterByOrigin, filterByRepos, filterBySearch, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, inboxConfig, insertRepoHeaders, itermRun, jumpToRepo, jumpToRepoPane, layoutGHItems, matchesFilter, maxViewStart, moveCursor, openInTab, parsePatterns, profileOf, readCache, relativeTime, renderMarkdown, repoPriority, reposInSections, resetInboxConfig, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, signatureOf, sortByRecency, sortItems, toCiStatusState, topLevelCount, truncate, useActionMenu, whoseMove, windowCount, withHeaders, withoutItem, writeCache } from '@kud/gh-ink';
4
5
  import { Health } from '@kud/gh';
5
6
  export { InboxSource, buildInboxQueries, buildInboxQuery, mergeInboxData } from '@kud/gh';
6
7
 
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { __export, withRetry, toGHItem, signalPath, registerPrompts, mergeInboxData, computeHealth, buildInboxQuery, buildInboxQueries, DrillView, lib_exports, AiLauncher, seedPromptFor, CopyPromptNotice, __reExport } from './chunk-E7DTQQX6.js';
2
- export { DrillView, buildInboxQueries, buildInboxQuery, computeHealth, mergeInboxData, registerPrompts, signalPath, toGHItem, withRetry } from './chunk-E7DTQQX6.js';
1
+ import { useActionMenu, buildActions, AiLauncher, seedPromptFor, CopyPromptNotice, DrillView, ActionMenu, resolveRepoPath, openInTab } from './chunk-LLKZMQJY.js';
2
+ export { ActionMenu, App, COLS, CiStatusLine, CommentsPanel, DrillView, HealthPanel, PIN_MARK, budgetNotice, buildActions, buildCheckoutCmd, buildInboxQueries, buildInboxQuery, checkoutDirs, clipboard, computeHealth, configureInbox, drillCmd, explainGhAction, explainItem, filterByOrigin, filterByRepos, filterBySearch, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, inboxConfig, insertRepoHeaders, itermRun, jumpToRepo, jumpToRepoPane, layoutGHItems, matchesFilter, maxViewStart, mergeInboxData, moveCursor, openInTab, parsePatterns, profileOf, readCache, registerPrompts, relativeTime, renderMarkdown, repoPriority, reposInSections, resetInboxConfig, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, signalPath, signatureOf, sortByRecency, sortItems, toCiStatusState, toGHItem, topLevelCount, truncate, useActionMenu, whoseMove, windowCount, withHeaders, withRetry, withoutItem, writeCache } from './chunk-LLKZMQJY.js';
3
3
  import { parsePatterns, HealthPanel, CommentsPanel, inboxConfig } from '@kud/gh-ink';
4
4
  import { $ } from 'zx';
5
5
  import { useState, useEffect } from 'react';
@@ -11,28 +11,6 @@ import { readFileSync, mkdirSync, writeFileSync } from 'fs';
11
11
  import { homedir } from 'os';
12
12
  import { join } from 'path';
13
13
 
14
- // src/index.ts
15
- var index_exports = {};
16
- __export(index_exports, {
17
- DrillView: () => DrillView,
18
- IssueView: () => IssueView,
19
- PrView: () => PrView,
20
- buildInboxQueries: () => buildInboxQueries,
21
- buildInboxQuery: () => buildInboxQuery,
22
- checkDrillFor: () => checkDrillFor,
23
- computeHealth: () => computeHealth,
24
- defineCockpit: () => defineCockpit,
25
- detailFor: () => detailFor,
26
- hasPatterns: () => hasPatterns,
27
- mergeInboxData: () => mergeInboxData,
28
- parseArgs: () => parseArgs,
29
- registerCheckDrills: () => registerCheckDrills,
30
- registerPrompts: () => registerPrompts,
31
- signalPath: () => signalPath,
32
- toGHItem: () => toGHItem,
33
- withRetry: () => withRetry
34
- });
35
-
36
14
  // src/config.ts
37
15
  var defineCockpit = (config) => config;
38
16
  var parseArgs = (argv) => {
@@ -229,7 +207,7 @@ var openInEditor = async (repoPath, file) => {
229
207
  }
230
208
  }
231
209
  const editor = process.env.EDITOR || "vi";
232
- await (0, lib_exports.openInTab)(
210
+ await openInTab(
233
211
  `cd ${repoPath} && ${editor} ${file.line ? `+${file.line} ` : ""}${file.path}`
234
212
  );
235
213
  return editor;
@@ -253,7 +231,7 @@ var FilePicker = ({
253
231
  const safeCursor = Math.min(cursor, Math.max(0, list.length - 1));
254
232
  const open = async (f) => {
255
233
  setNote(`\u22EF resolving ${repo}\u2026`);
256
- const repoPath = await (0, lib_exports.resolveRepoPath)(repo);
234
+ const repoPath = await resolveRepoPath(repo);
257
235
  if (!repoPath) {
258
236
  setNote(`\u2717 ${repo} isn't checked out locally`);
259
237
  return;
@@ -342,7 +320,7 @@ var PrView = ({
342
320
  const [files, setFiles] = useState(false);
343
321
  const [copy, setCopy] = useState(false);
344
322
  const [replying, setReplying] = useState(false);
345
- const menu = (0, lib_exports.useActionMenu)();
323
+ const menu = useActionMenu();
346
324
  const comments = useCachedResource(
347
325
  `pr-comments-${item.repo}-${item.number}`,
348
326
  () => fetchComments(item.repo, item.number, "pr")
@@ -381,7 +359,7 @@ var PrView = ({
381
359
  if (key.escape || input === "q") return onBack();
382
360
  if (input === "M") {
383
361
  menu.open([
384
- ...(0, lib_exports.buildActions)(
362
+ ...buildActions(
385
363
  item,
386
364
  login,
387
365
  () => {
@@ -505,7 +483,7 @@ var PrView = ({
505
483
  hints,
506
484
  children: [
507
485
  /* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(Tabs, { active: tab, items: tabItems }) }),
508
- menu.actions ? /* @__PURE__ */ jsx(lib_exports.ActionMenu, { item, actions: menu.actions, cursor: menu.cursor }) : tab === "health" ? /* @__PURE__ */ jsx(
486
+ menu.actions ? /* @__PURE__ */ jsx(ActionMenu, { item, actions: menu.actions, cursor: menu.cursor }) : tab === "health" ? /* @__PURE__ */ jsx(
509
487
  HealthPanel,
510
488
  {
511
489
  repo: item.repo,
@@ -622,7 +600,4 @@ var detailFor = (ctx) => ctx.kind === "pr" ? /* @__PURE__ */ jsx(
622
600
  /* @__PURE__ */ jsx(IssueView, { item: ctx.item, login: ctx.login, onBack: ctx.onBack })
623
601
  );
624
602
 
625
- // src/index.ts
626
- __reExport(index_exports, lib_exports);
627
-
628
603
  export { IssueView, PrView, checkDrillFor, defineCockpit, detailFor, hasPatterns, parseArgs, registerCheckDrills };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kud/gh-cockpit",
3
- "version": "0.2.2",
3
+ "version": "0.3.0",
4
4
  "description": "A configurable GitHub cockpit for the terminal — your PRs, reviews and issues in one Ink TUI, grouped by whose move it is.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -54,7 +54,7 @@
54
54
  },
55
55
  "dependencies": {
56
56
  "@kud/gh": "0.9.0",
57
- "@kud/gh-ink": "0.32.1",
57
+ "@kud/gh-ink": "0.32.2",
58
58
  "@kud/ink-ui": "0.14.0",
59
59
  "zx": "8.8.5"
60
60
  },